Pourquoi est l'adresse zéro utilisé pour le pointeur null?

En C (ou C++ d'ailleurs), les pointeurs sont spéciales si elles ont la valeur zéro: je suis conseillé de définir des pointeurs vers zéro après la libération de leur mémoire, parce qu'il signifie de les libérer à nouveau le pointeur n'est pas dangereux, quand j'ai appeler malloc retourne un pointeur avec la valeur zéro si elle ne peut pas me faire de la mémoire; je l'utilise if (p != 0) tout le temps à assurez-vous passé les pointeurs sont valides, etc.

Mais depuis adressage de mémoire commence à 0, n'est-ce pas 0 comme une adresse valide d'un autre? Comment peut-0 pour la manipulation de pointeurs null si c'est le cas? Pourquoi n'est-il pas un nombre négatif null à la place?


Edit:

Un tas de bonnes réponses. Je vais résumer ce qui a été dit dans les réponses exprimées comme mon propre esprit interprète et j'espère que la communauté va me corriger si j'ai mal compris.

  • Comme tout le reste dans la programmation, c'est une abstraction. Il suffit d'une constante, pas vraiment lié à l'adresse 0. C++0x souligne ce en ajoutant le mot-clé nullptr.

  • Il n'est même pas une adresse de l'abstraction, c'est la constante spécifiée par la norme C et le compilateur peut se traduire par un autre nombre, tant qu'il permet de s'assurer à jamais, il équivaut à un "réel" de l'adresse, et est égal à d'autres pointeurs null si 0 n'est pas le meilleur de la valeur à utiliser pour la plate-forme.

  • Dans le cas où il n'est pas une abstraction, qui a été le cas dans les premiers jours, l'adresse 0 est utilisé par le système et hors des limites du programmeur.

  • Mon nombre négatif suggestion a été un peu sauvage de remue-méninges, je l'avoue. À l'aide d'un entier signé pour les adresses est un peu du gaspillage si cela signifie que, en dehors de pointeur null (-1 ou quoi que ce soit) la valeur de l'espace est divisé en parts égales entre les entiers positifs qui font des adresses valides et les nombres négatifs qui sont tout simplement perdu.

  • Si un nombre est toujours représentable par un type de données, c'est 0. (Probablement 1 l'est aussi. Je pense à celui-bit integer qui sera de 0 ou 1 si non signé, ou tout simplement l'signé bits si signé, ou les deux bits entier qui serait [-2, 1]. Mais ensuite, vous pouvez simplement aller de 0 nul et 1 étant le seul accessible octet en mémoire.)

Il y a quand même quelque chose qui est en suspens dans mon esprit. La Pile Overflow question Pointeur à une adresse fixe me dit que même si la valeur 0 pour le pointeur null est une abstraction, d'autres valeurs de pointeur ne sont pas nécessairement. Ce qui m'amène à poster une autre Pile Overflow question, Pourrais-je veux accéder à l'adresse zéro?.

  • Vous pouvez tout aussi facilement changer if (p != 0) à if (p) qui est une commune de l'idiome en C et C++, bien que vous aurez à sortir de l'habitude, si vous prenez Java.
  • La suppression de deux fois la même chose signifie que votre code est faux. Je vous déconseille de réglage des pointeurs à null après de sorte que vous pouvez planter et de résoudre le problème, pas la supprimer. En tout cas, vous faites l'erreur de supposer une adresse est certain entier. Ce n'est pas nécessairement vrai, et 0 représente simplement un peu de vraie valeur du pointeur qui est spécifique à l'implémentation. Un "négatif adresse" n'a pas de sens, sur le plan conceptuel.
  • Peut-être même une bonne idée de définir un pointeur vers une adresse qui va forcer un blocage, comme 0xDEADBEEF.
  • La question qui ne mourra jamais!
  • Ne suivez pas GMan conseils. La suppression Multiple peut indiquer un problème théorique, mais ne va jamais à cause d'un problème. Un déréférencement/suppression d'un pointeur non valide sur l'autre main est toujours une question, MAIS la! ne doit pas nécessairement entraîner une panne. Il existe de nombreux cas dans lesquels vous pouvez déréférencement d'un pointeur non valide et simplement les résultats en complet de la folie et peut-être un accident plus tard. La seule fois que vous pouvez réellement pari (et non par le standard) que vous aurez un accident est si vous accédez à l'extérieur de votre programme de l'espace, qui a la valeur null sera certainement. UB peut causer des heures supplémentaires debug temps.
  • Le point est définie sur null -> masquer les erreurs de programmation, ne définissez pas la valeur null -> trouver les erreurs de programmation. Je ne sais pas vous, mais j'aimerais avoir mon code correct.
  • Les adresses ne sont pas signés,une valeur négative pourrait représentent simplement une très haute valeur en mémoire, selon la façon dont les OS cartes de mémoire virtuelle.
  • Depuis que cette question est dans la langue de terre, je vais souligner les adresses ne sont pas nécessairement des entiers non signés.
  • Depuis la non-char* pointeurs sont pratiquement toujours alignés (souvent sur une limite de 8 octets ces jours-ci), il peut être bénéfique pour les remplir de désallouer la mémoire de déchets octets dont le bit de poids faible jeu. J'utilise 0x61 mais c'est arbitraire. (L'avantage? Il vous donne une erreur/de signal due à des non-alignés d'accès lorsque vous déréférencement d'elle.)
  • vous n'allez pas faire votre code correct en invoquant nasale démons. La suppression des pointeurs deux fois n'est jamais un code incorrect. Il peut ou peut ne pas être un problème de conception, mais il n'est jamais une erreur.
  • Roberts: Selon la norme C, free()ing un pointeur deux fois les résultats dans un comportement indéfini. Je ne sais pas vous, mais j'essaie d'éviter que dans mes programmes.
  • oui, bien sûr j'ai oublié de préciser que c'est uniquement le cas lorsque le pointeur a été fixé à 0 depuis la libération d'un 0 ptr est un nop. Je n'ai pas de considérer qu'il est nécessaire étant donné que la position je suis, argumentant contre, c'est que de ne pas définir un pointeur à null, il fait en quelque sorte plus facile de trouver un code d'erreurs causées par la suppression d'un pointeur deux fois.
  • Êtes-vous d'accord que la suppression d'un pointeur deux fois, c'est parfois une erreur de logique?
  • Mon mentionnant des conseils pour définir le pointeur à null après la suppression causé tout un débat. Je n'ai pas vraiment a me reposer, et je certainement ne pas compter ni sur la pratique. Pour les intéressés, cette discussion a sa page ici: stackoverflow.com/questions/1931126/...
  • gman est correct. Le point entier dans C est pour éviter la surcharge de la vérification des contraintes au moment de l'exécution, sinon vous seriez de codage dans un sane langage comme Java. Il n'y a que quelques rares cas où vous double gratuit quelque chose, surtout depuis qu'elle est NULLE, tout d'abord..
  • êtes-vous sûr de dire d'accord avec gman->ne pas définir un pointeur à null après la suppression parce que vous voulez bloquer si vous avez accidentellement gratuit il de nouveau... Vos mots des sons autrement.
  • définir "erreur de logique". Il peut parfois être un pointeur null se faire supprimé est parce qu'il se passe autre chose qui ne devrait pas l'être. Si l'expose lui-même comme un bug dans le programme, alors c'est une erreur. Si la seule chose qui va "mal" c'est pas un pointeur null est passé à free() ou supprimer alors je pense que vous avez besoin de revoir votre définition de "erreur". En outre, l'alternative que gman propose ne garantit rien. La suppression d'un pointeur invalide, UB, pas de "crash". Plus souvent que pas, il exposera lui-même dans fous les moyens.
  • Roberts, je suis d'accord avec gman que vous ne devriez pas régler le pointeur de quoi que ce soit pour la marque de nullité, sauf si c'est votre "vivant" drapeau... c'est à dire: Si vous avez une structure avec 3 pointeurs, et un drapeau en disant: météo la structure est en vie, vous ne réglez que le drapeau et de laisser le pointeur en tant que-est après leur libération.
  • Si vous passez un pointeur vers une fonction qui estime que le pointeur est encore vivante, et il n'est pas, alors que c'est une erreur de logique. Même quand ils ne sont pas la cause directe de la plante, de les éviter n'est pas sans mérite. Il a tendance à faire des modifications plus facile si le code fonctionne comme prévu, plutôt que comme promis. Je ne veux pas dire que vous ne devriez pas régler morts pointeurs à null, mais en disant double suppression n'est jamais une erreur est tout simplement faux.
  • "adressage de mémoire commence à 0" [citation nécessaire]
  • Un plus pinailleurs détail 😬 Un un bits entier signé est composée de deux valeurs: 0 et -1, représenté sous la forme de 0 et de 1 que la seule valeur du bit, respectivement 🙂
  • Paramètre un pointeur à null après la libération il peut cacher double-libre d'erreurs de conception. Ne pas le mettre à null peut en cacher utilisé après libéré des erreurs. Ce dernier est un ordre de grandeur plus graves. Si un pointeur n'est plus valide, vous voulez toute tentative de déférence pour résultat bien défini comportement au lieu d'imprévisible de corruption de la mémoire. Ces bugs sont l'enfer de la piste vers le bas et peut-être un trou de sécurité.

InformationsquelleAutor Joel | 2010-05-03