*Seufz*
Für etwas, das man einfach fix in jedem guten C-Lehrbuch nachlesen könnte, hältst du gewaltig lange an deinen Fehlvorstellungen fest.
Beispielcode:
#include <stdio.h>
const int zeilen=5;
const int spalten=6;
int main()
{
int matrix[zeilen][spalten];
return 0;
}
GCC mit C89, pedantic:
test.c:8:5: warning: ISO C90 forbids variable length array 'matrix' [-Wvla]
int matrix[zeilen][spalten];
^
test.c:8:5: warning: ISO C90 forbids variable length array 'matrix' [-Wvla]
test.c:8:9: warning: unused variable 'matrix' [-Wunused-variable]
int matrix[zeilen][spalten];
^
Dies ist, was dir ein anderer Compiler als Meldung geben könnte (und wird).
Mit C99 wird Maschinencode erzeugt (ohne Optimierung, da sonst das unbenutzte Array entfernt würde):
.file "test.c"
.globl zeilen
.section .rodata
.align 4
.type zeilen, @object
.size zeilen, 4
zeilen:
.long 5
.globl spalten
.align 4
.type spalten, @object
.size spalten, 4
spalten:
.long 6
.text
.globl main
.type main, @function
main:
.LFB0:
.cfi_startproc
pushq %rbp
.cfi_def_cfa_offset 16
.cfi_offset 6, -16
movq %rsp, %rbp
.cfi_def_cfa_register 6
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $32, %rsp
.cfi_offset 14, -24
.cfi_offset 13, -32
.cfi_offset 12, -40
.cfi_offset 3, -48
movq %rsp, %r10
movq %r10, %r12
movl $6, %r10d
movslq %r10d, %r10
subq $1, %r10
movq %r10, -56(%rbp)
movl $6, %r10d
movslq %r10d, %r10
movq %r10, %r13
movl $0, %r14d
movl $5, %r10d
movslq %r10d, %r10
subq $1, %r10
movq %r10, -48(%rbp)
movl $6, %r10d
movslq %r10d, %r10
movq %r10, %r8
movl $0, %r9d
movl $5, %r10d
movslq %r10d, %r10
movq %r10, %rax
movl $0, %edx
movq %r9, %r11
imulq %rax, %r11
movq %rdx, %r10
imulq %r8, %r10
addq %r11, %r10
mulq %r8
leaq (%r10,%rdx), %r8
movq %r8, %rdx
movl $6, %eax
cltq
movq %rax, %rsi
movl $0, %edi
movl $5, %eax
cltq
movq %rax, %rcx
movl $0, %ebx
movq %rdi, %rdx
imulq %rcx, %rdx
movq %rbx, %rax
imulq %rsi, %rax
leaq (%rdx,%rax), %r8
movq %rsi, %rax
mulq %rcx
leaq (%r8,%rdx), %rcx
movq %rcx, %rdx
movl $6, %eax
movslq %eax, %rdx
movl $5, %eax
cltq
imulq %rdx, %rax
salq $2, %rax
leaq 3(%rax), %rdx
movl $16, %eax
subq $1, %rax
addq %rdx, %rax
movl $16, %edi
movl $0, %edx
divq %rdi
imulq $16, %rax, %rax
subq %rax, %rsp
movq %rsp, %rax
addq $3, %rax
shrq $2, %rax
salq $2, %rax
movq %rax, -40(%rbp)
movl $0, %eax
movq %r12, %rsp
leaq -32(%rbp), %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %rbp
.cfi_def_cfa 7, 8
ret
.cfi_endproc
.LFE0:
.size main, .-main
.ident "GCC: (geht niemanden hier etwas an)"
.section .note.GNU-stack,"",@progbits
Hingegen mit defines (egal ob C89 oder C99):
.file "test.c"
.text
.globl main
.type main, @function
main:
.LFB0:
.cfi_startproc
pushq %rbp
.cfi_def_cfa_offset 16
.cfi_offset 6, -16
movq %rsp, %rbp
.cfi_def_cfa_register 6
subq $8, %rsp
movl $0, %eax
leave
.cfi_def_cfa 7, 8
ret
.cfi_endproc
.LFE0:
.size main, .-main
.ident "GCC: (geht niemanden hier etwas an)"
.section .note.GNU-stack,"",@progbits
Selbst wenn du kein Assembler verstehst, sollte offensichtlich sein, dass es hier riesige Unterschiede gibt. Im zweiten Compilat existieren die Objekte zeilen und spalten nicht mehr. Das kann man so wollen oder nicht; wichtig ist, dass es einen Unterschied macht.
Viel wichtiger und auch viel größer ist jedoch der Unterschied bei der Speicherallokierung in der main. Die im zweiten Fall ebenfalls nicht wirklich existiert, da es sich einfach nur um einen Offset beim Start der Funktion handelt. Beim ersten Code muss hingegen richtig Arbeit verrichtet werden (und zwar weit mehr als 3 Takte), da es sich um eine (semi-)dynamische Allokation handelt.