Pour répondre à la question que vous avez postée dans plusieurs commentaires (que je pense que vous devriez éditer dans votre post):
Ce que je ne comprends pas, c'est comment l'ordinateur sait quand il lit une valeur de variable et une adresse telle que 10001 si est un entier ou un caractère. Imaginons que je clique sur un programme appelé anyprog.exe. Immédiatement, le code commence à s'exécuter. Ce fichier exe contient-il des informations sur le fait de savoir si les variables sont stockées dans ou dans char?
Alors mettons un peu de code dessus. Disons que vous écrivez:
int x = 4;
Et supposons qu'il soit stocké dans la RAM:
0x00010004: 0x00000004
La première partie étant l'adresse, la deuxième partie étant la valeur. Lorsque votre programme (qui s’exécute en tant que code machine) s’exécute, il ne voit que 0x00010004
la valeur 0x000000004
. Il ne «connaît» pas le type de ces données et ne sait pas comment il est «supposé» être utilisé.
Alors, comment votre programme détermine-t-il la bonne chose à faire? Considérons ce code:
int x = 4;
x = x + 5;
Nous avons une lecture et une écriture ici. Lorsque votre programme lit en x
mémoire, il le trouve 0x00000004
. Et votre programme sait y ajouter 0x00000005
quelque chose. Et la raison pour laquelle votre programme "sait" qu'il s'agit d'une opération valide, c'est parce que le compilateur s'assure que l'opération est valide par le biais de la sécurité de type. Votre compilateur a déjà vérifié que vous pouvez ajouter 4
et 5
ensemble. Ainsi, lorsque votre code binaire s'exécute (le fichier exe), il n'a pas à effectuer cette vérification. Il exécute chaque étape à l'aveuglette, en supposant que tout va bien (les mauvaises choses arrivent lorsqu'elles le sont, en fait, ce n'est pas OK).
Une autre façon de penser est comme ça. Je vous donne cette information:
0x00000004: 0x12345678
Même format que précédemment - adresse à gauche, valeur à droite. De quel type est la valeur? À ce stade, vous connaissez autant d'informations sur cette valeur que votre ordinateur en exécutant du code. Si je vous disais d'ajouter 12743 à cette valeur, vous pourriez le faire. Vous ne savez pas quelles seront les répercussions de cette opération sur l'ensemble du système, mais vous êtes vraiment doué pour ajouter deux chiffres, vous pouvez donc le faire. Est-ce que cela fait de la valeur un int
? Pas nécessairement - Tout ce que vous voyez est deux valeurs 32 bits et l'opérateur d'addition.
Peut-être qu'une partie de la confusion est alors de récupérer les données. Si nous avons:
char A = 'a';
Comment l'ordinateur sait-il s'afficher a
dans la console? Eh bien, il y a beaucoup d'étapes à suivre. La première consiste à aller à l’ A
emplacement de s en mémoire et à le lire:
0x00000004: 0x00000061
La valeur hexadécimale correspondant a
à ASCII est 0x61. Il est donc possible que ce qui précède apparaisse dans la mémoire. Alors maintenant, notre code machine connaît la valeur entière. Comment sait-il transformer la valeur entière en un caractère pour l'afficher? En bref, le compilateur s’est assuré de mettre en place toutes les étapes nécessaires à cette transition. Mais votre ordinateur lui-même (ou le programme / exe) n'a aucune idée du type de ces données. Cette valeur de 32 bits peut être n'importe quoi - int
, la char
moitié d'un double
, un pointeur, une partie d'un tableau, une string
partie, une partie d'une instruction, etc.
Voici une brève interaction de votre programme (exe) avec l’ordinateur / le système d’exploitation.
Programme: Je veux commencer. J'ai besoin de 20 Mo de mémoire.
Système d'exploitation: trouve 20 Mo de mémoire libre qui ne sont pas utilisés et les remet
(La remarque importante est que cela pourrait revenir tout 20 Mo de mémoire, ils ne sont même pas être contigus. À ce stade, le programme peut maintenant fonctionner dans la mémoire , il a sans parler à l'OS)
Programme: Je vais supposer que la première place en mémoire est une variable entière de 32 bits x
.
(Le compilateur s'assure que les accès aux autres variables ne toucheront jamais cet emplacement en mémoire. Rien dans le système ne dit que le premier octet est variable x
, ou que cette variable x
est un entier. Une analogie: vous avez un sac. Vous dites aux gens que vous ne mettrez que des balles de couleur jaune dans ce sac. Lorsque quelqu'un retirera quelque chose du sac, il serait choquant de pouvoir sortir quelque chose de bleu ou un cube - quelque chose a mal tourné. Il en va de même pour les ordinateurs: votre programme suppose maintenant que le premier emplacement de mémoire est une variable x et qu’il s’agit d’un entier. Si quelque chose d’autre est écrit sur cet octet de mémoire ou si on suppose qu’il est autre chose, il s’est passé quelque chose d’horrible. Le compilateur assure ce genre de choses pas arriver)
Programme: J'écrirai maintenant 2
les quatre premiers octets où je suppose en x
être à.
Programme: Je veux ajouter 5 à x
.
Lit la valeur de X dans un registre temporaire
Ajoute 5 au registre temporaire
Stocke la valeur du registre temporaire dans le premier octet, qui est toujours supposé être x
.
Programme: Je vais supposer que le prochain octet disponible est la variable char y
.
Programme: je vais écrire a
à variable y
.
Programme: Je veux afficher le contenu de y
Lit la valeur dans le deuxième emplacement mémoire
Utilise une bibliothèque pour convertir d'octet en caractère
Utilise des bibliothèques graphiques pour modifier l'écran de la console (définition des pixels du noir au blanc, défilement d'une ligne, etc.)
(Et ça continue d'ici)
Ce qui vous préoccupe probablement, c’est que se passe-t-il lorsque la première place dans la mémoire n’est plus x
? ou la seconde n'est plus y
? Qu'est - ce qui se passe quand quelqu'un lit x
un char
ou y
comme un pointeur? En bref, de mauvaises choses arrivent. Certaines de ces choses ont un comportement bien défini, et d'autres ont un comportement indéfini. Un comportement indéfini est exactement cela: tout peut arriver, qu’il s’agisse de rien, de planter le programme ou le système d’exploitation. Même un comportement bien défini peut être malveillant. Si je peux changer x
pour un pointeur vers mon programme et obtenir que votre programme l'utilise comme pointeur, je peux le faire exécuter par mon programme - ce qui est exactement ce que font les pirates. Le compilateur est là pour nous aider à ne pas utiliser int x
commestring
et des choses de cette nature. Le code machine lui-même ne connaît pas les types et il ne fera que ce que les instructions lui indiquent. Il existe également une grande quantité d'informations découvertes au moment de l'exécution: quels octets de mémoire le programme est-il autorisé à utiliser? x
Commence- t-on au premier octet ou au 12?
Mais vous pouvez imaginer à quel point il serait horrible d’écrire des programmes comme celui-ci (et vous pouvez le faire, en assembleur). Vous commencez par "déclarer" vos variables - vous vous dites que l'octet 1 est x
, l'octet 2 y
, et que vous écrivez chaque ligne de code, le chargement et le stockage des registres, vous (en tant qu'être humain) devez vous rappeler lequel est x
et lequel On est y
, parce que le système n'a aucune idée. Et vous (en tant qu'être humain) devez vous rappeler quels types x
et quels types y
car, encore une fois - le système n'a aucune idée.