I tested amd64 and, to my surprise, this seems to be consistent behavior (but I don't know if this is an error). gcc places foo1_init and bar1_init in a shared data segment or a segment of null-initialized values by the operating system (.bss). foo2_init and bar2_init are placed in a read-only segment (.rodata), as if they were non-zero initialized values. This can be seen using -O0. Since you are not using the OS, the initialized section of the OS is manually initialized by gcc and / or the linker and then copied. gcc optimizes rodata values by creating a direct memset and eliminating dead variables * 2_init. However, clang optimizes both cases.
Here follows the output of gcc (-O0):
.file "defs.c" .local foo1_init .comm foo1_init,8,8 .section .rodata .align 8 .type foo2_init, @object .size foo2_init, 8 foo2_init: .zero 8 .local bar1_init .comm bar1_init,80,32 .align 32 .type bar2_init, @object .size bar2_init, 80 bar2_init: .zero 80 .text .globl init_foo1 .type init_foo1, @function init_foo1: .LFB0: .cfi_startproc pushq %rbp .cfi_def_cfa_offset 16 .cfi_offset 6, -16 movq %rsp, %rbp .cfi_def_cfa_register 6 movq foo1_init(%rip), %rax movq %rax, foo1(%rip) nop popq %rbp .cfi_def_cfa 7, 8 ret .cfi_endproc .LFE0: .size init_foo1, .-init_foo1 .globl init_foo2 .type init_foo2, @function init_foo2: .LFB1: .cfi_startproc pushq %rbp .cfi_def_cfa_offset 16 .cfi_offset 6, -16 movq %rsp, %rbp .cfi_def_cfa_register 6 movq $0, foo2(%rip) nop popq %rbp .cfi_def_cfa 7, 8 ret .cfi_endproc .LFE1: .size init_foo2, .-init_foo2 .globl init_bar1 .type init_bar1, @function init_bar1: .LFB2: .cfi_startproc pushq %rbp .cfi_def_cfa_offset 16 .cfi_offset 6, -16 movq %rsp, %rbp .cfi_def_cfa_register 6 movq bar1_init(%rip), %rax movq %rax, bar1(%rip) movq bar1_init+8(%rip), %rax movq %rax, bar1+8(%rip) movq bar1_init+16(%rip), %rax movq %rax, bar1+16(%rip) movq bar1_init+24(%rip), %rax movq %rax, bar1+24(%rip) movq bar1_init+32(%rip), %rax movq %rax, bar1+32(%rip) movq bar1_init+40(%rip), %rax movq %rax, bar1+40(%rip) movq bar1_init+48(%rip), %rax movq %rax, bar1+48(%rip) movq bar1_init+56(%rip), %rax movq %rax, bar1+56(%rip) movq bar1_init+64(%rip), %rax movq %rax, bar1+64(%rip) movq bar1_init+72(%rip), %rax movq %rax, bar1+72(%rip) nop popq %rbp .cfi_def_cfa 7, 8 ret .cfi_endproc .LFE2: .size init_bar1, .-init_bar1 .globl init_bar2 .type init_bar2, @function init_bar2: .LFB3: .cfi_startproc pushq %rbp .cfi_def_cfa_offset 16 .cfi_offset 6, -16 movq %rsp, %rbp .cfi_def_cfa_register 6 movl $bar2, %eax movl $80, %ecx movl $0, %esi movq %rsi, (%rax) movl %ecx, %edx addq %rax, %rdx addq $8, %rdx movq %rsi, -16(%rdx) leaq 8(%rax), %rdx andq $-8, %rdx subq %rdx, %rax addl %eax, %ecx andl $-8, %ecx movl %ecx, %eax shrl $3, %eax movl %eax, %ecx movq %rdx, %rdi movq %rsi, %rax rep stosq nop popq %rbp .cfi_def_cfa 7, 8 ret .cfi_endproc .LFE3: .size init_bar2, .-init_bar2 .ident "GCC: (GNU) 6.3.1 20170306" .section .note.GNU-stack,"",@progbits