Pourquoi devez-vous spécifier le type de données lors de la déclaration de variables?

41

Dans la plupart des langues de codage (si pas toutes), vous devez déclarer des variables. Par exemple en C # s'il s'agit d'un champ numérique,

int PhoneNumber

Si j'utilise une langue anglaise normale, je n'ai pas besoin de déclarer PhoneNumberque intje l'utilise. Par exemple, si je demande à mon ami Sam de me donner son numéro de téléphone, je dis:

"Sam donne moi le numéro de téléphone"

Je ne dirais pas

"Char (20) Sam me donner le numéro de téléphone international"

Pourquoi devons-nous spécifier un type de données?

Dick Smith
la source
83
C'est parce que l'anglais a un type de saisie implicite - votre numéro de téléphone est donc implicitement saisi comme un numéro de téléphone - les humains ont également une allocation de mémoire dynamique ...;)
HorusKol
28
Vous et Sam savez qu'un numéro de téléphone est composé de chiffres et vous seriez surpris de trouver une lettre. Les ordinateurs n'en ont pas et doivent être prévenus.
Thorbjørn Ravn Andersen
16
Et quand j'entends des chiffres comme 1-800-JIMBO dans les films, ma pensée est: comment est-ce un nombre ? Oo
muru
103
Vous ne devez pas déclarer phoneNumber en tant qu'int. Dans la plupart des langages de programmation, cela supprimera les zéros de gauche.
Aron_dc
25
@HorusKol: les humains ont non seulement une allocation de mémoire dynamique, mais également un récupérateur de déchets hautement non conservateur ...
leftaroundabout

Réponses:

79

Dans la plupart des langues de codage (si pas toutes), vous devez déclarer des variables.

[…]

Pourquoi devons-nous spécifier un type de données?

Ce sont deux questions indépendantes:

  • Pourquoi avons-nous besoin de déclarer des variables?
  • Pourquoi avons-nous besoin de déclarer des types?

Incidemment, la réponse aux deux est: nous ne le faisons pas.

Il y a beaucoup de langages de programmation statiquement typés où il n'est pas nécessaire de déclarer les types. Le compilateur peut déduire les types du contexte et de l'utilisation.

Par exemple, à Scala, vous pouvez dire

val age: Int = 23

ou vous pouvez simplement dire

val age = 23

Les deux sont exactement équivalents: le compilateur déduira que le type Intprovient de l'expression d'initialisation 23.

De même, en C, vous pouvez dire l'un ou l'autre, et les deux signifient exactement la même chose:

int age = 23;
var age = 23;

Cette fonctionnalité est appelée inférence de type , et de nombreuses langues autres que Scala et C♯ l’ont: Haskell, Kotlin, Ceylan, ML, F♯, C ++. Même Java a des formes limitées d'inférence de type.

Dans les langages de programmation à typage dynamique, les variables n'ont même pas de types. Les types n'existent que de manière dynamique au moment de l'exécution, pas de manière statique. Seules les valeurs et les expressions ont des types et uniquement au moment de l'exécution, les variables n'ont pas de types.

Par exemple, dans ECMAScript:

const age = 23;
let age = 23;

Enfin, dans de nombreuses langues, vous n’avez même pas besoin de déclarer des variables. par exemple en rubis:

age = 23

En fait, ce dernier exemple est valable dans plusieurs langages de programmation. La même ligne de code fonctionnerait également en Python, par exemple.

Alors,

  • même dans les langages à typage statique où les variables ont des types, vous n'avez pas nécessairement à les déclarer,
  • dans les langages à typage dynamique, les variables n'ont pas de types, donc vous ne pouvez même pas les déclarer,
  • dans de nombreuses langues, vous n'avez même pas à déclarer de variables
