2017-07-26 3 views
2

j'ai appris par this question que incrémenter un pointeur NULL ou incrémenter après la fin d'un tableau est un comportement bien défini:Est-ce que comparer à un pointeur un élément après la fin d'un tableau bien défini?

int* pointer = 0; 
pointer++; 

int a[3]; 
int* pointer2 = &a[0]; 
pointer2 += 4; 

Mais si le pointeur pointant vers un endroit non valide est utilisé uniquement à titre de comparaison et la mémoire à son emplacement n'est jamais accessible?

Exemple:

void exampleFunction(int arrayLen, char** strArray) 
{ 
    for(char** str = strArray; str < strArray + arrayLen; str++) //or even str < &strArray[arrayLen] 
    { 
     //here *str is always a pointer to the first char of my string 
    } 
} 

Ici, je compare mon pointeur à un pointeur un élément après la fin du tableau. Est-ce un comportement bien défini?

+0

Quand l'expression '* argv + argc' aurait-elle un sens? La longueur de 'argv [0]' n'est pas liée à 'argc'. Si vous voulez dire 'argv + argc', c'est bien AIUI parce que les pointeurs" un élément après la fin du tableau "sont bien définis et peuvent être comparés à d'autres pointeurs dans le même tableau. (Ou 'argv + argc + 1' car, comme chux mentionné,' argv' se termine par 'NULL'.) – Ryan

+0

@chux Bon à savoir! Je dois juste utiliser '<=' alors. Mais la question initiale ne devrait pas prendre mon erreur en considération. Mise à jour avec un meilleur exemple – Winter

+0

Votre deuxième code est OK car 'str' est toujours un pointeur valide. Cette dernière valeur n'est cependant pas dé-référencée. – chux

Répondre

4

En comparant à un pointeur une étape après la fin d'un tableau est bien définie. Cependant, vos exemples pointer et pointer2 ne sont pas définis, même si vous ne faites littéralement rien avec ces pointeurs.

Un pointeur peut pointer vers un élément après la fin du tableau. Ce pointeur ne peut pas être déréférencé (sinon ce serait undefined behavior) mais peut être comparé à un autre pointeur dans le tableau.

Section 6.5.6 du C standard dit ce qui suit en ce qui concerne l'addition de pointeur:

Si les deux opérandes de pointeur et le point de résultat aux éléments du même objet tableau, ou un passé la dernière élément du tableau objet, l'évaluation ne doit pas produire un débordement; sinon, le comportement est indéfini. Si le résultat dépasse le dernier élément de l'objet tableau, il ne doit pas être utilisé comme opérande d'un opérateur * unaire évalué.

article 6.5.8 dit ce qui suit au sujet des comparaisons de pointeur:

Lorsque deux pointeurs sont comparés, le résultat dépend des emplacements relatifs à l'espace d'adressage des objets mis en évidence. Si deux pointeurs vers des types d'objet pointent tous deux vers le même objet, ou les deux point après le dernier élément du même objet tableau, ils comparent égal. Si les objets pointés sont des membres du même objet agrégé , les pointeurs vers les membres de structure déclarés plus tard comparent plus grand que les pointeurs aux membres déclarés plus tôt dans la structure et pointeurs vers des éléments de tableau avec des valeurs d'indice plus élevées comparent supérieur aux pointeurs vers éléments du même tableau avec des valeurs d'indice inférieures. Tous les pointeurs vers les membres du même objet union comparer égal. Si l'expression P pointe vers un élément d'un tableau objet et l'expression Q pointe vers le dernier élément du même objet tableau , l'expression de pointeur Q + 1 compare plus de P. Dans tous les autres cas, le comportement est indéfini.

+1

La règle "un passé" ne s'applique-t-elle pas également aux objets non-tableaux? 'int x; int * p = &x+1; ' – chux

+1

@chux Vous avez peut-être raison. Section 6.5.8 partie 4 indique * "Pour les besoins de ces opérateurs, un pointeur vers un objet qui n'est pas un élément d'un tableau se comporte comme un pointeur vers le premier élément d'un tableau de longueur 1 avec le type de l'objet comme type d'élément. * "La section 6.5.6 partie 7 a le même libellé. – dbush

+0

Le 6.5.8 cité s'applique à '<', '<=', '> =', et '>'. Les opérateurs '==' et '! =' Ne donnent jamais de comportement indéfini quand on leur donne des pointeurs sur des objets, des pointeurs "juste après" des objets, ou des pointeurs NULL. Une comparaison entre un pointeur "vers" un objet et un pointeur "juste après" un autre peut signaler une égalité, mais cela ne signifie pas que les pointeurs peuvent être utilisés de manière interchangeable. – supercat