Comment la taille d’un tableau de longueur variable est-elle calculée lors de l’exécution en C99?

En C89, la longueur d’un tableau est connue au moment de la compilation. Mais dans C99, avec des tableaux de longueur variable, la longueur d’un tableau peut être inconnue avant l’exécution.

Alors, comment est-il calculé?

Et pourquoi la longueur d’un tableau alloué dynamicment ne pourrait-elle pas être calculée de la même manière?

    De ISO / IEC 9899: TC3 Section 6.7.5.2: Déclarateurs de masortingce

    Un identificateur ordinaire (tel que défini au 6.2.3) ayant un type modifié de manière variable doit avoir une scope de bloc et aucune scope de prototype de liaison ou de fonction. Si un identificateur est déclaré être un object avec une durée de stockage statique, il ne doit pas avoir de type tableau de longueur variable.

    La taille d’un VLA est simplement sizeof(vla_element_type) * vla_length . Comme un VLA ne peut être défini que dans un bloc, its length must be either a local variable or a function parameter , auquel le compilateur peut accéder lorsque le vla est utilisé. (Depuis la longueur de vla et le vla lui-même appartient au même cadre de stack).

     Here is an example: int main(int argc, char* argv[]) { int m; scanf("%d\n", &m); int a[m]; printf("%d\n", sizeof(a)); return 0; } 

    Compilé avec clang -o test.ll -O2 -emit-llvm -S test.c , l’IR généré est présenté comme suit:

     define i32 @main(i32 %argc, i8** nocapture %argv) nounwind { entry: // Allocate space on stack for m %m = alloca i32, align 4 // call scanf %call = call i32 (i8*, ...)* @__isoc99_scanf(i8* getelementptr inbounds ([4 x i8]* @.str, i32 0, i32 0), i32* %m) nounwind // %0 now contains the value of m %0 = load i32* %m, align 4, !tbaa !0 // %1 is m << 2, which is m * sizeof(int) %1 = shl nuw i32 %0, 2 // call printf, output m * sizeof(int) to screen. %call1 = call i32 (i8*, ...)* @printf(i8* getelementptr inbounds ([4 x i8]* @.str, i32 0, i32 0), i32 %1) nounwind // DONE. ret i32 0 } 

    La différence entre un VLA et un tableau malloc ed que vous tenez avec une variable de pointeur (en plus de vivre dans différentes parties de la mémoire) est que le compilateur sait au moment de la compilation que la première est un tableau. Il peut contenir les informations de taille à un endroit donné avec le VLA. Il s’agit donc en gros d’une sorte de variable cachée. Selon l’utilisation que vous faites avec cette variable, par exemple si vous utilisez sizeof avec elle ou si vous indexez un VLA 2D via quelque chose comme A[i][j] le compilateur peut alors décider si cette variable cachée est vraiment nécessaire sinon, optimisez-le.