Jörg W Mittag
la source
2
Plus un pour expliquer à la fois l'inférence de type et le dactylographie dynamique (liaison tardive)
départ du
36
C'est une excellente information sur les idées fausses derrière la question, mais laisse toujours la question sans réponse. La question, plus correctement, est pourquoi devons-nous spécifier le type de données lors de la déclaration de variables dans des langages qui le nécessitent? Pourquoi ont-ils été conçus? Il y a de bonnes réponses à cette question et, même si élaborer de nouvelles alternatives élargit les horizons du PO et est très bon, cela ne me semble pas complet.
Kryan
7
@KRyan: si vous voulez savoir pourquoi un certain concepteur de langage a fait un certain choix de conception de langue, vous devrez demander à ce concepteur de langue, j'en ai bien peur. Je ne peux pas vous dire pourquoi les concepteurs de C ont décidé de ne pas recourir à l'inférence de type, et je ne peux pas non plus vous dire pourquoi ils ont ultérieurement changé d'avis. La conception du langage a une forte opinion et revient souvent au goût. Si, OTOH, vous souhaitez en savoir plus sur les compromis spécifiques impliqués, la réponse serait essentiellement une réimpression des types et langages de programmation du professeur Pierce, qui est beaucoup trop large pour Stack Exchange.
Jörg W Mittag
2
JörgWMittag: comme @KRyan l'a déjà dit, la réponse "vous n'êtes pas obligé de" n'est pas très intéressante (c'est trivialement évident - beaucoup de langues permettent d'omettre les déclarations de type dans certains cas). La question "pourquoi voudriez-vous déclarer des types" est beaucoup plus intéressante et reflète mieux l'esprit de la question initiale (votre réponse me rappelle la blague: "où nous sommes?" - "vous êtes dans une montgolfière ! " ). Vous n'avez pas besoin de savoir ce qu'un concepteur d'une langue spécifique pensait à l'époque, pour donner de bonnes raisons en faveur de la déclaration de type.
Jfs
1
@Zaibis: auto i = 1 // i is inferred to type int, vector<int> vec; auto itr = vec.iterator(); // itr is inferred to type vector<int>::iteratoret ainsi de suite. Si vous voulez savoir comment cela fonctionne, vous pouvez le rechercher dans la spécification.
Jörg W Mittag
53

Lorsque vous utilisez le langage naturel pour faire référence à des informations, celles-ci ne sont pas très précises et, en particulier, ne communiquent pas beaucoup d'informations à propos de votre intention. Des problèmes similaires se produisent lorsque vous essayez de faire des maths en langage naturel: cela n’est tout simplement pas assez précis.

La programmation est complexe. les erreurs sont trop faciles à trouver. Les types font partie d'un système de vérification conçu pour empêcher les états de programme illégaux, en détectant les conditions d'erreur. Différentes langues utilisent les types différemment: certaines langues utilisent énormément les types pour détecter les erreurs lors de la compilation. Presque toutes les langues ont une notion des types incompatibles en tant qu'erreur d'exécution. Généralement, une erreur de type indique un bogue dans le programme. Lorsque nous autorisons les programmes à continuer malgré les erreurs, nous obtenons probablement de très mauvaises réponses. Nous préférons arrêter le programme plutôt que d'obtenir des réponses mauvaises ou incorrectes.

En d'autres termes, les types expriment des contraintes sur le comportement du programme. Les contraintes, lorsqu'elles sont appliquées par un mécanisme quelconque, fournissent des garanties. Ces garanties limitent la quantité de raisonnement nécessaire pour réfléchir au programme, simplifiant ainsi la tâche de lecture et de maintenance du programme pour les programmeurs. En l'absence de types et de leur implication dans des outils (le compilateur) permettant de détecter les erreurs de type, la charge de programmation est considérablement plus lourde et donc plus coûteuse.

Il est vrai que de nombreux humains distinguent facilement un numéro de téléphone européen, américain et international. Cependant, l'ordinateur ne "pense pas" vraiment et composera, si on le lui dit, un numéro de téléphone des États-Unis en Europe, ou inversement. Les types, par exemple, sont un bon moyen de faire la distinction entre ces cas, sans avoir à apprendre à l'ordinateur à "penser". Dans certaines langues, une erreur de compilation peut survenir si vous essayez de mélanger un numéro de téléphone européen sur un système téléphonique américain. Cette erreur nous indique que nous devons modifier notre programme (peut-être en convertissant le numéro de téléphone en une séquence de numérotation internationale ou en utilisant le numéro de téléphone en Europe) avant d'essayer d'exécuter le programme.

De plus, comme l’ordinateur ne le pense pas, le nom du champ ou de la variable (par exemple phonenumber) ne signifie rien pour l’ordinateur. Pour l'ordinateur, ce nom de champ / variable est simplement "blah123". Pensez à ce que serait votre programme si toutes les variables étaient "blahxxx". Beurk. Eh bien, c'est ce que voit l'ordinateur. Fournir un type donne à l'ordinateur une idée de la signification de la variable qu'il ne peut tout simplement pas déduire de son nom.

En outre, comme @Robert le dit, dans de nombreuses langues modernes, nous n’avons pas à spécifier autant de types qu’auparavant, car des langages comme C # effectuent une "inférence de type", qui est un ensemble de règles permettant de déterminer le type approprié. pour une variable en contexte. C # ne fournit que l'inférence de type sur les variables locales, mais pas sur les paramètres formels, ni sur les champs de classe ou d'instance.

