C11 и оценка постоянного выражения в метках переключателей - PullRequest
0 голосов
/ 24 мая 2018

после этого вопроса Почему gcc не допускает использование const int в качестве выражения регистра? , в основном то же, что и Какие повышенные типы используются для сравнения выражений регистра переключателя? или Есть ли способ использовать постоянный массив с постоянным индексом в качестве метки регистра переключателя в C? .

Из первой ссылки я попытался заменить:

case FOO:                       // aka 'const int FOO = 10'

с:

case ((int) "toto"[0]):         // can't be anything *but* constant

Что дает:

https://ideone.com/n1bmIb -> https://ideone.com/4aOSXR = работает в C ++

https://ideone.com/n1bmIb -> https://ideone.com/RrnO2R = не удается в C

Я не совсем понимаю, поскольку строка "toto" не может быть чем-либо , но константой, это не такДаже переменная находится в пустоте памяти компилятора.Я даже не играю с нечеткой логикой 'const' языка C (которая на самом деле означает «только чтение, а не константа, что вы ожидали?»), Проблема в «доступе к массиву» или в «ссылках на указатели»«в константное выражение, которое не оценивается в C, но хорошо работает в C ++.

Я ожидал использовать этот« трюк », чтобы использовать HASH_MACRO (str) для генерации уникальных значений меток регистра из идентификатора ключаоставив в конечном итоге компилятор для выдачи ошибки в случае коллизии из-за найденных похожих значений меток.

ОК, хорошо, мне сказали, что эти ограничения были сделаны для упрощения языковых инструментов (preproc, компилятор, компоновщик) и Cэто не LISP, но вы можете иметь полнофункциональный интерпретатор / компилятор LISP за долю от размера эквивалента C, так что это не оправдание.

Вопрос: есть ли «расширение» для C11, котороепросто позволяет этому "toto" работать в GCC, CLANG и ... MSVC?Я не хочу идти по пути C ++ (предварительные объявления typedef больше не работают) и потому, что встроенный материал (отсюда вычисление хеша во время компиляции для пространственно-временного искажения).

Есть ли посредник "C + «язык, который является более« разрешающим »и« понимающим », встроен немного лучше, как -Praise the Lords-« перечисляет как члены битового поля », среди других приятных вещей, которых у нас не может быть (из-за нереальных стандартов, развивающихся как улитки)под пустынным солнцем)?

# Докажем, #changemymind, # norustplease

Ответы [ 3 ]

0 голосов
/ 24 мая 2018

Неважно, может ли он быть известен компилятору во время компиляции.Метка case должна иметь значение, которое является целочисленным константным выражением (C11 6.8.4.2p3) .

Выражение каждой case метки должно быть выражением целочисленной константы , и никакие два выражения константы регистра в одном и том же операторе switch не должны иметь одинакового значения после преобразования.В операторе switch может быть не более одной метки по умолчанию.(Любой вложенный оператор switch может иметь метку по умолчанию или выражения константы регистра со значениями, которые дублируют выражения константы регистра во включающем операторе switch.)

И определение целочисленного константного выражения: в C11 6,6p6 :

Выражение целочисленной константы должно иметь тип целочисленного типа и иметь только те операнды, которые являются целочисленными константами, константами перечисления, символьными константами, sizeof выражениями, результаты которых являются целочисленными константами, выражениями _Alignof и плавающими константами, которые являются непосредственными операндами.слепков.Операторы приведения в выражении с целочисленной константой должны преобразовывать только арифметические типы в целочисленные типы, кроме как как часть операнда, к оператору sizeof или _Alignof.

Поскольку "toto" не является целочисленными константами, константами перечисления, символьными константами, константами выражений sizeof, _Alignof или константами с плавающей точкой, приведенными к целому числу;и этот список был указан в разделе стандарта constraints , компилятор не должен передавать это молча.(Даже соответствующий компилятор все еще может успешно скомпилировать программу, но он должен диагностировать это как нарушение ограничения.)


То, что вы можете использовать, приковано ? : для преобразования индекса в символьную константу,то есть

  x == 0 ? 't' 
: x == 1 ? 'o'
: x == 2 ? 't'
: x == 3 ? 'o'

Это можно записать в макрос.

0 голосов
/ 24 мая 2018

"toto[0]" не является целочисленным константным выражением , поскольку C определяет термин:

6.6. Постоянные выражения
...
6 Anцелочисленное константное выражение 117) должно иметь целочисленный тип и иметь только те операнды, которые являются целочисленными константами, константами перечисления, символьными константами, sizeof выражениями, результаты которых являются целочисленными константами, _Alignof выражения и плавающие константы, которые являются непосредственными операндами приведений.Операторы приведения в выражении с целочисленной константой должны преобразовывать только арифметические типы в целочисленные типы, кроме как в качестве части операнда к оператору sizeof или _Alignof.
117) Выражение из целочисленной константы требуется в ряде контекстов, таких как размер элемента битового поля структуры, значение константы перечисления и размер массива неизменяемой длины,Дополнительные ограничения, которые применяются к целочисленным константным выражениям, используемым в директивах предварительной обработки условного включения, обсуждаются в 6.10.1.

C 2011 г. онлайн-проект

0 голосов
/ 24 мая 2018

Проблема, с которой вы сталкиваетесь, заключается в том, что в C "toto" представляет собой массив символов.Конечно, он постоянен в памяти, но это все еще просто массив.Оператор [] индексирует в массиве (по указателю).Если бы вы хотели, вы могли бы редактировать скомпилированный двоичный файл и изменить строку «toto» на что-то другое.В некотором смысле, это не известно во время компиляции.Это эквивалентно выполнению:

char * const ___string1 = "toto";
...
case ((int) ___string1[0]):

(Это немного принудительно и избыточно, но только для демонстрации)

Обратите внимание, что тип элементов строкового литерала равен char, не const char.

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...