Search code examples
cassemblystandards

According to the current C Standard, what is the default value assigned to an `int` which is declared but not defined?


Question of C Standard

Easy question, but couldn't seem to find the answer with a duckduckgo or by searching SO (here).

I am aware that in C, the standard states that uninitialized arrays of ints results in undefined behaviour. (Or at least most compilers behave this way.)

int a[100]; // 100 x 32bits on stack, values are whatever was left over on the stack
printf("a[5]=%d", a[5]); // undefined behaviour, can be any valid `int` value (-2**15 to 2**15 - 1)

However, what is the default value of a single int?

int a; printf("a=%d", a);

My guess would be that since this is on the stack, a "push stack" instruction has to be executed by the CPU, and this instruction MUST take a value, and the most sensible value for a compiler to use if no value is specified would be zero.

Am I correct?

Example Test Program and Disassembly

#include <stdio.h>

int a;
    
int main(void)
{
    printf("%d\n", a);
    return 0;
}

And this is this dissassembly: (`gcc -save-temps -Wall test.c -o test)

    .file   "test.c"
    .text
    .globl  a
    .bss
    .align 4
    .type   a, @object
    .size   a, 4
a:
    .zero   4
    .section    .rodata
.LC0:
    .string "%d\n"
    .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
    movl    a(%rip), %eax
    movl    %eax, %esi
    leaq    .LC0(%rip), %rdi
    movl    $0, %eax
    call    printf@PLT
    movl    $0, %eax
    popq    %rbp
    .cfi_def_cfa 7, 8
    ret
    .cfi_endproc
.LFE0:
    .size   main, .-main
    .ident  "GCC: (Debian 10.2.1-6) 10.2.1 20210110"
    .section    .note.GNU-stack,"",@progbits

This appears to have the line

a:
    .zero 4

does this mean that a is initialized as a block of memory in the .data section as 4x 0x00 (bytes) ?


Solution

  • In your example

    #include <stdio.h>
    
    int a;
        
    int main(void)
    {
        printf("%d\n", a);
        return 0;
    }
    

    The variable a is declared globally, so it is initialized to zero.

    On the other hand, if the variable a is declared locally and non-statically

    #include <stdio.h>
        
    int main(void)
    {
        int a;
        printf("%d\n", a);
        return 0;
    }
    

    It has an indeterminate value and using the value invokes undefined behavior.

    Quote from N1570 6.7.9 Initialization 10:

    If an object that has automatic storage duration is not initialized explicitly, its value is
    indeterminate. If an object that has static or thread storage duration is not initialized
    explicitly, then:
    — if it has pointer type, it is initialized to a null pointer;
    — if it has arithmetic type, it is initialized to (positive or unsigned) zero;
    — if it is an aggregate, every member is initialized (recursively) according to these rules,
    and any padding is initialized to zero bits;
    — if it is a union, the first named member is initialized (recursively) according to these
    rules, and any padding is initialized to zero bits;