Question Pourquoi sizeof (x ++) n'incrémente pas x?


Voici le code compilé dans dev c ++ windows:

#include <stdio.h>

int main() {
    int x = 5;
    printf("%d and ", sizeof(x++)); // note 1
    printf("%d\n", x); // note 2
    return 0;
}

Je m'attends à x être 6 après l'exécution note 1. Cependant, le résultat est le suivant:

4 and 5

Quelqu'un peut-il expliquer pourquoi x n'augmente pas après note 1?


467
2017-11-22 11:07


origine


Réponses:


Du Norme C99 (l'accent est à moi)

6.5.3.4/2

L'opérateur sizeof donne la taille (en octets) de son opérande, qui peut être une expression ou le nom entre parenthèses d'un type. La taille est déterminée à partir du type de l'opérande. Le résultat est un entier. Si le type de l'opérande est un type de tableau de longueur variable, l'opérande est évalué; autrement, l'opérande n'est pas évalué et le résultat est une constante entière.


500
2017-11-22 11:11



sizeof est un opérateur de compilation, alors au moment de la compilation sizeof et son opérande sont remplacés par la valeur du résultat. le l'opérande est non évalué (sauf s'il s'agit d'un tableau de longueur variable) seulement le type du résultat compte.

short func(short x) {  // this function never gets called !!
   printf("%d", x);    // this print never happens
   return x;
}

int main() {
   printf("%d", sizeof(func(3))); // all that matters to sizeof is the 
                                  // return type of the function.
   return 0;
}

Sortie:

2

comme short occupe 2 octets sur ma machine.

Changer le type de retour de la fonction en double:

double func(short x) {
// rest all same

va donner 8 en sortie.


175
2017-11-22 11:10



sizeof(foo) essaie vraiment de découvrir la taille d'une expression au moment de la compilation:

6.5.3.4:

L'opérateur sizeof donne la taille (en octets) de son opérande, qui peut être un   expression ou le nom entre parenthèses d'un type. La taille est déterminée à partir du type de   l'opérande. Le résultat est un entier. Si le type de l'opérande est un tableau de longueur variable   type, l'opérande est évalué; sinon, l'opérande n'est pas évalué et le résultat est un   constante entière.

En bref: tableaux de longueur variable, exécutés au moment de l'exécution. (Remarque: Tableaux à longueur variable sont une caractéristique spécifique - pas des tableaux alloués avec malloc(3).) Sinon, seul le type de l'expression est calculée, et cela au moment de la compilation.


46
2017-11-22 11:13



sizeof est un opérateur intégré à la compilation et est ne pas une fonction. Cela devient très clair dans les cas où vous pouvez l'utiliser sans la parenthèse:

(sizeof x)  //this also works

33
2017-11-22 13:32



Remarque

Cette réponse a été fusionnée à partir d'un duplicata, ce qui explique la date tardive.

Original

À l'exception de tableaux de longueur variable  taille de n'évalue pas ses arguments. Nous pouvons le voir dans le projet de section standard C99 6.5.3.4  L'opérateur sizeof paragraphe 2 qui dit:

L'opérateur sizeof donne la taille (en octets) de son opérande, qui peut être un   expression ou le nom entre parenthèses d'un type. La taille est déterminée à partir du type de   l'opérande. Le résultat est un entier. Si le type de l'opérande est un tableau de longueur variable   tapez, l'opérande est évalué; sinon, l'opérande n'est pas évalué et le résultat est un   constante entière.

Un commentaire(maintenant enlevé) a demandé si quelque chose comme ceci évaluerait au moment de l'exécution:

sizeof( char[x++]  ) ;

et en effet, quelque chose comme ça fonctionnerait aussi (Les voir tous les deux vivre):

sizeof( char[func()]  ) ;

car ils sont tous les deux des tableaux de longueur variable. Bien que, je ne vois pas beaucoup d'utilisation pratique dans l'un ou l'autre.

Remarque: les tableaux de longueur variable sont couverts dans le projet de norme C99 section 6.7.5.2  Array declarators paragraphe 4:

[...] Si la taille est une expression constante et que le type d'élément a une taille constante connue, le type de tableau n'est pas un type de tableau de longueur variable; sinon, le type de tableau est un type de tableau de longueur variable.

Mettre à jour

En C11 la réponse change pour le cas VLA, dans certains cas il n'est pas spécifié si l'expression de taille est évaluée ou non. De la section 6.7.6.2  Les déclarateurs de tableau qui dit:

[...] Où une expression de taille fait partie de l'opérande d'une tailleof   opérateur et la modification de la valeur de l'expression de taille ne serait pas   affecter le résultat de l'opérateur, il n'est pas précisé si   l'expression de taille est évaluée.

Par exemple dans un cas comme celui-ci (le voir en live):

sizeof( int (*)[x++] )

18
2018-02-24 18:14



Comme l'opérande de sizeof l'opérateur n'est pas évalué, vous pouvez le faire:

int f(); //no definition, which means we cannot call it

int main(void) {
        printf("%d", sizeof(f()) );  //no linker error
        return 0;
}

Démonstration en ligne: http://ideone.com/S8e2Y

C'est-à-dire que vous n'avez pas besoin de définir la fonction f s'il est utilisé dans sizeof seulement. Cette technique est principalement utilisée dans la métaprogrammation de template C ++, car même en C ++, l'opérande de sizeof n'est pas évalué.

Pourquoi cela fonctionne-t-il? Cela fonctionne parce que le sizeof l'opérateur ne fonctionne pas sur valeur, à la place, il fonctionne sur type de l'expression. Donc, quand vous écrivez sizeof(f()), il fonctionne sur le type de l'expression f(), et qui n'est rien d'autre que le type de retour de la fonction f. Le type de retour est toujours le même, quelle que soit la valeur que la fonction retournerait si elle s'exécutait réellement.

En C ++, vous pouvez même faire ceci:

struct A
{
  A(); //no definition, which means we cannot create instance!
  int f(); //no definition, which means we cannot call it
};

int main() {
        std::cout << sizeof(A().f())<< std::endl;
        return 0;
}

Pourtant, on dirait, en sizeof, Je crée d'abord une instance de A, en écrivant A(), puis appelant la fonction f sur l'instance, en écrivant A().f(), mais une telle chose n'arrive pas.

Démonstration http://ideone.com/egPMi

Voici un autre sujet qui explique d'autres propriétés intéressantes de sizeof:


10
2017-11-23 04:35



L'exécution ne peut pas avoir lieu pendant la compilation. Alors ++i/i++ ça n'arrivera pas. Aussi sizeof(foo()) n'exécutera pas la fonction mais retournera le bon type.


9
2017-11-22 14:37



sizeof() l'opérateur donne uniquement la taille du type de données, il n'évalue pas les éléments internes.


0
2018-01-22 09:52