53 votes

Est-ce que je pourrais un jour vouloir accéder à l'adresse zéro ?

La constante 0 est utilisée comme pointeur nul en C et C++. Mais comme dans la question "Pointeur vers une adresse fixe spécifique " il semble que l'attribution d'adresses fixes puisse être utile. Existe-t-il jamais un besoin concevable, dans un système quelconque, pour une tâche de bas niveau, d'accéder à l'adresse 0 ?

Si c'est le cas, comment cela est-il résolu avec 0 étant le pointeur nul et tout ?

Si ce n'est pas le cas, qu'est-ce qui permet d'affirmer qu'il n'y a pas un tel besoin ?

69voto

AndreyT Points 139512

Ni en C ni en C++, la valeur du pointeur nul n'est liée de quelque manière que ce soit à l'adresse physique. 0 . Le fait que vous utilisiez la constante 0 dans le code source pour mettre un pointeur sur une valeur nulle n'est rien de plus qu'un morceau de sucre syntaxique . Le compilateur doit la traduire en l'adresse physique réelle utilisée comme valeur du pointeur nul sur la plate-forme spécifique.

En d'autres termes, 0 dans le code source n'a aucune importance physique. Il aurait pu être 42 o 13 par exemple. C'est-à-dire que les auteurs de la langue, s'ils le voulaient, auraient pu faire en sorte que vous deviez faire p = 42 afin de placer le pointeur p à une valeur de type null-pointer. Encore une fois, cela ne signifie pas que l'adresse physique 42 devrait être réservé aux pointeurs nuls. Le compilateur serait tenu de traduire le code source p = 42 en code machine qui remplirait la valeur physique réelle du pointeur nul ( 0x0000 o 0xBAAD ) dans le pointeur p . C'est exactement comme ça que ça se passe maintenant, avec une constante 0 .

Notez également que ni le C ni le C++ ne fournissent une fonction strictement définie qui vous permettrait d'attribuer une adresse physique spécifique à un pointeur. Ainsi, votre question sur "comment assigner 0 adresse à un pointeur" est formellement sans réponse. Vous ne pouvez tout simplement pas attribuer une adresse spécifique à un pointeur en C/C++. Cependant, dans le domaine des fonctionnalités définies par l'implémentation, la conversion explicite d'entier en pointeur est destinée à avoir cet effet. Donc, vous le feriez comme suit

uintptr_t address = 0;
void *p = (void *) address;

Notez que ce n'est pas la même chose que de faire

void *p = 0;

Cette dernière produit toujours la valeur null-pointer, alors que la première ne le fait pas dans le cas général. La première produira normalement un pointeur à l'adresse physique 0 qui peut ou non être la valeur du pointeur nul sur la plate-forme donnée.

18voto

John Källén Points 3680

Sur une note tangentielle : vous serez peut-être intéressé de savoir qu'avec le compilateur C++ de Microsoft, un pointeur NULL vers un membre sera représenté par le motif binaire 0xFFFFFFFF sur une machine 32 bits. C'est-à-dire

struct foo
{
      int field;
};

int foo::*pmember = 0;     // 'null' member pointer

pmember aura le motif binaire "tous les uns". C'est parce que vous avez besoin de cette valeur pour le distinguer de

int foo::*pmember = &foo::field;

où le motif binaire sera en effet 'tous les zéros' -- puisque nous voulons l'offset 0 dans la structure foo.

D'autres compilateurs C++ peuvent choisir un schéma binaire différent pour un pointeur nul vers un membre, mais l'observation clé est que ce ne sera pas le schéma binaire tout-zéro auquel vous vous attendiez.

12voto

Jerry Coffin Points 237758

Vous partez d'une prémisse erronée. Lorsque vous assignez une constante entière avec la valeur 0 à un pointeur, ce devient une constante à pointeur nul. Cela fait no Cependant, cela signifie qu'un pointeur nul se réfère nécessairement à l'adresse 0. Bien au contraire, les normes C et C++ sont toutes deux très Il est clair qu'un pointeur nul peut faire référence à une adresse autre que zéro.

