Memory for variable length arrays clearly can't be statically allocated. It can however be allocated on the stack. Generally this involves the use of a "frame pointer" to keep track of the location of the functions stack frame in the face of dynamicly determined changes to the stack pointer.
When I try to compile your program it seems that what actually happens is that the variable length array got optimised out. So I modified your code to force the compiler to actually allocate the array.
#include <stdio.h>
int main(int argc, char const *argv[])
{
int n;
scanf("%d",&n);
int k[n];
printf("%s %ld",k,sizeof(k));
return 0;
}
Godbolt compiling for arm using gcc 6.3 (using arm because I can read arm ASM) compiles this to https://godbolt.org/g/5ZnHfa. (comments mine)
main:
push {fp, lr} ; Save fp and lr on the stack
add fp, sp, #4 ; Create a "frame pointer" so we know where
; our stack frame is even after applying a
; dynamic offset to the stack pointer.
sub sp, sp, #8 ; allocate 8 bytes on the stack (8 rather
; than 4 due to ABI alignment
; requirements)
sub r1, fp, #8 ; load r1 with a pointer to n
ldr r0, .L3 ; load pointer to format string for scanf
; into r0
bl scanf ; call scanf (arguments in r0 and r1)
ldr r2, [fp, #-8] ; load r2 with value of n
ldr r0, .L3+4 ; load pointer to format string for printf
; into r0
lsl r2, r2, #2 ; multiply n by 4
add r3, r2, #10 ; add 10 to n*4 (not sure why it used 10,
; 7 would seem sufficient)
bic r3, r3, #7 ; and clear the low bits so it is a
; multiple of 8 (stack alignment again)
sub sp, sp, r3 ; actually allocate the dynamic array on
; the stack
mov r1, sp ; store a pointer to the dynamic size array
; in r1
bl printf ; call printf (arguments in r0, r1 and r2)
mov r0, #0 ; set r0 to 0
sub sp, fp, #4 ; use the frame pointer to restore the
; stack pointer
pop {fp, lr} ; restore fp and lr
bx lr ; return to the caller (return value in r0)
.L3:
.word .LC0
.word .LC1
.LC0:
.ascii "%d\000"
.LC1:
.ascii "%s %ld\000"