Erik Eidt
la source
4
RE the sad partie: Il est impossible de déduire le type d'un membre accessible au public (champ public, signature de méthode publique), car vous ne pouvez pas prédire quand et comment il sera utilisé. En outre, les annotations de type sont de la documentation.
Sergio Tulentsev
Je pense que vous devriez mettre en évidence / gras cette ligne: Types are part of a system of checks that ...puisqu'elle répond directement à l'OP sur Why do we have to specify data type at all?..
txtechhelp
Remarque: vous répondez en supposant qu'un langage utilisé pour spécifier des types est en quelque sorte meilleur pour éviter les erreurs que votre langage de programmation habituel. Il est évident que ce n'est pas le cas, par exemple, considérons le langage de modèle C ++ qui est Turing-complet (et permet donc d'exprimer de nombreuses vérifications d'erreur), mais il est presque illisible par rapport à de nombreux autres langages de Turing-complet tels que Haskell, Python et même d'autres parties de. C ++ lui-même. Demandez-vous pourquoi vous n'utiliserez pas le même langage de programmation pour exprimer les contrôles d'erreur que le reste de votre programme (il existe de bonnes réponses dans certains cas, mais pas tous).
Jfs
@SergioTulentsev Ce n'est pas vrai - en F #, vous pouvez avoir des méthodes publiques sans spécifier explicitement leurs types. Le compilateur déduira les types d'utilisation dans la méthode. Par exemple, voici les définitions de méthodes publiques valides: static member add x y = x + y, member x.Append s = x.Text + s. Dans le premier cas, xet ysera déduit être ints en raison de l'addition. Dans le second cas, ce sera ce qui est valable en fonction du type de x.Text- si c'est un string, alors ce ssera stringaussi. Je conviens que les annotations de type sont de la documentation.
Roujo
"Types locaux implicites, types d'interface explicites", explique beaucoup de personnes, même dans des langages tels que Haskell, qui vous permettent d'omettre (presque) tous les types tout en permettant au compilateur d'inférer des types stricts. Il y a beaucoup de gens qui ne le considèrent pas triste quand un langage applique cette pratique (comme le fait C #).
Ben
29

Outre les autres réponses, il y a une chose à inclure. Rappelez-vous que les ordinateurs ne sont que des bits. Dites que je vous donne les octets:

26 3A 00 FF

Qu'est-ce que ça veut dire ? C'est stocké de cette façon par l'ordinateur, mais sans aucune interprétation, ce ne sont que des bits . Il pourrait s'agir de 4 personnages ascii. Ce pourrait être un entier. Il pourrait s'agir d'octets dans un tableau. Cela pourrait faire partie d'un objet. Ce pourrait être un pointeur sur l'endroit où la vidéo de votre chat met en mémoire tampon. Quasiment tous les langages de programmation de l' assemblage sur place besoin quelque chose de savoir comment interpréter les bits pour leur faire faire le calcul significatif.

Et comme l'ordinateur ne peut pas connaître la signification de ces bits, il est nécessaire que vous le disiez, soit explicitement via des annotations de type, soit implicitement via des mécanismes d'inférence de type mentionnés dans les autres réponses.

Telastyn
la source
10
Bien que cela soit vrai, mais pour que vous restiez bouche bée, réalisez que l'ordinateur n'est jamais capable de comprendre ce que signifient ces bits, même lorsque vous lui indiquez plusieurs annotations. Vos explications sont simplement transformées en encore plus de nombres hexadécimaux, afin de "clarifier" les premiers nombres hexadécimaux. La signification est entièrement créée par les personnes afin de mettre l'intention dans l'électronique et de les amener à faire ce que nous voulons. Maintenant, allez dire "merci" à un ingénieur. :)
Wildcard
1
J'ai passé de nombreuses années à programmer sur des mainframes. Avec PL / 1, cette réponse a beaucoup de sens. Nous utiliserions assez régulièrement le stockage basé sur un pointeur défini sur l'adresse d'une autre variable d'un type de données différent pour accéder aux octets d'une manière différente. Par exemple, PL / 1 ne prend pas en charge un champ numérique binaire de 1 octet, mais nous baserions une adresse de 1 caractère à l'adresse pour nous permettre de stocker un tableau de 6 octets stockant 6 champs binaires d'un octet (permettant dans ce cas de sauvegarder 6 octets par adresse - ce qui était important lorsque le stockage était coûteux).
Kickstart
1
L'ordinateur est capable de comprendre beaucoup de possibilités, mais même les compilateurs intelligents ont besoin de contexte pour être compris. Ce n'est pas le même que le nombre 0 ou "0". Ou la chaîne "31 décembre" sera commandée avant le "1er mai" traitée comme une chaîne mais pas si elle est traitée comme une date. Ou prendre 5/2. C'est 2 en entrée mais 2,5 en double. En outre, le type est une mesure de sécurité contre les conversions non désirées. Null, NaN, et l'arrondissement ou les débordements peuvent également devenir un problème. Les langages forts et statiques présentent certains avantages. Par exemple, le compilateur vous aide à détecter les problèmes lors du refactoring.
Borjab
1
@Borjab Vouliez - vous dire « Il est 2 comme un nombre entier »?
Richard Everett
1
@ RichardEverett Certes, c'était un lapsus. Merci mais trop tard pour le modifier.
Borjab
23