Ce que cela signifie, c'est que vous do doivent mettre de côté une adresse à laquelle un pointeur nul se référerait - mais il peut s'agir essentiellement de n'importe quelle adresse de votre choix. Lorsque vous convertissez un zéro en un pointeur, celui-ci doit se référer à cette adresse choisie -- mais c'est tout ce qui est vraiment nécessaire. Par exemple, si vous décidez que la conversion d'un entier en un point signifie l'ajout de 0x8000 à l'entier, alors le pointeur nul fera référence à l'adresse 0x8000 au lieu de l'adresse 0.

Il convient également de noter que le déréférencement d'un pointeur nul entraîne un comportement non défini. Cela signifie que vous ne pouvez pas le faire dans portable code, mais il ne no signifie que vous ne pouvez pas le faire du tout. Lorsque vous écrivez du code pour de petits microcontrôleurs et autres, il est assez courant d'inclure des morceaux de code qui ne sont pas du tout portables. La lecture d'une adresse peut vous donner la valeur d'un capteur, tandis que l'écriture à la même adresse peut activer un moteur pas à pas (juste pour l'exemple). L'appareil suivant (même s'il utilise exactement le même processeur) peut être connecté de telle sorte que ces deux adresses renvoient à la RAM normale.

Même si un pointeur nul fait se réfère à l'adresse 0, cela ne vous empêche pas de l'utiliser pour lire et/ou écrire ce qui se trouve à cette adresse - cela vous empêche simplement de le faire portatif -- mais cela n'a pas beaucoup d'importance. La seule raison pour laquelle l'adresse zéro serait normalement importante serait si elle était décodée pour se connecter à quelque chose d'autre qu'un stockage normal, donc vous ne pouvez probablement pas l'utiliser entièrement de manière portable de toute façon.

9voto

WhirlWind Points 8305

Le compilateur s'en charge pour vous ( FAQ comp.lang.c ):

Si une machine utilise un motif de bits non nuls pour les pointeurs nuls, il incombe au compilateur de le générer lorsque le programmeur demande, en écrivant "0" ou "NULL", un pointeur nul. Par conséquent, #définir NULL comme 0 sur une machine pour laquelle les pointeurs nuls internes sont non nuls est aussi valable que sur n'importe quelle autre, parce que le compilateur doit (et peut) toujours générer les pointeurs nuls corrects de la machine en réponse aux 0 non ornés vus dans les contextes de pointeurs.

Vous pouvez atteindre l'adresse zéro en référençant zéro à partir d'un contexte non pointeur.

7voto

Daniel Stutzbach Points 20026

En pratique, les compilateurs C laisseront volontiers votre programme tenter d'écrire à l'adresse 0. Vérifier chaque opération de pointeur au moment de l'exécution pour un pointeur NULL serait un peu coûteux. Sur les ordinateurs, le programme se plantera parce que le système d'exploitation l'interdit. Sur les systèmes embarqués sans protection de la mémoire, le programme écrira effectivement à l'adresse 0, ce qui fera souvent planter tout le système.

L'adresse 0 peut être utile sur un système embarqué (terme général désignant un processeur qui n'est pas intégré à un ordinateur ; il fait fonctionner tout, de votre chaîne stéréo à votre appareil photo numérique). En général, les systèmes sont conçus de manière à ce que vous n'ayez pas besoin d'écrire à l'adresse 0. Dans tous les cas que je connais, il s'agit d'une sorte d'adresse spéciale. Même si le programmeur a besoin d'y écrire (par exemple, pour configurer une table d'interruption), il n'aura besoin de le faire que pendant la séquence de démarrage initiale (généralement un court passage en langage d'assemblage pour configurer l'environnement pour le C).

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X