2017-05-11 2 views
4

Je sais que cette question a été posée, mais ma question est plus spécifique, est ici le code:la taille du tableau alloué dynamiquement en C

#include <stdio.h> 
#include <time.h> /* must be included for the time function */ 

main() 
{ 
    time_t t = time(NULL); 
    srand((unsigned) t); 

    int i = rand(); 

    int a[i]; 

    printf("%d\n", i);  /* ouptut: 18659 */ 
    printf("%d\n", sizeof a); /* output: 74636 */ 
} 

Je compilé ce code en utilisant gcc et -ansi option pour le restreindre à reconnaître le C ANSI seulement. Je sais qu'il n'y a aucun moyen que le compilateur puisse savoir à la compilation la taille du tableau car il est déterminé aléatoirement au moment de l'exécution. Maintenant, ma question est est la valeur retournée par sizeof est juste une valeur aléatoire, ou il a une signification?

+8

Ce code C89 n'est pas valide, en raison du tableau de longueur variable. C'est valable dans C99 +, où sizeof fait explicitement de la magie d'exécution sur les VLA (indice: qu'est-ce que 74636/18659?) –

+0

@OliverCharlesworth mais pourquoi compile-t-il? –

+2

Faisons un exercice - nous essayons de multiplier 18659 par 4. Qu'obtenons-nous? –

Répondre

3

La valeur retournée par sizeof est une valeur pseudo-aléatoire qui a un sens:

  • La valeur représente la taille de VLA a, en octets
  • Il est aléatoire seulement dans le sens que le nombre des éléments du tableau est déterminée par un appel à rand.

Il semble que sizeof(int) sur votre système est 4, car le nombre retourné par sizeof est quatre fois le nombre d'éléments du tableau.

Remarque: L'une des conséquences de l'autorisation de VLA dans C99 est que sizeof n'est plus une expression purement compilable. Lorsque l'argument de l'opérateur sizeof est un VLA, le résultat est calculé au moment de l'exécution.

2

est la valeur retournée par sizeof est juste une valeur aléatoire, ou a-t-elle une signification?

Il a un sens, comme 74636/18659 = 4, qui est apparemment la taille de int sur votre machine.

Alors sizeof (qui sera calculé au moment de l'exécution au lieu de la compilation puisque l'argument est un VLA), retournera la taille du tableau a en octets, qui est le nombre de int est qu'il contient (dans d'autres mots i ou 18659) multiplié par la taille de int, qui est 4 sur votre machine.

Comme i (le résultat de rand) est aléatoire, vous pouvez considérer que la valeur de sizeof sera également aléatoire dans ce sens.

6

L'opérateur sizeof est évalué au moment de la compilation pour la plupart des opérandes. Dans le cas d'un VLA, il est évalué à l'exécution.

De la section 6.5.3.4 de la C standard:

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

Ainsi, la taille renvoyée par sizeof est la taille en octets du VLA. Dans votre exemple, ce serait i * sizeof(int)

2

De l'gcc manual

L'option -ansi ne provoque pas de programmes non-ISO à rejeter à titre gratuit. Pour cela, -Wedantic est requis en plus de -ansi.

+0

Ce n'est pas vraiment la réponse à la question (sizeof (a) valable pour VLA), n'est-ce pas? – Aconcagua

+0

@ Aconcagua en fait, car cela signifie que sizeof (a) n'est plus évalué au moment de la compilation seulement comme c'est le cas en C89 (n'utilisant pas l'option -Wedantic). –

+0

@MaykelJakson Le mot «sizeof» n'est même pas mentionné dans la réponse - ni un mot sur l'évaluation de ce dernier lors de la compilation/exécution, ni une confirmation que la structure est valide. * Ceci * aurait été ce qui fait la bonne réponse - étant donné que l'on répond à la question "Comment compiler ANSI seulement avec GCC?", Ce que OP (à tort) supposait déjà en train de faire ... – Aconcagua