Voici le code compilé dans les fenêtres dev c ++:
#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
à avoir 6 ans après avoir exécuté la note 1 . Cependant, la sortie est:
4 and 5
Quelqu'un peut-il expliquer pourquoi x
n'augmente pas après la note 1 ?
VLAs
où aucune des autres ne le fait.Réponses:
De la norme C99 (l'accent est mis sur moi)
la source
N
depuis stdin et makeint array[N]
. C'est l'une des fonctionnalités de C99, non disponible en C ++.sizeof(int[++x])
(vraiment, vraiment une mauvaise idée, de toute façon) le++
pourrait être évalué.gcc
,clang
et à ideone.com/Pf7iFsizeof
est un opérateur au moment de la compilation, donc au moment de la compilationsizeof
et son opérande sont remplacés par la valeur du résultat. L' opérande n'est pas évalué (sauf lorsqu'il s'agit d'un tableau de longueur variable); seul le type de résultat compte.Production:
car
short
occupe 2 octets sur ma machine.Modification du type de retour de la fonction en
double
:donnera
8
en sortie.la source
sizeof(foo)
essaie vraiment de découvrir la taille d'une expression au moment de la compilation:6.5.3.4:
En bref: tableaux de longueur variable, exécutés au moment de l'exécution. (Remarque: les tableaux de longueur variable sont une fonctionnalité spécifique - pas les tableaux alloués avec
malloc(3)
.) Sinon, seul le type de l'expression est calculé, et cela au moment de la compilation.la source
sizeof
est un opérateur intégré à la compilation et n'est pas une fonction. Cela devient très clair dans les cas où vous pouvez l'utiliser sans les parenthèses:la source
sizeof
opérateur n'est pas un opérateur à la compilation, il suffit de lui donner un VLA pour le comprendre.Remarque
Cette réponse a été fusionnée à partir d'un doublon, ce qui explique la date tardive.
Original
À l'exception des tableaux de longueur variable, sizeof n'évalue pas ses arguments. Nous pouvons le voir dans le projet de section standard C99
6.5.3.4
Le paragraphe 2 de l' opérateur sizeof qui dit:Un commentaire ( maintenant supprimé ) a demandé si quelque chose comme ça évaluerait au moment de l'exécution:
et en effet cela fonctionnerait, quelque chose comme ça fonctionnerait aussi (les voir en direct ):
car ils sont tous deux des tableaux de longueur variable. Cependant, je ne vois pas beaucoup d'utilisation pratique dans l'un ou l'autre.
Remarque, les tableaux de longueur variable sont traités dans le projet de section standard C99
6.7.5.2
Déclarateurs de tableau, paragraphe 4 :Mise à jour
Dans 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. Extrait de la section
6.7.6.2
Déclarateurs de tableaux qui dit:Par exemple dans un cas comme celui-ci ( voir en direct ):
la source
sizeof
c'est effectivement une macro - elle ne crée pas de code, mais pré-calcule la valeur attendue et la dépose directement dans le code. Notez que c'était le seul comportement jusqu'à C99, car les VBA n'existaient pas (je n'en avais jamais entendu parler avant cette réponse, croyez-le ou non!)sizeof (char[x++]);
utiliserait la valeur dex
pour autre chose que la détermination de la valeur de l'expressionx++
et de la nouvelle valeur pourx
, qui sont toutes deux normales avec cet opérateur?char[x++]
un VLA. il ressemble effectivement à unchar*
à mes yeux inconnus.Comme l'opérande d'
sizeof
opérateur n'est pas évalué, vous pouvez le faire:Démo en ligne: http://ideone.com/S8e2Y
Autrement dit, vous n'avez pas besoin de définir la fonction
f
si elle est utiliséesizeof
uniquement. Cette technique est principalement utilisée dans la métaprogrammation de modèles C ++, car même en C ++, l'opérande desizeof
n'est pas évalué.Pourquoi ça marche? Cela fonctionne parce que l'
sizeof
opérateur n'opère pas sur la valeur , mais opère sur le type de l'expression. Ainsi, lorsque vous écrivezsizeof(f())
, il opère sur le type de l'expressionf()
, et qui n'est rien d'autre que le type de retour de la fonctionf
. Le type de retour est toujours le même, quelle que soit la valeur que la fonction retournerait si elle s'exécute réellement.En C ++, vous pouvez même ceci:
Pourtant, il semble que, dans
sizeof
, je crée d'abord une instance deA
, en écrivantA()
, puis j'appelle la fonctionf
sur l'instance, en écrivantA().f()
, mais rien de tel ne se produit.Démo: http://ideone.com/egPMi
Voici un autre sujet qui explique quelques autres propriétés intéressantes de
sizeof
:la source
L'exécution ne peut pas se produire pendant la compilation. Donc
++i
/ çai++
n'arrivera pas. N'exécuterasizeof(foo())
pas non plus la fonction mais renverra le type correct.la source
sizeof
une expression de constante de temps de compilation"?sizeof
s'exécute au moment de la compilation, maisx++
ne peut être évalué qu'au moment de l'exécution. Pour résoudre ce problème, la norme C ++ stipule que l'opérande desizeof
n'est pas évalué. La norme C dit:la source
sizeof()
L'opérateur donne uniquement la taille du type de données, il n'évalue pas les éléments internes.la source
sizeof()
opérateur agit de manière récursive et obtiendra la taille en octets de tous les éléments d'un conteneur, des membres d'une classe ou d'une structure, etc. Vous pouvez le prouver très facilement en créant une classe simple avec quelques membres et l'appelsizeof()
. (Cependant, tout ce qui est un pointeur ne peut pas voir la taille de - juste la taille du pointeur.) Cela se produit au moment de la compilation, comme d'autres commentateurs l'ont déclaré: les expressions à l'intérieur dusizeof()
ne sont pas évaluées.