La réponse à la question de savoir pourquoi les ordinateurs ont besoin de ces informations est liée à la représentation des données .

Le nom du "type de données" est une référence aux règles qui aident l'ordinateur à stocker et à récupérer des informations à partir de son état brut de 0 et de 1 dans la mémoire de l'ordinateur.

Par exemple, votre caractère ASCII 8 bits normal serait stocké dans la mémoire de l'ordinateur (RAM ou disque) sous la forme 01000001(le caractère majuscule "A", le code ASCII 65) ou 00001000(le signe de pourcentage), ou toute combinaison de 0 et 1 est dans ces 8 bits.

Pour un autre exemple, un entier non signé de 8 bits peut être stocké sous la forme 00000101(le nombre 5) ou 00001000(le nombre 8)

Remarquez comment la représentation binaire de 8 et le caractère% peuvent être identiques, mais ils signifient des choses différentes car leurs types sont différents.

Même les langues qui déduisent le type de données, elles peuvent ne pas avoir la règle que "tous les types de variables doivent être déclarés par le programmeur", ils ont des règles du type "si votre série de caractères est placée entre guillemets, c'est une chaîne" et beaucoup plus de règles pour chaque type de données.

Ainsi, même ces types de données ont besoin de comprendre la signification des 0 et des 1, afin de pouvoir, par exemple, effectuer la fonction de concaténation de chaînes si vous essayez "d'ajouter" deux caractères, ou d'ajouter des entiers si vous essayez d'ajouter deux entiers. .

Dans votre histoire aussi, supposons que vous n'ayez pas demandé le numéro de téléphone à Sam, mais qu'il vous a remis un morceau de papier sur lequel est écrit "1123581321". Vous ne pouvez pas savoir avec certitude si Sam est simplement un fan des huit premiers numéros de Fibonacci ou s'il s'agit d'un numéro de téléphone. Pour deviner, vous devrez tenir compte du contexte et des indices dont vous disposez, par exemple, vous avez peut-être demandé un numéro de téléphone à Sam il y a un jour, ou la note indique "Appelle-moi", ou si vous comptez les chiffres et trouvez il correspond aux modèles de la plupart des numéros de téléphone. Ce n’est qu’alors que vous saurez que c’est un numéro de téléphone que vous pouvez appeler et non quelques chiffres que vous composeriez avec une calculatrice.

Notez que ces indications qui vous ont conduit à deviner que le numéro était un numéro de téléphone sont similaires à la façon dont les indications dirigent un langage informatique ne nécessitant pas de déclaration pour déduire le type d'une valeur.

Peeyush Kushwaha
la source
3
C'est la réponse la plus proche. Tout a à voir avec la mémoire. Vous déclarez le type pour que le compilateur sache combien de mémoire doit être demandée à l'application au moment de l'exécution. Savoir comment les bits doivent être interprétés est secondaire.
Greg Burghardt
@ GregBurghardt vrai. Pour donner un sens aux bits déjà présents et pour y placer les bits en premier lieu après la conversion de données données en données binaires en fonction du type de données.
Peeyush Kushwaha
10

Dans certaines langues, il n'est pas nécessaire de spécifier le type de données.

Les langues qui prennent en charge l'inférence de type peuvent généralement déterminer le type de données à partir de votre utilisation. Par exemple,

var name = "Ali"

est typé en interne sous forme de chaîne, car la valeur est entourée de guillemets.

Certaines langues ne vous obligent pas à déclarer la variable non plus; la variable est créée lors de sa première utilisation. Toutefois, il est considéré comme une pratique exemplaire de déclarer spécifiquement vos variables, pour un certain nombre de raisons importantes; surtout parce que cela exprime mieux votre intention.

