Следующий код компилируется и запускается на компиляторе GCC.
#include <stdio.h>
int arr[10];
int func()
{
printf("In func\n");
return 0;
}
int main()
{
if (&arr[func()])
printf("In main\n");
return 0;
}
Выход:
In main
Почему не запускает printf("In func\n");?
Скомпилируйте свой код со всеми предупреждениями и отладочной информацией: gcc -Wall -Wextra -g. Тогда использовать отладчик gdb. Вы должны наблюдать за printf.
Или, по крайней мере, убедитесь, что вы «сохранили» после публикации кода, затем скомпилируйте с включенными предупреждениями и продолжайте.
Я просто вставил ваш код и получил In func/In main. (gcc 5.4.0)
Даже действительно умный оптимизатор может узнать только то, что проверка всегда отлична от нуля, поэтому он должен вызвать побочный эффект.
Я скомпилировал и визуализировал ваш код, он работает, и оба отпечатка распечатываются должным образом. в чем смысл утверждения if, он всегда оценивается как истина, поскольку &arr[func()] - это адрес arr[0]. какой компилятор вы используете?
Давайте сделаем небольшое изменение, чтобы предотвратить оптимизацию func() с помощью gcc ... int *p = &arr[func()]; if (p) printf("In main\n"); и повторите попытку.
@Jayesh: Я думаю, вы просто неправильно скомпилировали свою программу. Пожалуйста, дайте фактическую команду компиляции, которую вы набрали в терминале
@BasileStarynkevitch, это действительно проблема gcc. В gcc 7.3 func() полностью оптимизирован из main(). Несмотря на то, что он производит вывод. Более ранние версии gcc справляются с этим нормально. Действительно странно. .string "In func" сохранен, функция func() есть, но она полностью опущена при генерации кода для main:, так что @Jayesh не сумасшедший.
@ DavidC.Rankin: При компиляции с gcc -Wall -g jayesh.c -o jayesh я наблюдаю два выхода, с gcc 7.3 на Debian / Sid. И даже с gcc -O -Wall -g jayesh.c -o jayesh вывод тоже наблюдаю. И даже с -O3; если бы это было не так, это было бы серьезной ошибкой оптимизации. Поэтому мы не можем воспроизвести ваше наблюдение.
Я скомпилировал последнее ядро 4.15.8 с помощью gcc 7.3.0, и его больше нет. Это странно. Выложу сборку.
Укажите, известно ли вам о содержании ссылки, предоставленной @PkmX в своем ответе. Сходство примеров кода поразительно. Если вы пытаетесь протестировать StackOverflowers, я голосую за PkmX.





