Здравствуйте, Кодт, Вы писали:
К>Здравствуйте, watchmaker, Вы писали:
К>>>Но синтаксически... сломали совместимость. W>>Сломали совместимость с чем? Такое поведение у inline в стандарте языка было всегда
К>http://ideone.com/x4thLo — C89 — ok
ll.c:3:8: error: expected ‘=’, ‘,’, ‘;’, ‘asm’ or ‘__attribute__’ before ‘void’
inline void foo() { printf("foo\n"); }
^
А вот что думает clang-3.5 -std=c89:
ll.c:3:1: error: unknown type name 'inline'
inline void foo() { printf("foo\n"); }
^
Это уже не говоря о том, что есть и куда более важное несоответствие с c89:
gcc
ll.c:8:5: error: expected expression before ‘/’ token
// your code goes here
^
clang
ll.c:8:5: error: // comments are not allowed in this language
// your code goes here
^
К>Хочешь сказать, что инстанцирование &foo — это добрая воля и личная инициатива компилятора?
В с99 инстанциирования не будет по стандарту (и у компиляторов с этим нет проблем — не делать как-то всегда проще чем наоборот что-то делать).
В с89 такой код невалиден.
К>(Аналогичная ситуация со статическими членами-константами в С++ однозначно приводит к ошибке линковки).
Однозначно — слишком сильно сказано. Никто не гарантирует, что такая ситуация не приведёт. И, конечно, это нужно исправлять. Но достаточно часто не приводит из-за слишком умного оптимизатора, и забытое определение может быть обнаружено совсем не сразу.
Здравствуйте, jazzer, Вы писали:
W>>>Кстати говоря, в C++ есть механизмы, который работают точно также. Например,
W>>>class Bar {
W>>> static const int x = 4;
W>>>};
W>>>По стандарту недостаточно написать это в .h файле, но нужно дополнительно в одном из .cpp файлов сделать инстанциирование
const int Bar::x;
A>>только если "x" ODR-used. (http://ru.stackoverflow.com/a/419547/177684)
J>Теоретически да, а практически у меня гцц в релизных билдах все собирает нормально, а дебаг-билдах требует инстанцирование.
там по ссылке на RU.SO об этом и написано.
если есть код
int f(int& arg) { return arg; }
int main() {
return f(Bar::x);
}
то оптимизатор инлайнит код, и переменная перестает быть ODR-used.
а без оптимизаций f(Bar::x) остается, генерится код
extern dd Bar_x
...
main:
push offset Bar_x
call f
ret
Здравствуйте, Кодт, Вы писали:
К>Здравствуйте, Abyx, Вы писали:
A>>лучше использовать онлайн компилятор в котором можно задать командную строку A>>http://coliru.stacked-crooked.com/a/2491064e67a98380
К>Ох щи! Оказывается, inline — это фича C99 и расширение GNU C89. То есть, все эти годы мы ходили по граблям...
Хорошо хоть MS используют два подчеркивания для расширений __inline.
Здравствуйте, Abyx, Вы писали:
A>Здравствуйте, Tilir, Вы писали:
T>>Не все знают, что в GCC начиная с 5.0 стандартом по умолчанию сделали C99.
A>я смотрю что не все знают что сейчас 2015 год, а не 1999 A>за 15 лет уже новые программисты родились (sic!), а вы всё не можете прочитать что там такое написано в стандарте, A>который содержит всего 500 страниц (а не 1300 как в С++)
Ну, я бы сказал, что это из области "программистского бессознательного". Я вот при "plain C" на автомате пишу static для всех локальных функций, но про тонкости стандартов Cxx vs Cyy действительно не задумывался (в отличие от C++), в первую очередь по причине идиомы "это ж plain C, старый язык, едва ли не legacy".
Здравствуйте, Tilir, Вы писали:
T>Hi,
T>Не все знают, что в GCC начиная с 5.0 стандартом по умолчанию сделали C99. T>Но это является источником радости. Надеюсь этот пост убережет кого-то из тех, кто пойдет по моим следам (перевод немаленького проекта на новый компилятор).
Благодарствую за граблеописание. Ещё раз убедился, что моя подсознательная нелюбовь к явному описанию inline — не спроста
T>Не все знают, что в GCC начиная с 5.0 стандартом по умолчанию сделали C99 (UPD: на самом деле GNU11, то есть C11 + GNU extensions) T>Но это является источником радости. Надеюсь этот пост убережет кого-то из тех, кто пойдет по моим следам (перевод немаленького проекта на новый компилятор).
T>Итак вы берете некий код, который кажется не содержит никаких ошибок:
Как-же будет компилиться ядро линукса?
Вот "стандартный" файл fs.h
MS>"static inline" — очень много. Будут переделывать?
Каюсь не обратил внимание на то, что static решает проблему
Сам постоянно пишу static inline и уж чуть было не бросился переписывать (пока только на 4.8.2 работаю)
A>int f(int& arg) { return arg; }
A>int main() {
A> return f(Bar::x);
A>}
A>
A>то оптимизатор инлайнит код, и переменная перестает быть ODR-used.
Ну нет. Переменная не перестаёт быть ODR-used. Это же формальное свойство — оно зависит только от текста программы, а не от используемого компилятора или его настроек оптимизации. И встраивание тут не исключение.
А собирается такая программа лишь из-за особенностей устройства линкера и компилятора. Раз по стандарту компилятор не должен следить за наличием определений для ODR-used переменных, то он и не следит. А linker игнорирует всё, на что нет внешних ссылок. Вместе две эти особенности и приводят к успешной сборке программы.
В общем, пропадает не свойство ODR-used, а ссылки внутри объектных файлов. Вот только первое — это про С++, а второе — лишь про особенности конкретной реализации. Сама же константа Bar::x как была ODR-used, так и осталась.