Robert Harvey
la source
5
Le var name = "Ali"style est commun aux langages modernes typés statiquement . Dans les langages à typage statique, le type est fixé à la création, mais il peut toujours être déterminé par l'initialiseur. La définition d'un langage à typage dynamique est que les types se rattachent à des valeurs et non à des variables. L'affectation d'une valeur à une variable définit donc également le type de la variable.
MSalters
@MSalters: J'ai légèrement modifié le libellé.
Robert Harvey
5
L'ironie ici est que cela inclut C # avec cette syntaxe exacte.
Derek Elkins
1
@MSalters L' attribution d'une valeur à une variable définit donc également le type de la variable. Ou que la variable n'a pas de type inhérent et que l'interprète tentera d'appliquer n'importe quelle opération à la valeur de la variable. Existe-t-il des langages à typage dynamique dans lesquels un code tel que celui-ci (Javascript) ne serait pas autorisé var x = 5; x = "";car la première instruction fait xen sorte que le type "Number" soit associé x? Tri des conflits avec la frappe dynamique . Et si non, quel est l'effet du type associé à la variable, au-delà de l'association du type avec la valeur?
Zev Spitz
1
@ZevSpitz: Le premier type de système n'est pas typé dynamiquement, mais pas du tout. Votre exemple Javascript n'est pas typé dynamiquement, précisément parce que le type Number ne peut pas changer. Dans un langage typé dynamiquement, x = "";modifie le type de x en chaîne, même s'il s'agissait auparavant d'un nombre.
MSalters
9

Parce que c'est ce que la conception de langage spécifie. Donc, pour répondre à votre question, nous devons examiner l’intention qui sous-tend le typage explicite dans des langages tels que C # et C ++. (Eh bien, C # le fait parce que C ++ le fait parce que C le fait, nous devons donc examiner l'intention de cette manière à l'époque).

Premièrement, le typage explicite et statique fournit un codage rigoureux - spécifier une variable comme étant un entier signifie que le compilateur et le logiciel doivent être surpris et émettre une erreur lorsque vous affectez un caractère ou une chaîne à la variable. Le typage dynamique peut causer des maux de tête pour les imprudents (il suffit de regarder l’approche PHP ou javascripts pour la véracité de choses telles que les tableaux et les chaînes vides).

Vous pouvez avoir statique avec le typage implicite - initialiser une variable en tant que chaîne signifie que cette variable ne devrait jamais être une chaîne, mais mon sentiment est que cela peut causer des problèmes à la lecture du code par les humains (j'ai tendance à supposer un typage dynamique en cas de typage implicite )

De plus, il est possible, dans certaines langues, d'écrire quelque chose comme ce pseudo-code pour initialiser une classe à partir d'une entrée de chaîne:

PhoneNumber phoneNumber = "(61) 8 8000 8123";

Deuxièmement, le typage explicite va également de pair avec l’allocation de mémoire. Un int est toujours tellement d'octets. Un numéro de téléphone, c'est tellement d'octets. Le compilateur peut affecter un bloc de mémoire de taille appropriée qui pourra ensuite être utilisé sans avoir à voir combien d'espace il lui faudra pour assigner une valeur.

PhoneNumber phoneNumber;
...
phoneNumber = "some value from somewhere";

Enfin, cela élimine la confusion ... 123 est-il un entier ou un entier non signé? Ils ont besoin du même nombre d'octets, mais la valeur maximale stockée dans les variables de l'un ou l'autre type est très différente ...

Ce n’est pas vrai dire que explicite vaut mieux qu’implicite - mais la conception du langage s’appuie sur ce type de choix et C # fonctionnerait différemment avec le typage implicite. PHP et javascript fonctionneraient différemment avec un typage explicite.

HorusKol
la source
5

Parce que Sam est plus intelligent que les compilateurs. Par exemple, lorsque vous dites me donner le numéro de téléphone, vous ne spécifiez pas si vous voulez le préfixe du pays ou l'indicatif régional s'il s'agit d'un numéro professionnel où seuls les 4 derniers chiffres sont requis. De plus, si vous demandiez le numéro du joint de pizza local, vous seriez en mesure de traiter la réponse "pizza4u".

Sam, le comprend à partir du contexte. Même si le compilateur peut aussi comprendre le contexte, Sam sera meilleur (et est capable d’interrompre le processus pour demander des éclaircissements).

Il existe deux approches de base pour les types et les variables, soit la variable a un type, auquel cas les actions qui ne sont pas autorisées par le type sont interdites et empêchent la compilation, ou la valeur a un type et les actions qui ne sont pas autorisées par le type. Les types sont capturés au moment de l'exécution.

Chaque approche a ses avantages et ses inconvénients. En général, les rédacteurs de compilateur essaient de minimiser les inconvénients et de maximiser les avantages. C’est pourquoi, par exemple, C # permet var phoneNumber = GetPhoneNumber();et déduira le type de numéro de téléphone de la signature de GetPhoneNumber. Cela signifie que vous devez déclarer le type de la méthode, mais pas la variable qui reçoit le résultat. D'autre part, il existe différents projets d'indication de type / application de code pour JavaScript. Tout est un compromis.

Jmoreno
la source
3

C'est une question de la façon dont les données sont stockées. Votre interaction avec Sam ferait une meilleure comparaison si vous le demandiez pour que vous puissiez l'écrire mais que vous ne disposiez que de huit caractères.

"Sam, donne-moi le numéro de téléphone."

"5555555555"

"Oh non, je n'ai plus de papier. Si seulement j'avais su à l'avance combien de données je demandais, j'aurais pu mieux préparer!"

Donc au lieu de cela, la plupart des langues vous obligent à déclarer un type, ainsi il saura et se préparera à l'avance:

"Sam, combien de temps dure un numéro de téléphone?"

"Dix personnages."

"Ok, alors laisse-moi avoir un plus gros morceau de papier. Maintenant, donne-moi le numéro de téléphone."

"5555555555"

"Compris! Merci Sam!"

Cela devient encore plus poilu quand on regarde les méthodes fondamentales de stockage des données. Si vous êtes comme moi, vous avez un cahier avec diverses notes, des chiffres tout bribouillés, aucun contexte ni étiquette pour quoi que ce soit, et vous n'avez aucune idée de ce que cela signifie trois jours plus tard. C'est aussi un problème pour les ordinateurs. Beaucoup de langues ont des types "int" (int, long, court, octet) et "float" (float, double). Pourquoi est-ce nécessaire?

Eh bien, voyons d'abord comment un entier est stocké et généralement représenté dans l'ordinateur. Vous êtes probablement conscient du fait qu'au niveau de base, tout est binaire (1 et 0). Le binaire est en fait un système de numération qui fonctionne exactement comme notre système de numération décimale. En décimal, vous comptez 0 à 9 (avec des zéros infinis implicites que vous n'écrivez pas), vous revenez à 0 et incrémentez le chiffre suivant de sorte que vous ayez 10. Vous répétez jusqu'à ce que vous passiez de 19 à 20, répéter jusqu'à ce que vous passez de 99 à 100, et ainsi de suite.

