Combien de niveaux de pointeurs peut-on avoir?
Combien de pointeurs (*
) sont autorisés dans une seule variable?
Considérons l'exemple suivant.
int a = 10;
int *p = &a;
De la même façon que nous pouvons avoir
int **q = &p;
int ***r = &q;
et ainsi de suite.
Par exemple,
int ****************zz;
- Si cela devient un réel problème pour vous, vous faites quelque chose de très mal.
- Techniquement il n'y a probablement pas de limite (bien que c'est le compilateur spécifique). La véritable limite est celle de votre (et vos collègues de travail') capacité mentale de garder une trace de ce que votre variable représente en fait. Et en respectant le code lisible est généralement plus important que le faible niveau d'optimisation. De ce point de vue, dans le code de production déjà triple indirection (par exemple
int***
) n'est pas recommandée dans la plupart des cas. - Vous pouvez continuer à ajouter des niveaux de pointeurs jusqu'à ce que votre cerveau explose ou le compilateur fond - selon ce qui se produit en peu de temps.
- Depuis un pointeur vers un pointeur est nouveau, eh bien, juste un pointeur, il ne devrait pas y avoir de limite théorique. Peut-être que le compilateur ne pas être en mesure de la traiter au-delà de certains ridiculement haute limite, mais bon...
- avec le nouveau c++, vous devez utiliser quelque chose comme
std::shared_ptr<shared_ptr<shared_ptr<...shared_ptr<int>...>>>
- Peut-être un "décoré commentaire" a obtenu hors de contrôle et a tiré cette question 🙂
- Pourquoi ne pas simplement écrire un programme simple pour le tester sur votre compilateur? Quelle que soit répondu par d'autres, est susceptible de ne pas correspondre exactement à votre environnement.
- Pourquoi? Ce qui est si destructeur (ou non constructive ) à ce sujet?
- les pires conseils possibles, il peut compiler et d'échouer dans la prochaine version ou il peut échouer maintenant à un bug du compilateur. vérifiez la documentation du compilateur, vérifiez la norme et en dernier recours, de vérifier la mise en œuvre actuelle.
- il peut faire sens pour les générateurs de code...
- cela montre un problème dans la norme C++ - il n'y a aucun moyen pour augmenter les pointeurs intelligents de pouvoirs. Nous devons immédiatement à la demande d'une extension à l'appui par exemple
(pow (std::shared_ptr, -0.3))<T> x;
pour -0.3 niveaux d'indirection. - Il dépend de la mémoire de votre système. Si elle excède, le système se bloque. Sinon, elle est infinie. Vous pouvez essayer avec
while(1)
. - Mmmm, nah. C'est sur le sujet. Et si l'un de vous reddit les gens veulent aller à travers mes questions/réponses et massivement upvote eux, n'hésitez pas!
- le lien que vous avez fourni est de l'or, juste de l'or pur.
- J'ai eu la "joie" de maintenir un trois étoiles du programmeur base de code. Il avait aussi une tendance à traiter toutes les conditions d'erreur avec
exit(0)
(et rien d'autre, pas même un printf). - Assurez-vous que votre réponse appartient ici?
- yupe n'êtes-vous pas sûr
- semble être la bonne façon de force de code spaghetti au rpc 🙂
- bien logiquement, il ne ferait aucun sens de créer des pointeurs à cette n niveau. Le compilateur n'a pas de problèmes, mais votre programme si elle utilise des
- jamais entendu parler de la parole, mais reconnaissons donc beaucoup de programmeurs que je l'ai rencontré à travers les années. Merci pour le partage de cette brillante lien.
- J'ai été taquiné pour l'écriture de 3-étoiles code de once upon a time. Si c'était en fait un tableau d'adresses de chaînes... qui est (dans mon esprit) très différente de pointeur de pointeur de pointeur de char, comme j'ai été accusé de. [soupir] je serais encore défendre ce code.
- Je sais que beaucoup de 3-étoiles programmeurs. Ils sont quantique des chimistes du programme 4D tableaux dans le naïf, mais courants de la mode.
- Tu veux dire, comme ça? coliru.stacked-crooked.com/a/92a6666764acbaff 😀
- Notez qu'il existe un assez commun pointeur qui est généralement écrit avec trois niveaux: char*** argv (ou souvent écrit en tant que char** argv[]). Par exemple, c'est exactement la façon dont vous call MPI_Init (et d'autres fonctions qui peuvent changer votre argv lors du passage).
- Une fois, j'ai dû utiliser un
void****
dans un véritable programme de vie. - Tout programme qui nécessite de nombreux niveaux de pointeurs [1] probablement très inefficace et [2] a probablement beaucoup de bugs. Il suffit de coller avec une ou deux couches de pointeurs.
- Dire que pour Microsoft 🙂 L'objet en question a été le pointeur vers un pointeur intelligent autour d'un pointeur d'interface COM, qui a effectivement des points à un pointeur vers un tableau de pointeurs de fonction. Avec moi encore? 🙂
Vous devez vous connecter pour publier un commentaire.
La
C
norme spécifie la limite inférieure:La limite supérieure est de la mise en œuvre spécifique.
typedef
s.En fait, les programmes en C font fréquemment usage de l'infini pointeur d'adressage indirect. Un ou deux statique niveaux sont communs. Triple indirection est rare. Mais l'infini est très commun.
Infini pointeur d'adressage est réalisé avec l'aide d'un struct, bien sûr, pas un accès direct à un jugement de nullité, ce qui serait impossible. Et une structure est nécessaire de sorte que vous pouvez inclure d'autres données dans cette structure à différents niveaux où cela peut se terminer.
maintenant vous pouvez avoir
list->next->next->next->...->next
. C'est vraiment juste plusieurs pointeur indirections:*(*(..(*(*(*list).next).next).next...).next).next
. Et le.next
est fondamentalement un noop quand il est le premier membre de la structure, de sorte que nous pouvons imaginer ce que***..***ptr
.Il n'y a vraiment pas de limite sur ce point car les liens peuvent être parcourus avec une boucle plutôt qu'un géant de la manifestation de ce genre, et de plus, la structure peut être facilement fait en circulaire.
Donc, en d'autres termes, les listes liées peut-être l'exemple ultime de l'ajout d'un autre niveau d'indirection pour résoudre un problème, puisque vous le faites de façon dynamique à chaque opération push. 🙂
list->next
etlist->next->next
sont du même type; sinon, nous avons de construire une infinité de type.)struct list *
) et un seul pointeur déréférencé à un moment, chaque collier par un "presque aucun op". (Comme cela a déjà été pratiquement souligné, mais bon.)*******x
est un à la fois, exactement commex->next->next->next->next
.LOAD R1, [R1]
tant que R1 est un pointeur valide à chaque étape. Il n'existe pas de types autres que "la parole qui est titulaire d'une adresse". Qu'il existe ou non déclaré types ne détermine pas l'indirection et de la façon dont de nombreux niveaux.R1
contient l'adresse de l'emplacement qui pointe vers lui-même, puisLOAD R1, [R1]
peut être exécutée dans une boucle infinie.->next
éléments est contrôlée par le programmeur; gérer*****....*****int
le compilateur a interne à représenter la profondeur de l'pointeurs (de sorte qu'il peut détecter les erreurs de déréférencement). Certaines façons de stocker cette représentation ne peut être limité par la mémoire (utilisé par le compilateur), mais d'autres méthodes peuvent avoir des limites strictes.*P
sont à la fois la syntaxe. Comment profondément que la syntaxe est imbriquée est contrôlée par le programmeur. Le compilateur doit représenterP->memb->memb->memb->memb...
et il a de représenter***..P
.P->next
qui arrive à point à un autreP
, le compilateur ne doit connaître que c'est un pointeur vers la structure mère. À compilation il ne se soucie pas combien de temps une chaîne de liens à des éléments que vous créez lors de l'exécution. Pour*****int
, le compilateur au moment de la compilation représente le type pour tous les niveaux ... c'est*****int
est un pointeur vers une****int
qui points à***int
... pour un*int
qui enfin des points pour unint
. Pour certains compilateurs, en vertu de l' certains conditions, il peut manquer d'espace pour le faire.DEREFI(DEREFV(DEREFV...(DEREFV(P)) ...))
oùP
est unvoid *
pointeur,DEREFV
est#define DEREFV(P) (*((void **) (P)))
etDEREFI
est similaire, mais avec un casting deint *
. I. e. arbitrairement une longue chaîne devoid *
pointeurs qui pointent versvoid *
, et enfin unint
.Théoriquement:
Vous pouvez avoir autant de niveaux d'indirections que vous le souhaitez.
Pratiquement:
Bien sûr, rien de ce qui consomme de la mémoire peut être de durée indéterminée, il y aura des limitations en raison des ressources disponibles sur l'hôte de l'environnement. Donc, pratiquement il y a une limite maximale à ce qu'une mise en œuvre peut prendre en charge et la mise en œuvre du document de manière appropriée. Donc, dans tous ces artefacts, la norme ne précise pas la limite maximale, mais il ne précise pas les limites les plus basses.
Voici la référence:
Standard C99 5.2.4.1 Traduction limites:
Spécifie la limite inférieure que chaque mise en œuvre doit de soutien. Notez que dans un footenote la norme dit encore:
*
est surchargé pour un nombre de classes dans une rangée, et chaque surcharge retourne un objet d'un autre type dans la ligne, puis il peut être stackoverflow pour ces enchaîné les appels de fonction.*
sQue les gens ont dit, pas de limite "en théorie". Cependant, l'intérêt, j'ai couru ce avec g++ 4.1.2, et il a travaillé avec la taille jusqu'à 20 000. La compilation est assez lent, donc je n'ai pas essayé plus haut. Donc je suppose g++ n'impose pas de limite non plus. (Essayez de définir
size = 10
et à la recherche dans ptr.cpp si elle n'est pas immédiatement évident.)g++ create.cpp -o create ; ./create > ptr.cpp ; g++ ptr.cpp -o ptr ; ./ptr
create.cpp
*
jusqu'à ce que j'en ai eu un qui a échoué, et la précédente qui se passait; j'ai ensuite fait une recherche binaire sur cet intervalle pour la première celui qui a échoué. L'ensemble de l'essai a duré moins d'une seconde pour fonctionner.)Amusant à vérifier.
Visual Studio 2010 (sur Windows 7), vous pouvez avoir 1011 niveaux avant d'obtenir cette erreur:
gcc (Ubuntu),+ de 100k
*
sans crash ! Je suppose que le matériel est la limite ici.(testé avec juste une déclaration de variable)
*
nœuds sur la pile avant d'être en mesure de faire une réduction.Il n'y a pas de limite, vérifier exemple ici.
La réponse dépend de ce que tu veux dire par "niveaux de pointeurs." Si vous voulez dire "Combien de niveaux d'indirection que vous pouvez avoir dans une seule déclaration?", la réponse est "Au moins 12."
Si vous voulez dire "Combien de niveaux de pointeur que vous pouvez utiliser avant que le programme devient difficile à lire," c'est une question de goût, mais il y a une limite. Avoir deux niveaux d'indirection (un pointeur vers un pointeur vers quelque chose) est commun. Pas plus que cela devient un peu plus difficile à penser facilement; ne pas le faire à moins que l'alternative serait pire.
Si vous voulez dire "Combien de niveaux d'indirection de pointeur que vous pouvez avoir lors de l'exécution," il n'y a pas de limite. Ce point est particulièrement important pour les circulaires des listes, dans lequel chacun des points de nœud à l'autre. Votre programme peut suivre les pointeurs pour toujours.
g++
échoue avec une erreur interne au 98242 sur ma machine. Je pense que la limite réelle dépendra de la machine et de la charge. J'ai aussi ne vous attendez pas à être un problème dans le code réel.)circ_list
exemple en ce qui concerne l'OP question: Le fait que vous pouvez parcourir une liste de pointeurs ne signifie pas que le compilateur peut compiler un n-étoiles indirection.C'est même plus drôle avec le pointeur de fonctions.
Comme illustré ici cela donne:
Et il n'implique pas de gestion d'exécution, de sorte que vous pouvez probablement les empiler autant que vous voulez... jusqu'à ce que votre compilateur étouffe sur le fichier.
Il est pas de limite. Un pointeur est une partie de la mémoire dont le contenu est une adresse.
Comme vous l'avez dit
Un pointeur vers un pointeur est également une variable qui contient une adresse d'un autre pointeur.
Ici
q
est pointeur de pointeur de la tenue de l'adresse dep
qui est déjà en tenant l'adresse dea
.Il n'y a rien de particulier un pointeur vers un pointeur.
Il n'y a pas de limite sur la chaîne de poniters qui sont la tenue de l'adresse d'un autre pointeur.
ie.
est autorisé.
Remarque qu'il y a deux questions: combien de niveaux d'indirection de pointeur, nous pouvons réaliser dans un de type C, et combien de niveaux d'indirection de pointeur, nous pouvons trucs en une seule déclaration.
Le C standard permet un maximum pour être imposé à l'ancienne (et donne une valeur minimale pour que). Mais qui peut être contournée par le biais de multiples typedef déclarations:
Donc, finalement, c'est une question de mise en œuvre connecté à l'idée de savoir comment grand/complexe peut faire un programme en C avant de est rejetée, ce qui est très compilateur spécifique.
Chaque développeur C++ doit avoir entendu parler du fameux Trois étoiles programmeur
Et il semble vraiment y avoir un peu de magie "pointeur de la barrière" qui doit être camouflé
Je tiens à souligner que la production d'un type avec un nombre arbitraire de " * " est quelque chose qui peut arriver avec le modèle de la métaprogrammation. J'oublie ce que je faisais exactement, mais il a été suggéré que je pourrais produire de nouveaux types distincts qui ont une sorte de méta de manœuvre entre eux à l'aide de récursive T* types.
Modèle de la Métaprogrammation est une lente descente dans la folie, de sorte qu'il n'est pas nécessaire de faire des excuses lors de la génération d'un type avec plusieurs milliers de niveau d'indirection. C'est juste un moyen pratique pour la carte des entiers de peano, par exemple, sur le modèle de l'expansion comme un langage fonctionnel.
De la règle 17.5 de l'2004 MISRA C norme interdit plus de 2 niveaux d'indirection de pointeur.
"non-compliant"
à leurs normes. Le mot ou la phrase dans sa décision, est l'utilisation du mot"should"
à partir de cette déclaration:Use of more than 2 levels of indirection can seriously impair the ability to understand the behavior of the code, and should therefore be avoided.
ce sont des lignes directrices établies par cette organisation plutôt que sur des règles définies par la norme du langage.Il n'y a pas une telle chose comme véritable limite mais limite existe. Tous les pointeurs sont des variables qui sont généralement le stockage dans la pile pas de tas. La pile est généralement de petite taille (il est possible de changer sa taille au cours de certaines de liaison). Donc, disons que vous avez de 4MO de la pile, ce qui est tout à fait normal de taille. Et disons que nous avons pointeur qui est de 4 octets taille de pointeur (tailles ne sont pas les mêmes en fonction de l'architecture, de la cible et les paramètres du compilateur).
Dans ce cas
4 MB /4 b = 1024
donc possible nombre maximal serait 1048576, mais nous ne devons pas ignorer le fait que quelques autres trucs est dans la pile.Cependant, certains compilateurs peuvent avoir un nombre maximum de pointeur de la chaîne, mais la limite est la taille de la pile. Donc, si vous augmentez la taille de la pile lors de la liaison avec l'infini et de la machine avec l'infini de la mémoire qui exécute le système d'exploitation qui gère la mémoire de sorte que vous aurez illimité pointeur de la chaîne.
Si vous utilisez
int *ptr = new int;
et placez votre pointeur dans le tas, ce n'est pas si d'habitude façon dont la limite serait de la taille du segment, pas de pile.MODIFIER Viens de réaliser que
infinity /2 = infinity
. Si la machine dispose de plus de mémoire de sorte que le pointeur de la taille augmente. Donc, si la mémoire est l'infini et de la taille du pointeur est l'infini, de sorte qu'il est de mauvaises nouvelles... 🙂new int*
). B) Unint*
et unint**********
ont la même taille, au moins sur des architectures.int*
et unint**********
ont la même taille, je n'ai pas dit qu'ils ont de différent.new *int
, désolé, pour Un, vous avez raisonCela dépend de l'endroit où vous stocker des pointeurs. Si ils sont dans la pile que vous avez assez faible limite. Si vous les conservez au tas, vous limite est beaucoup, beaucoup beaucoup plus.
Regarder ce programme:
Il crée 1M pointeurs et à la montre à quel point, à ce qu'il est facile de remarquer que la chaîne passe à la première variable
number
.BTW. Il utilise
92K
de RAM alors imaginez à quelle profondeur vous pouvez aller.