2 votes

Comment comprendre l'accès à un pointeur NULL lors de l'utilisation de sizeof ?

Vérifiez ceci C programme :

#include <stdio.h>

int main(void) {
        // your code goes here
        char **p = NULL;

        printf("%d,%d\n", sizeof(*p), sizeof(**p));
        return 0;
}

En exécutant le code ci-dessus, le résultat est :

8,1

Bien que p es NULL il ne provoque pas de crash du programme dans sizeof(*p) y sizeof(**p) . Comment comprendre ce comportement ? Est-il assuré dans c spec ?

5voto

Lundin Points 21616

En sizeof est évalué au moment de la compilation. Son opérande n'est pas évalué pour les effets secondaires, votre programme est donc sûr. Ceci est garanti par la norme 6.5.3.4/2 (c'est moi qui souligne) :

Si le type de l'opérande est un type de tableau à longueur variable, la fonction est évalué, sinon, l'opérande n'est pas évalué et le résultat est une constante entière.

(Notez qu'il existe un cas spécial de tableaux à longueur variable, auquel cas l'évaluation a lieu en cours d'exécution, donc le code déréférençant un pointeur invalide vers un VLA à l'intérieur de sizeof ne serait pas sûr).

À titre d'information, le spécificateur de format correct pour printf lors de l'impression du résultat de la commande sizeof es %zu (le résultat de sizeof est le type size_t ).

4voto

WiSaGaN Points 9382

Parce que sizeof(exp) est un opérateur en temps de compilation, et il n'évalue pas l'expression exp au moment de l'exécution.

Par conséquent, il n'y a pas de déréférencement de l'élément NULL au moment de l'exécution. Vous avez simplement le code machine équivalent d'une constante dans vos printf dans votre binaire final.

3voto

John3136 Points 12125

Vous savez p es un char** donc sizeof(*p) == sizeof(char*) - aucune déréférence n'est réellement requise.

Il en va de même pour sizeof(**p) - n'a pas besoin d'effectuer de déréférencement car il peut déterminer la taille au moment de la compilation.

2voto

user6259831 Points 46

L'opérande de sizeof n'est pas évaluée. En d'autres termes, p n'est jamais déféré, donc ce n'est pas un comportement indéfini. Sur un système 64 bits, un pointeur aura une largeur de 8 octets, et un char est toujours de 1 octet, ce qui explique votre résultat.

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