Le binaire n’est pas différent, sauf qu'au lieu de 0 à 9, vous comptez 0 à 1. 0, 1, 10, 11, 100, 101, 110, 111, 1000. Ainsi, lorsque vous tapez 9, en mémoire, elle est enregistrée en binaire. 1001. C'est un nombre réel. Il peut être ajouté, soustrait, multiplié, etc. exactement sous cette forme. 10 + 1 = 11. 10 + 10 = 100 (survolez 1 à 0 et portez le 1). 11 x 10 = 110 (et de manière équivalente, 11 + 11 = 110).

Maintenant dans la mémoire réelle (registres inclus), il y a une liste, un tableau, peu importe comment vous voulez l'appeler, de bits (potentiels 1 ou 0 ') l'un à côté de l'autre, c'est comment il garde ces bits organisés de manière logique pour faire une nombre supérieur à 1. Le problème, c'est que faites-vous avec des nombres décimaux? Vous ne pouvez pas simplement insérer un élément de matériel entre les deux bits du registre, et ajouter des "bits décimaux" entre chaque paire de bits coûterait beaucoup trop cher. Alors que faire?

Vous l'encodez. Généralement, l’architecture de la CPU ou du logiciel déterminera comment procéder. Cependant, une méthode courante consiste à stocker un signe (+ ou -, généralement 1 est négatif) dans le premier bit du registre, une mantisse (votre numéro décalé). Cependant, il est souvent nécessaire de supprimer la décimale) pour le nombre X suivant de bits et un exposant (le nombre de fois que vous avez dû le déplacer) pour le reste. C'est similaire à la notation scientifique.

La frappe permet au compilateur de savoir à quoi il ressemble. Imaginez que vous ayez stocké la valeur 1.3 dans le registre 1. Nous allons simplement créer ici notre propre schéma de codage de fantaisie, 1 bit pour le signe, 4 pour la mantisse, 3 pour l'exposant (1 bit pour le signe, 2 pour la magnitude). C'est un nombre positif, donc le signe est positif (0). Notre mantisse serait 13 (1101) et notre exposant serait -1 (101 (1 pour négatif, 01 = 1)). Donc nous avons stocké 01101101 dans le registre 1. Maintenant, nous n’avons pas tapé cette variable, donc quand le runtime va l’utiliser, il dit "bien sûr, c’est un entier, pourquoi pas", alors quand il affiche la valeur, on voit 109 (64 + 32 + 8 + 4 + 1), ce qui n’est évidemment pas correct.

Cependant, toutes les langues ne nécessitent pas explicitement de taper. C # a un mot clé "var" qui interprète le type d'une variable lors de la compilation, et d'autres langages comme Javascript sont typés de manière totalement dynamique, au point que vous pouvez stocker un entier dans une variable, puis l'assigner à un booléen, puis assignez-le à nouveau à une chaîne et la langue en gardera la trace.

Mais c’est beaucoup plus facile pour le compilateur, l’interprète ou le moteur d’exécution - et aboutit souvent à un programme plus rapide, car il n’a pas à dépenser de précieuses ressources pour trier tout ce qui est dactylographié - pour vous demander, à vous, le programmeur, quel type de les données que vous lui donnez.