Проблема в твоей компиляции. Я использую gcc для компиляции. Я скомпилировал ваш файл так:
gcc main.c -o prog
./prog
In func
In main
Мне кажется, это хорошо. Проверьте процедуру компиляции с вашим компилятором, если вы используете компилятор, отличный от gcc. Также использую gcc 7.3
А с GCC 7.3 такой же вывод происходит с -O, -O2, -O3.
GCC 7.3.0 на Mac показывает мне ошибку (как эта версия, так и версия из GCC Bug # 84607 - с -O0, -O1, -O2 или -O3.
Кажется, есть тонкая проблема, преднамеренная или непреднамеренная, с различными комбинациями последней версии gcc. версия 7.3 в последней версии ядра 4.15.8 на Archlinux. По какой-то причине вызов func() опущен для кода, сгенерированного для main(). например
$ gcc -S -masm=intel -o infunc2.asm infunc2.c
Сгенерированная сборка:
$ cat infunc2.asm
.file "infunc2.c"
.intel_syntax noprefix
.text
.comm arr,40,32
.section .rodata
.LC0:
.string "In func"
.text
.globl func
.type func, @function
func:
.LFB0:
.cfi_startproc
push rbp
.cfi_def_cfa_offset 16
.cfi_offset 6, -16
mov rbp, rsp
.cfi_def_cfa_register 6
lea rdi, .LC0[rip]
call puts@PLT
mov eax, 0
pop rbp
.cfi_def_cfa 7, 8
ret
.cfi_endproc
.LFE0:
.size func, .-func
.section .rodata
.LC1:
.string "In main"
.text
.globl main
.type main, @function
main:
.LFB1:
.cfi_startproc
push rbp
.cfi_def_cfa_offset 16
.cfi_offset 6, -16
mov rbp, rsp
.cfi_def_cfa_register 6
lea rdi, .LC1[rip]
call puts@PLT
mov eax, 0
pop rbp
.cfi_def_cfa 7, 8
ret
.cfi_endproc
.LFE1:
.size main, .-main
.ident "GCC: (GNU) 7.3.0"
.section .note.GNU-stack,"",@progbits
Обратите внимание, что вызов func() обозначен выше как .LFB0:. Процедура для main: вообще не вызывает func или .LFB0:, несмотря на то, что они присутствуют, и несмотря на то, что строка "In func" присутствует в .LC0:. Я подозреваю, что это ненормальное поведение.
Например, при простой компиляции без оптимизации -O0 функция не вызывается, например:
$ gcc -g -O0 -o bin/if2 infunc2.c
$ ./bin/if2
In main
Изменение кода для сохранения адреса arr[func()] вызывает принудительный вызов func(), например
#include <stdio.h>
int arr[10];
int func()
{
printf ("In func\n");
return 0;
}
int main (void)
{
int *p = &arr[func()];
if (p)
printf("In main\n");
return 0;
}
потом
$ gcc -Wall -Wextra -pedantic -std=gnu11 -Ofast -o bin/infunc infunc.c
$ ./bin/infunc
In func
In main
А сгенерированная сборка поддерживает другое поведение:
$ gcc -S -masm=intel -o infunc.asm infunc.c
$ cat infunc.asm
.file "infunc.c"
.intel_syntax noprefix
.text
.comm arr,40,32
.section .rodata
.LC0:
.string "In func"
.text
.globl func
.type func, @function
func:
.LFB0:
.cfi_startproc
push rbp
.cfi_def_cfa_offset 16
.cfi_offset 6, -16
mov rbp, rsp
.cfi_def_cfa_register 6
lea rdi, .LC0[rip]
call puts@PLT
mov eax, 0
pop rbp
.cfi_def_cfa 7, 8
ret
.cfi_endproc
.LFE0:
.size func, .-func
.section .rodata
.LC1:
.string "In main"
.text
.globl main
.type main, @function
main:
.LFB1:
.cfi_startproc
push rbp
.cfi_def_cfa_offset 16
.cfi_offset 6, -16
mov rbp, rsp
.cfi_def_cfa_register 6
sub rsp, 16
mov eax, 0
call func
cdqe
lea rdx, 0[0+rax*4]
lea rax, arr[rip]
add rax, rdx
mov QWORD PTR -8[rbp], rax
cmp QWORD PTR -8[rbp], 0
je .L4
lea rdi, .LC1[rip]
call puts@PLT
.L4:
mov eax, 0
leave
.cfi_def_cfa 7, 8
ret
.cfi_endproc
.LFE1:
.size main, .-main
.ident "GCC: (GNU) 7.3.0"
.section .note.GNU-stack,"",@progbits
Хотел бы я дать здесь какое-то логическое объяснение этой обработки, но я могу только задокументировать это. Кажется, нам нужно поговорить с парнями из списка gcc.
Побочные эффекты, отбрасываемые при вычислении адреса внутри if
Похоже, это регресс в gcc, который появится в зависимости от того, применяет ли отдельный дистрибутив достаточно исправлений, чтобы замаскировать его. Это ошибка gcc в работе. Ошибка 84607
Вы должны сообщить об ошибке в вашем дистрибутиве Linux. Кстати, в Debian / Sid я этого не наблюдаю.
Это также может объяснить некоторые недавние необъяснимые проблемы с дистрибутивом :(. Спасибо за ответ.
Возможно, в вашем дистрибутиве есть какой-то странный файл спецификации, который требует некоторой оптимизации
Я думаю, что это просто регресс где-то в линейке вещей gcc на Arch. Сегодня в списке Arch (одна моя) есть пара необъяснимых ошибок, и все, что вызывает их, кажется идеальным кандидатом для устранения проблем. "Хьюстон у нас проблема..."
Это ошибка gcc (# 84607), которая была исправлена в gcc 7.3.1 или новее.
Кажется, это источник основной идеи цитаты кода в вопросе.
Что делает эта строка кода
if (&arr[func()])? Когда адрес любого элементаarrстанет нулевым? Вы уверены, что в вашем коде нет управляющих символов DOS? Получаете какие-либо предупреждения компилятора? Какие?