?

Log in

No account? Create an account

Для вас, language lawyers! - Общество дровосеков Бердичева по изучению Мишны

Oct. 26th, 2015

11:25 am - Для вас, language lawyers!

Previous Entry Share Next Entry



Не пользуясь условной компиляцией или знанием, какие значения каких символов препроцессора определяет тот или иной компилятор, напишите программу, валидную и как С, и как С++, которая определяет, в каком стандарте языка она скомпилирована: C89, C99, C11, C++98 или C++11.

Отличить C89 от остальных языков легко, и отличить C от C++ на практике легко, а дальше?



В C11, в отличие от предыдущих версий, есть юникодные строки вида U"...."

#define HAS_UNICODE(U) (sizeof(U"x") > 2)
#include <stdio.h>
int main() { puts(HAS_UNICODE() ? "Yes" : "No"); }


Аналогичный трюк в С++11, где есть "raw strings" вида R"(...)".

Comments:

[User Picture]
From:ygam
Date:October 26th, 2015 06:29 pm (UTC)
(Link)
Я знаю, что sizeof('A') разное между C и C++, но я не помню, о каких версиях идет речь.
(Reply) (Thread)
[User Picture]
From:spamsink
Date:October 26th, 2015 06:31 pm (UTC)
(Link)
Да, так отличается весь С от всего С++, кроме платформ, на которых sizeof(int) == 1 :).
(Reply) (Parent) (Thread)
[User Picture]
From:ygam
Date:October 26th, 2015 06:36 pm (UTC)
(Link)
int i = 2
//* */ 2
;

В C89 будет 1; во всех остальных будет 2.


Edited at 2015-10-26 06:36 pm (UTC)
(Reply) (Parent) (Thread)
[User Picture]
From:spamsink
Date:October 26th, 2015 06:39 pm (UTC)
(Link)
Да. Т.е. 5 вариантов на 3 подмножества мы разбили, осталось различить С99/С11, и С++98/С++11.
(Reply) (Parent) (Thread)
[User Picture]
From:ygam
Date:October 27th, 2015 02:11 pm (UTC)
(Link)
И какое решение?
(Reply) (Parent) (Thread)
[User Picture]
From:spamsink
Date:October 27th, 2015 03:04 pm (UTC)
(Link)
В конце недели расскажу, если никто не решит.
(Reply) (Parent) (Thread)
[User Picture]
From:spamsink
Date:October 31st, 2015 10:48 am (UTC)
(Link)
См. подсказку.
(Reply) (Parent) (Thread)
[User Picture]
From:ygam
Date:October 31st, 2015 04:56 pm (UTC)
(Link)
U-U-U!
(Reply) (Parent) (Thread)
[User Picture]
From:spamsink
Date:November 1st, 2015 06:43 am (UTC)
(Link)
Конструкцию U"...." можно написать в #define.
(Reply) (Parent) (Thread)
[User Picture]
From:spamsink
Date:November 2nd, 2015 07:01 pm (UTC)
(Link)
См. ответ.
(Reply) (Parent) (Thread)
[User Picture]
From:ygam
Date:November 2nd, 2015 07:05 pm (UTC)
(Link)
sizeof(указатель) всегда больше двух.
(Reply) (Parent) (Thread)
[User Picture]
From:spamsink
Date:November 2nd, 2015 07:08 pm (UTC)
(Link)
А скомпилировать и посмотреть? :) Строка - это массив.
(Reply) (Parent) (Thread)
[User Picture]
From:bangor_flying
Date:October 26th, 2015 06:40 pm (UTC)
(Link)
У меня включение галочки "C+11 standard" приводит к тому, что обрубается часть казалось бы стандартных возможностей C99, например //-комментариев. Это очень печалит. Навскидку - реализация комплексных чисел разная, принудительное приведение указателей - обязательно в C++ и "очень не рекомендуется" в C, разница в typedef enum ... кстати, zortech/digital mars имеет свои отличия от обычного C++. Если что, я не так давно этим занимаюсь :)
(Reply) (Thread)
[User Picture]
From:spamsink
Date:October 26th, 2015 06:57 pm (UTC)
(Link)
Это очень странно, поскольку //-комментарии в С++ отродясь. У GCC и clang в режиме "-std=c++11 -pedantic" с //-комментариями нет никаких проблем.

Обычно стандарт конкретного языка стремится сохранить совместимость, поэтому если какая не содержащая неспецифицированного/неопределенного поведения программа компилировалась и работала в стандарте C99, то и в стандарте С11 (аналогично с С++98/С++11) она должна работать идентично; кроме случаев намеренного синтаксического трюкачества, как в примере, приведенном ygam. При переходе с С89 на С99 и введении, тем самым, распознавания //-комментариев по умолчанию, никого не беспокоило, что запись 2//**/2 в конце строки будет распознана иначе, нежели раньше, ибо нефиг. Таким образом, решение должно содержать еще какие-то синтаксические трюки.
(Reply) (Parent) (Thread)
[User Picture]
From:bangor_flying
Date:October 26th, 2015 07:08 pm (UTC)
(Link)
У меня Dev-c++. Он ругается на //-комментарий при установке опций ISO или Gnu C+11, если программа сохранена, как .c, но с .cpp ее пропускает. (Вероятно, я неправильно пользуюсь программой, потому что компилирую то чистые С, то С++ исходники, не меняя настроек). Я подозреваю, что компилятор обрезает при этом подмножество языка до максимально общего в двух стандартах. На такие мысли меня навела книга под названием C/C++ Kompendium, если не ошибаюсь, там в начале рассмотрены разные стандарты языка в качестве пересекающихся множеств и выводятся "безопасные" подмножества. Большое спасибо за интересный комментарий.

Edited at 2015-10-26 07:15 pm (UTC)
(Reply) (Parent) (Thread)
[User Picture]
From:spamsink
Date:November 2nd, 2015 07:02 pm (UTC)
(Link)
См. ответ.
(Reply) (Parent) (Thread)
From:qehgt
Date:October 26th, 2015 10:32 pm (UTC)
(Link)
Можно использовать всякие %zu в sprintf-подобных функциях. Они, вроде как, в C99 появились. Т.е. можно будет более тонко отличать стандарты.
(Reply) (Thread)
[User Picture]
From:archaicos
Date:October 26th, 2015 10:41 pm (UTC)
(Link)
Undefined behavior?

Edited at 2015-10-26 10:42 pm (UTC)
(Reply) (Parent) (Thread)
From:qehgt
Date:October 26th, 2015 11:19 pm (UTC)
(Link)
Верно, красивого решения оно не даст.
(Reply) (Parent) (Thread)
[User Picture]
From:spamsink
Date:November 2nd, 2015 07:02 pm (UTC)
(Link)
См. ответ.
(Reply) (Parent) (Thread)
[User Picture]
From:spamsink
Date:November 2nd, 2015 07:02 pm (UTC)
(Link)
См. ответ.
(Reply) (Parent) (Thread)
[User Picture]
From:archaicos
Date:November 2nd, 2015 07:37 pm (UTC)
(Link)
Foock!
(Reply) (Parent) (Thread)
[User Picture]
From:spamsink
Date:November 2nd, 2015 07:42 pm (UTC)
(Link)
Отож. :)
(Reply) (Parent) (Thread)
[User Picture]
From:spamsink
Date:October 26th, 2015 10:47 pm (UTC)
(Link)
Никто не гарантирует, что при компиляции со "старым" стандартом будет линковаться именно старая библиотека, если есть установленная более новая.
(Reply) (Parent) (Thread)