Devsman
la source
2

Il existe des langages de programmation dans lesquels vous n'avez pas à déclarer les types de données pour vos variables. Il existe même des langages de programmation où il n'est pas nécessaire de déclarer les variables à l'avance; vous pouvez simplement les utiliser , immédiatement.

Le problème avec le fait de ne pas déclarer les noms de variable est que si vous avez mal orthographié par erreur le nom d'une variable, vous avez maintenant créé accidentellement une nouvelle variable, totalement indépendante. Ainsi, lorsque vous exécutez votre programme, vous ne pouvez pas comprendre pourquoi l' enfer de cette variable que vous avez configurée n'a soudainement plus rien dedans ... Jusqu'à ce que, après de nombreuses heures de débogage, vous réalisiez que vous avez mal tapé le nom! GRRR !!

Donc, ils ont fait en sorte que vous deviez déclarer les noms de variable que vous allez utiliser avant. Et maintenant , quand vous tapez un mauvais nom, vous obtenez une erreur de compilation, qui vous indique immédiatement exactement où le bogue est, avant que votre programme fonctionne même. N'est-ce pas tellement plus facile?

Même affaire avec les types de données. Il existe des langages de programmation où il n'est pas nécessaire de déclarer quel type devrait être. Si vous avez une customervariable qui est en fait juste le nom du client, et non l'objet entier, essayer d'extraire l'adresse du client à partir d'une chaîne ordinaire, cela ne fonctionnera pas. Le point essentiel du typage statique est que le programme ne compile pas; il va se plaindre à voix haute, en indiquant l'endroit exact où se situe le problème. C'est beaucoup plus rapide que d'exécuter votre code et d'essayer de comprendre pourquoi il ne fonctionne pas.

Toutes ces fonctionnalités permettent au compilateur de dire ce que vous aviez l' intention de faire, afin qu'il puisse vérifier ce que vous avez réellement fait et s'assurer que cela a du sens. Cela permet au compilateur de localiser automatiquement les bogues pour vous, ce qui est un gros problème.

(Dans un passé lointain, vous n’aviez pas à déclarer de sous-routines . Vous GOSUBn’avez besoin que d’un numéro de ligne particulier. Si vous souhaitez transmettre des informations entre les sous-routines, vous devez définir des variables globales particulières, appeler votre sous-routine puis inspecter les autres. variables lorsque le sous-programme revient. Mais il est terriblement facile d’oublier d’initialiser l’un des paramètres. Désormais, presque tous les langages de programmation modernes exigent que vous déclariez les paramètres effectifs d’un sous-programme, afin que nous puissions vérifier que vous les avez tous spécifiés. )

MathematicalOrchid
la source
1
En C ++, vous pouvez mettre "auto x = 1" et il sait que c'est un int. auto y = 1,2; auto z = 'Z'; etc
QuentinUK
@QuentinUK En C #, vous pouvez utiliser var x=1des résultats similaires. Mais ce n'est rien en Haskell, vous pouvez écrire votre programme entier sans aucune signature de type, mais tout est statiquement tapé, et vous obtenez toujours des erreurs si vous commettez une erreur ... (Pas tout à fait classique cependant.)
MathematicalOrchid
@QuentinUK Mais si vous écrivez for (auto i=0; i<SomeStdVector.size(); ++i)votre linter va se plaindre car il en déduit un type signé et vous procédez à la comparer à un type non signé. Vous devez écrire auto i=0ul(en remettant explicitement les informations de type, vous devriez simplement écrire size_t i=0en premier lieu).
dmckee
1

Si j'utilise une langue anglaise normale, je n'ai pas besoin de déclarer PhoneNumber comme int pour l'utiliser. Par exemple, si je demande à mon ami Sam de me donner son numéro de téléphone, je dis:

"Sam donne moi le numéro de téléphone"

Je ne dirais pas>

"Char (20) Sam me donner le numéro de téléphone international"

Pourquoi devons-nous spécifier un type de données?

Rendez-vous sur MathOverflow ou sur l' informatique théorique et lisez pendant un moment pour avoir une idée de la façon dont les humains ont échangé des alogrithmes lorsqu'ils veulent s'assurer qu'il n'y a aucune possibilité de malentendu. Ou lisez le standard pour un langage de programmation mature.

Vous constaterez que la définition des types de valeurs autorisés pour un terme fait partie d'une pratique de communication très précise, même d'homme à homme.

Ce que vous avez remarqué, c’est que les interactions quotidiennes sont assez régulières et que les humains sont plutôt tolérants aux fautes. Un malentendu sur les numéros de téléphone est généralement évité grâce à la connaissance partagée des participants.

