jsn: (common)
[personal profile] jsn

[несколько слов пропущено, потому что они все нецензурные]

jason@jsn c $ cat r.c
#include <stdio.h>

#define B (sizeof(int) * 8)
int _ = B ;
int f(void) { return _ ; }

unsigned g(unsigned x) {
    printf("x == %d, ", x) ;
    return 1 << (B - x) ;
}

int main(int ac, const char *av[]) {
    printf("g(x) == %d\n", g(0)) ;
    printf("g(x) == %d\n", g(B - f())) ;
    return 0 ;
}
jason@jsn c $ gcc -o r r.c && ./r
x == 0, g(x) == 1
x == 0, g(x) == 1
jason@jsn c $ gcc -O2 -o r r.c && ./r
x == 0, g(x) == 0
x == 0, g(x) == 1
jason@jsn c $ clang -o r r.c && ./r
x == 0, g(x) == 1
x == 0, g(x) == 1
jason@jsn c $ clang -O2 -o r r.c && ./r
x == 0, g(x) == 0
x == 0, g(x) == 1
jason@jsn c $ 

Это, что, считается нормально теперь? Там, что, в стандарте действительно сказано, что overflowing left shift result is undefined? И "undefined" следует интерпретировать как "ведёт себя по-разному в соседних строчках кода?"

Date: 2013-02-17 03:53 am (UTC)
From: [identity profile] evolver.livejournal.com
У меня есть несколько иная точка зрения на происходящее. Она основана на чтении результата трансляции с флажком "-S". Очень вероятно, что никакого константного шифта при опции "-O2" не cлучается. Компилятор инлайнит функцию g() в тело main(), причем делает это двумя разными способами. Для случая вызова g(0) он оптимизирует все до состояния, где в printf для g(0) попадает мусор после printf для x. Забавно наблюдать результат двух или более последовательных вызовов бинарника, скомпилированного с -O2. Кажый раз мы видим новый результат.

Фактическая инструкция "shll" выполняется только для второго инлайна функции g() в теле main(). Смотри строку 30 в этом фрагменте:
http://codepad.org/XBCaHfIo

Она как раз возвращает стабильный результат.

Вариант без "-O2" честно геренрирует и дважды вызывает функцию g(), которая честно содержит "shll". Наверно это объясняет наблюдаемое поведение.

Для меня загадкой остается то, зачем компилятор сохраняет в коде отдельную реализацию g(), которая никогда не вызывается, но это уже другая тема.

Date: 2013-02-18 09:13 am (UTC)
From: [identity profile] jsn.livejournal.com
никакого константного шифта при опции "-O2" не cлучается ... Для случая вызова g(0) он оптимизирует все до состояния, где в printf для g(0) попадает мусор после printf для x

Это не называется "оптимизирует" -- это баг. Константный шифт на 32, будучи undefined, сочтён nop-ом и несэмичен.

Фактическая инструкция "shll" выполняется только для второго инлайна функции g() в теле main().

Конечно; так и должно быть в случае precomputed vs emitted.

Date: 2013-02-18 09:51 am (UTC)
From: [identity profile] jsn.livejournal.com
Для меня загадкой остается то, зачем компилятор сохраняет в коде отдельную реализацию g()

Очевидно, потому что она не static, и поэтому может вызываться из других файлов, с которыми будет слинкован этот.

Date: 2013-02-18 02:55 pm (UTC)
From: [identity profile] evolver.livejournal.com
Да, точно. Я как-то про это не подумал. Выходит, загадок больше не осталось :)

Profile

jsn: (Default)
jsn

July 2020

S M T W T F S
   1234
56789 1011
12131415161718
19202122232425
262728293031 

Most Popular Tags

Style Credit

Expand Cut Tags

No cut tags
Page generated Dec. 31st, 2025 09:00 pm
Powered by Dreamwidth Studios