Situation suivante, j'ai une structure contenant des pointeurs à des variables entière comme ceci: est: Je ne vois aucune raison pour que cela soit dysfonctionné, mais j'aimerais que votre Expertise sur elle.
Est-il légal de mettre une référence à la mémoire invalide (avec indice de tableau) dans un tableau comme celui-ci? Ou avez-vous besoin d'un type d'approche différent de cette situation? P> Je n'accède pas au contenu de ces variables avant la première initialisation. P> Merci beaucoup. p> éditer:
Pour le bénéfice des futurs lecteurs: var code> est ininitialisé la première fois que cette structure est remplie. (Comme dans:
null code>)
Peu de temps après (sur la première passe), la variable
var code> sera initialisée et les références seront mises à jour en conséquence. P>
var code> est une variable de pointeur globale, initialisée à NULL au début. L'initialisation le transforme en une matrice en utilisant
nouveau code>. P> p>
3 Réponses :
Je suppose que Je suppose également que Le comportement est indéfini. P>
si une digression: p>
c explicitement dit que fin de digression. P>
Oui, il suffit de calculer une adresse invalide comporte un comportement non défini, même s'il n'est jamais déréférencé. P>
Voici le texte pertinent de la norme ISO C ++ 2011, 5.7 [EXPR.ADD] Paragraphe 5; Remarque particulièrement la fin: p>
Lorsqu'une expression qui a un type intégral est ajoutée ou soustraite
À partir d'un pointeur, le résultat a le type de l'opérande de pointeur. Si la
Pointeur Opérande pointe vers un élément d'un objet de tableau et le tableau
est assez grand, le résultat pointe vers un élément décalé de la
élément original tel que la différence des sous-domes de la
Les éléments de tableau résultants et originaux sont égaux à l'expression intégrale.
En d'autres termes, si l'expression p pointe sur le i-ème élément d'un
objet de tableau, expressions (p) + n (équivalent, n + (p)) et (p) -n
(où n a la valeur n) pointe vers, respectivement, le i + n-e et je
- N-ème éléments de l'objet Array, à condition d'exister. De plus, si
L'expression p pointe sur le dernier élément d'un objet de tableau, le
expression (p) +1 points un après le dernier élément de l'objet Array,
et si l'expression q pointe un après le dernier élément d'un tableau
objet, l'expression (q) -1 pointe du dernier élément de la matrice
objet. Si l'opérande du pointeur et le résultat indiquent des éléments
du même objet de tableau, ou un passé le dernier élément de la matrice
objet, l'évaluation ne doit pas produire de débordement; Sinon, le
le comportement est indéfini. P>
blockQuote> var code> est un objet de pointeur et que sa valeur actuelle est un pointeur null. Ceci est impliqué par votre déclaration: P>
var code> est ininitialisé la première fois que cette structure est remplie. (Comme dans:
null code>) p>
blockQuote>
var code> n'est pas défini à la portée du bloc. S'il est défini à la portée de bloc, et vous n'avez pas été initialisé ni attribué une valeur à celle-ci, sa valeur est une ordures, pas nécessairement une valeur de pointeur NULL, et toute tentative de référence à sa valeur a un comportement indéfini. P>
var == null code>, puis
& var [n] code> a un comportement indéfini. P>
arr [index] code> est par définition équivalent à
* (Arr + index) code>, donc
& var [n] code> est équivalent à
& (* (Var + n)) code>. Le comportement de l'arithmétique du pointeur est défini en termes d'éléments de l'objet de réseau dans lesquels les points de pointeur (avec un seul objet traité comme une matrice d'un élément) et un pointeur null ne souligne rien. P>
& * x code> est évalué sous forme
x code> et
& [x [i]) code> est évalué comme
x + i code>; C ++ ne dit pas cela, de sorte que l'opérande de
& code> doit être valide. C ++ a un cas particulier pour ajouter
0 code>, qui est bien défini, même pour un pointeur NULL (C n'a pas de cas particulier). Mais
& var [0] code> est toujours invalide dans C et C ++, mais pour différentes raisons. Dans C, il est équivalent à
var + 0 code>, mais ajouter
0 code> sur un pointeur NULL a un comportement non défini. En C ++, il est pas em> équivalent à
var + 0 code>; il est plutôt équivalent à
& (* (var + 0)) code>;
var + 0 code> est un pointeur NULL et la désirficite qu'il a un comportement non défini.) P>
Pouvez-vous fournir la référence lors de l'arithmétique sur le pointeur NULL est interdit? Ou suis-je mal compris ce que tu dis?
Mais si var code> est un tableau et non un pointeur, il ne devrait y avoir aucun problème.
@MarkB, il a à voir avec les définitions légales de null code>. Si
NULL code> est défini comme
((vide *) 0) code> (légal en C, illégal en C ++), puis faire de l'arithmétique sur elle est illégale. (Et évidemment, si
null code> est défini comme juste
0 code>, puis
null + 0 code> est légal.)
De plus, null + 1 code> devrait être très bien en C ++. Essayer d'utiliser les résultats pour initialiser un pointeur ne fonctionnera pas, car
0 + 1 code> peut être une expression constante intégrale, mais elle n'évalue pas à 0.
Puis-je demander pourquoi null + 0 code> n'est pas défini dans C? Afaik
null code> est juste
0 code>, et il semble donc comme
0 + 0 code> devrait être
0 code> aussi ... non?
@Vladlazarenko in c, null code> peut aussi être
((vide *) 0) code>. (Ce n'est pas le cas, traditionnellement, et je ne pense pas que de nombreux compilateurs le définissent de cette façon, mais il y en a un peu - c'était la définition traditionnelle sous MS-DOS, par exemple.).
@Jameskanze: Cela n'a pas à voir avec la définition du null code> macro. L'OP dit que
var code> est ininitialisé "comme dans:
null code>". L'arithmétique est effectuée sur un objet pointeur, non sur une constante de pointeur NULL, et l'arithmétique sur une valeur de pointeur NULL (autre que l'ajout
0 code>) est indéfini.
"(C affirment explicitement que & * x est évalué comme x x, et & & [x [i]) est évalué comme x + i; C ++ ne le dit pas, de sorte que l'opérande de & doit être valide.)" On dirait que Cela signifie même & var [0] code> n'est pas valide en C ++ lorsque
var code> est un pointeur NULL.
Merci pour l'explication approfondie. Je ferai la chose sensible et simplement déclarer le tableau après le bloc avec l'initialisation des variables globales ... Vous savez, où les références seront réellement utilisées.
@Ataylor: Vous n'avez jamais vraiment dit comment et où var code> est déclaré.
@Keiththompson var est, dans la mesure où vous avez correctement déduit, une variable globale, initialisée à «NULL» lors du démarrage du programme et sera initialisée lors de la première utilisation (et réinitialisée lors de la reconstruction du menu)
@Ataylor: Pour le bénéfice des futurs lecteurs, veuillez mettre à jour votre question avec ces informations.
Puisque vous n'utilisez pas les valeurs qu'après le premier passage, faites la bonne chose et initialisez les pointeurs de votre structure à NULL à la place. Ensuite, mettez les bonnes valeurs lorsque vous les connaissez. Si vous prenez cette approche, votre problème «est-ce légal» disparaît! P>
+1. En fait, structure de structure [2]; code> est assez assez. Si les résultats de l'initialisation ne sont jamais utilisés, cette initialisation n'est pas nécessaire.
Pour répondre à la question spécifique (oubli du code exemple): Oui, vous pouvez avoir une référence à une mémoire ininitialisée, vous ne pouvez tout simplement pas Déréférence em> it et attendre un comportement défini. P>
Je suis raisonnablement certain que la réponse est non et que certains optimiseurs vont casser votre code.
"Ou dois-je avoir un type d'approche différent pour cette situation?" Hmm, peut-être, initialiser la variable?
@Danieldaranas je suis. Cependant, seulement après que le tableau a été rempli. C'est une fonction qui s'appelle plusieurs fois.
@Slaks merci pour votre contribution. J'y penserai d'autres, peut-être que je trouverai une approche moins risquée.
Est
var code> une référence ou un pointeur?
Vous ne pouvez pas lire de la mémoire ininitialisée et vous attendre à ce que des choses sensibles se produisent.
Qu'est-ce qui est ininitialisé,
var code> ou
var [0] code>? Si
var code> est initialisé pour pointer vers "une région de mémoire qui est ininitialisée", votre code est correct.
Pouvez-vous mettre à jour votre question pour nous montrer la déclaration de
var code>?
Si
var code> a type
t [4] code>, il n'y a pas de problème.
@Jameskanze: Un, délicat, que: Comment une expression de type
t [4] code> a une valeur
null code>?
La norme indique explicitement qu'une référence doit être initialisée à un objet valide et qu'aucune autre chose qu'une référence à NULL ne peut exister dans un programme bien formé. Ce qui ne signifie pas que cela pourrait ne pas fonctionner de toute façon.
Si
var code> est un point inaidifié pointeur i> alors c'est UB dans toutes les directions. S'il s'agit d'un tableau i> de type
t code> avec un contentement ininitialisé i> alors c'est un comportement défini tant que vous ne lisez I> Le contenu des adresses stockées dans votre structure (ou dans
var code>) jusqu'à ce que le stockage des emplacements susmentionnés eux-mêmes i> a été initialisé. Sans plus d'informations sur le type de
var code> thats sur aussi profondez un commentaire que je peux offrir.
Attendez. Vous dites que
var code> est ininitialisé ("comme dans:
null code>"). Si
var code> est défini à la portée du bloc et est ininitialisé, sa valeur est une poubelle, pas nécessairement
null code>. Si c'est défini ailleurs, c'est implicitement initialisé à zéro, c'est-à-dire à une valeur de pointeur nulle. Veuillez mettre à jour votre question pour me montrer comment et où i>
var code> est défini.