Mais avez-vous déjà essayé de prendre un numéro de téléphone pour quelqu'un dans un autre pays? Vous ont-ils dit explicitement combien de fois pousser zéro pour arriver à un adressage international? Vous ont-ils dit leur code de pays? L'avez-vous reconnu comme tel? Vous attendiez combien de chiffres? Combien avez-vous obtenu? Saviez-vous comment regrouper les chiffres? Ou même si le groupement a une signification?

Soudain, le problème est beaucoup plus difficile et vous avez probablement pris beaucoup plus de soin de vérifier explicitement que le numéro reçu était compris de la manière dont l'expéditeur le pensait.

dmckee
la source
0

L'efficacité est une autre raison de déclarer des types. Tandis qu'un entier peut être stocké dans 1 octet, ou 2 octets, ou 4, un programme utilisant un très grand nombre de variables peut utiliser 4 fois la mémoire requise, en fonction de ce qui est fait. Seul le programmeur sait si un espace de stockage plus petit est viable, il peut donc le dire en déclarant le type.

De plus, les objets typés dynamiquement permettent de nombreux types possibles, à la volée. Cela pourrait entraîner des frais généraux "sous le capot", ce qui ralentirait le programme par rapport au fait de rester avec un type tout du long.

Donjuedo
la source
0

Un certain nombre de premiers langages de programmation (en particulier Fortran) ne vous obligeaient pas à déclarer les variables avant leur utilisation.

Cela a conduit à un certain nombre de problèmes. L'une des plus évidentes est que le compilateur ne peut plus détecter les erreurs typographiques simples de manière presque aussi fiable. Si vous avez un code censé modifier une variable existante, mais que vous avez une faute de frappe, vous avez toujours un code parfaitement légitime qui vient de créer (et d'attribuer une valeur) une nouvelle variable:

longVariableName = 1

// ...

longVaraibleName = longvariableName + anotherLongVariableName

Maintenant, en regardant cela isolément, avec déjà mentionné une faute de frappe comme source du problème, il est probablement assez facile de trouver la faute de frappe et le problème ici. Dans un long programme, où il est enfoui au milieu de nombreux autres codes, il est beaucoup plus facile de le rater.

Même avec de nombreux langages à typage dynamique, vous pouvez toujours résoudre assez facilement le même problème de base. Certains ont une certaine facilité à vous avertir si vous affectez une variable, mais ne la lisez jamais (ce qui heurte heureusement de nombreux problèmes comme celui-ci), les deux autres n'ont pas de telles choses.

Jerry Coffin
la source
0

Lorsque vous déclarez une variable, de l’espace est alloué dans la mémoire, mais la machine (l’ordinateur dans ce cas) ne sait pas déjà combien d’espace doit être alloué à cette variable.

Exemple: - vous créez un programme qui demande à l'utilisateur d'entrer un nombre quelconque, dans ce cas , vous devez spécifier un type de données pour stocker ce nombre, sinon la machine ne peut pas juger par lui - même qu'il doit allouer 2 octets ou 2 giga - octets , si elle tente Si vous indiquez le type de données dans votre programme, la machine allouera, après la compilation, l’espace approprié en fonction des besoins.

Atul170294
la source
cela ne semble rien offrir de substantiel sur les points soulevés et expliqués dans les 11 réponses précédentes
gnat
1
Gnat, vous devriez lire à nouveau toutes les réponses à fond et voir que j’ai essayé de répondre à cette question d’une manière beaucoup plus simple et facilement compréhensible.
Atul170294
Je viens de re-vérifié trois réponses les plus récentes qui ont été affichées environ une heure avant celui - ci et tous les trois semblent faire le même point et par ma lecture expliquer d'une manière plus simple que ici
moucheron
Bien que je n'ai pas répondu à la récompense de votre vote, mais je pense que vous devriez apprendre à savoir une chose, vous devriez baisser la réponse car cela peut donner des informations inutiles ou erronées et si elles contiennent quelque chose d'offensant. Toutes les réponses contenant les informations les plus utiles et les plus pertinentes obtiendront un nombre plus élevé de votes positifs, ce qui suffit à faire la différence entre une réponse, une bonne réponse et la meilleure réponse. Votre activité enfantine consistant à voter une réponse sans raison forte ne fera que décourager d'autres personnes qui souhaitent également partager leur opinion qui, à leur avis, pourrait être utile à d'autres
Atul170294
1
Votre réponse a probablement été refusée car elle n’est pas correcte. Le typage statique n'est pas nécessaire pour faciliter la gestion de la mémoire. De nombreuses langues permettent le typage dynamique et ces langues / environnements peuvent traiter les problèmes de gestion de la mémoire que vous avez mentionnés.
Jay Elston