Кто-то может объяснить это поведение? всего 2 строки кода

Просьба объяснить этот фрагмент:

#include <stdio.h>

int puts(const char *str) {
    fputs("Hello world!\n", stdout);
}

int main() {
    printf("Goodbye\n");
}

Выход: Hello world! return 13

Ответы

Ответ 1

Он специфичен для компилятора. Вы получаете это поведение с GCC. Вот несколько деталей.

  • так как вы #include <stdio.h> (фактически потому, что вы находитесь в размещенной среде) puts соответствует стандарту C99, а переопределяет его undefined

  • компилятор GCC имеет некоторые оптимизации для преобразования некоторого printf в последовательность более быстрого puts. Это законно, поскольку вы включили <stdio.h> (и стандарт C99 определяет, что должен делать printf в этом случае; GCC проходит через __builtin_printf в качестве промежуточного шага)

Если вы скомпилируете с помощью -ffreestanding, вы не заметите этого.

Ваш вопрос очень близок к этому; поэтому этот ответ также имеет значение.

Ответ 2

Я скомпилировал программу с помощью gcc x.c -S -o-. Это дало мне

[...]
main:
.LFB1:
        .cfi_startproc
        pushl   %ebp
        .cfi_def_cfa_offset 8
        .cfi_offset 5, -8
        movl    %esp, %ebp
        .cfi_def_cfa_register 5
        andl    $-16, %esp
        subl    $16, %esp
        movl    $.LC1, (%esp)
        call    puts
        leave
        .cfi_restore 5
        .cfi_def_cfa 4, 4
        ret
        .cfi_endproc
.LFE1:

так что вызов printf заменяется на puts в GCC, так как они имеют одинаковую семантику.

Ответ 3

Мое предположение заключается в том, что компилятор меняет вызов на printf() на вызов puts(), так как нет необходимости в printf() из-за отсутствия форматирования. Также строка заканчивается новой строкой, которая соответствует puts(). Компилятор не видел вашу страшную перегрузку функции библиотеки, поэтому она стала "одураченной".