c - Почему поведение реализации вычитающих символов специфично?




character-encoding (2)

ОП спрашивает о прямой цитате из стандарта - N1570 §6.10.1p3.4 + примечание 168 :

... выражение управляющей константы оценивается в соответствии с правилами 6.6. ... Это включает в себя интерпретацию символьных констант, которые могут включать в себя преобразование управляющих последовательностей в исполнительные элементы набора символов. Является ли числовое значение для этих символьных констант совпадающим с значением, полученным, когда идентичная символьная константа встречается в выражении (отличном от директивы #if или #elif), определяется реализацией. 168

[сноска 168] Таким образом, константное выражение в следующей директиве #if и инструкции if не гарантируется для оценки того же значения в этих двух контекстах.

#if 'z' - 'a' == 25
if ('z' - 'a' == 25)

Итак, да, это действительно не гарантировано.

Чтобы понять, почему это не гарантировано, сначала вам нужно знать, что стандарт C не требует, чтобы символьные константы 'a' и 'z' имели числовые значения, присвоенные этим символам ASCII. Большинство реализаций C в настоящее время используют ASCII или надмножество, но есть еще одна кодировка, называемая EBCDIC которая все еще широко используется (только для мэйнфреймов IBM, но их все еще много). В EBCDIC не только значения 'a' и 'z' имеют разные значения из ASCII, а алфавит не является последовательной последовательностью! Поэтому выражение 'z' - 'a' == 25 может не оценивать истину в первую очередь.

Вам также необходимо знать, что стандарт C пытается поддерживать различие между текстовой кодировкой, используемой для исходного кода («набор исходных символов»), и текстовым кодированием, которое программа будет использовать во время выполнения («набор символов выполнения»). Это значит, что вы можете, по крайней мере в принципе, взять программу, источник которой закодирован в тексте ASCII и запустить ее без изменений на компьютере, использующем EBCDIC, просто путем кросс-компиляции соответствующим образом; вам не нужно сначала преобразовывать исходный текст в EBCDIC.

Теперь компилятор должен понимать оба набора символов, если они разные, но исторически препроцессор C ( этапы перевода с 1 по 4) и «собственно компилятор» (этапы с 5 по 7) были двумя отдельными программами, а выражения #if являются единственным местом, где препроцессор должен был бы знать о наборе символов выполнения. Таким образом, определив, соответствует ли установленный препроцессором «набор символов выполнения», который используется соответствующим компилятором, стандарт разрешает препроцессору выполнять всю свою работу в наборе исходных символов, что делает жизнь немного легче назад в 1989 году.

Сказав все это, я был бы очень удивлен, если найду современный компилятор, который не заставил бы оба выражения оценивать одинаковое значение, даже если наборы символов исполнения и исходного кода грубо несовместимы. Современные компиляторы, как правило, имеют интегрированные препроцессоры - этапы с 1 по 7 выполняются одной и той же программой, и даже если они этого не делают, инженерное бремя специализации препроцессора в соответствии с его исполнением, установленным для самого компилятора, тривиально Настоящее время.

Это утверждение:

if('z' - 'a' == 25)

не гарантируется равноценным образом. Он зависит от компилятора. Кроме того, не гарантируется оценка так же, как это:

#if 'z' - 'a' == 25

даже если оба препроцессора и компилятор выполняются на одном компьютере. Это почему?


Потому что не все компьютеры используют ascii или unicode.

Раньше обычным был стандарт ebcdic. В ebcdic 500 значение 'z' равно 169, а значение 'a' равно 130. Тогда выражение 'z'-'a' будет оцениваться до 39.

Это объясняет, почему вы не можете принять определенное значение для выражения типа 'a' или даже 'z'-'a' . Однако он не объясняет, почему два выражения в Q не гарантируются равными.

Препроцессор и компилятор - это две разные вещи. Препроцессор имеет дело с кодировкой, используемой в исходном коде, тогда как компилятор нацелен на машину, для которой вы компилируете. См. Ответ zwol для более подробного объяснения.







character-encoding