инициализация массива символов с восьмеричной константой

Я видел комментарий, в котором говорилось, что инициализация массива символов с помощью "\001" поставит нуль в качестве первого символа. Я видел, где \0 устанавливает нулевое значение.

Неотредактированный комментарий:

ввод символов [РАЗМЕР] = ""; достаточно инициализации. while ( '\001' == input[0]) не делает то, что вы думаете, если вы инициализировали input[SIZE] = "\001"; (который создает пустую строку с нулевым символом в качестве 1-го символа.)

Эта программа

#include <stdio.h>
#define SIZE 8
int main ( void) {
    char input[SIZE] = "\001";

    if ( '\001' == input[0]) {//also tried 1 == input[0]
        printf ( "octal 1\n\n");
    }
    else {
        printf ( "empty string\n");
    }
    return 0;
}

работающий в Linux, скомпилированный с помощью gcc, выводит:

octal 1

таким образом, первый символ — 1, а не '\0'.
Это стандартное поведение или что-то в Linux и gcc? Почему он не устанавливает ноль?


person xing    schedule 30.07.2018    source источник
comment
Я бы сказал, что упомянутый комментарий неверен.   -  person Eugene Sh.    schedule 30.07.2018
comment
\0 сам по себе создает NUL, но стандартное поведение для \001 заключается в том, чтобы создавать символ с числовым значением 1, как вы заметили. (Общее правило состоит в том, что обратная косая черта, за которой следует одна, две или три восьмеричных цифры, представляет собой одиночный экран.) Пожалуйста, процитируйте нам полный и неотредактированный фактический комментарий, который вы видели, по крайней мере, с пятью строками контекст выше и ниже, и, если возможно, дайте ссылку на всю программу, которую вы цитируете.   -  person zwol    schedule 30.07.2018
comment
Есть разница между '\001' и "\001"   -  person Saeid Yazdani    schedule 30.07.2018
comment
@SaeidYazdani Но здесь это не совсем уместно   -  person Eugene Sh.    schedule 30.07.2018
comment
Да, @SaeidYazdani, и ОП дает все основания понимать это.   -  person John Bollinger    schedule 30.07.2018
comment
Хм, комментарий определенно неверен для стандартного C, но то, как он написан, заставляет меня задаться вопросом, могли ли быть компиляторы до C89, которые не всегда использовали три восьмеричных цифры (если они были доступны) после обратной косой черты. Я не могу припомнить, чтобы я споткнулся об один, но я совсем недостаточно взрослый, чтобы испытать все разнообразие достандартного C. Xing, не могли бы вы рассказать нам, где вы прочитали этот комментарий?   -  person zwol    schedule 31.07.2018


Ответы (3)


Это стандартное поведение или просто что-то с Linux и gcc? Почему он не устанавливает ноль?

Поведение кода, который вы представляете, соответствует требованиям стандарта. И в строковых литералах, и в целочисленных символьных константах восьмеричные escape-последовательности могут содержать одну, две или три цифры, и стандарт C указывает, что

Каждая восьмеричная [...] escape-последовательность является самой длинной последовательностью символов, которая может составлять escape-последовательность.

(C2011, 6.4.4.4/7)

В этом контексте дополнительно важно, что \0 — это восьмеричная escape-последовательность, а не специальный независимый код для нулевого символа. Более широкий контекст приведенной выше цитаты прояснит это.

В строковом литерале "\001" за обратной косой чертой следуют три восьмеричных цифры, а восьмеричная escape-последовательность может состоять из трех цифр, поэтому escape-последовательность состоит из обратной косой черты и всех трех цифр. Первым символом результирующей строки является тот, у которого целочисленное значение равно 1.

Если по какой-то причине вам нужен строковый литерал, состоящий из нулевого символа, за которым следуют десятичные цифры 0 и 1, вы можете выразить нуль с помощью полного трехзначного escape-последовательности,

"\00001"

или разделить его так:

"\0" "01"

C будет соединять соседние строковые литералы для получения желаемого результата.

person John Bollinger    schedule 30.07.2018

Я видел комментарий, в котором говорилось, что инициализация массива символов с помощью «\ 001» поставит нуль в качестве первого символа.

Этот комментарий был ошибочным.

Из 6.4.4.1 Целочисленные константы, параграф 3, выделение мое:

Восьмеричная константа состоит из префикса 0, за которым может следовать только последовательность цифр от 0 до 7.

Но то, что мы здесь рассматриваем, вообще не целочисленная константа. На самом деле у нас есть восьмеричная управляющая последовательность. И это определяется следующим образом (в 6.4.4.4 Символьные константы):

octal-escape-sequence:
        \ octal-digit
        \ octal-digit octal-digit
        \ octal-digit octal-digit octal-digit

Определение — как для целочисленных констант, так и для символьных констант — является «жадным», как описано в параграфе 7:

Каждая восьмеричная или шестнадцатеричная escape-последовательность является самой длинной последовательностью символов, которая может составлять escape-последовательность.

Это означает, что если за первой восьмеричной цифрой следует что-то, что может быть восьмеричной цифрой, следующий символ считается восьмеричной цифрой, принадлежащей этой константе (максимум до три в случае символьных констант - не так для целочисленных констант!).

Следовательно, ваш "\001" действительно является символом со значением 1.

Обратите внимание, что в то время как восьмеричные символьные константы содержат максимум три символа (что делает такую ​​константу вполне безопасной для использования, если дополнить ее ведущими нулями, что необходимо для получения длины в три цифры), шестнадцатеричные< Символьные константы /em> работают до тех пор, пока есть шестнадцатеричные цифры (потенциально переполнение типа char, для инициализации которого они предназначены).

person DevSolar    schedule 30.07.2018
comment
Наиболее важной частью является нецитируемый port70.net/~nsz/ c/c11/n1570.html#6.4.4.4p7 - person Eugene Sh.; 30.07.2018
comment
Это то, что перефразирует мой последний абзац, да. (Я не хотел втягивать в это формальную спецификацию утечки для шестнадцатеричной-экранирующей-последовательности.) - person DevSolar; 30.07.2018
comment
The definition -- both for integer constants as well as character constants -- is "greedy" – это пример правила максимального жевания? - person Arkadiusz Drabczyk; 30.07.2018
comment
@ArkadiuszDrabczyk: на самом деле я не уверен, что определение синтаксиса C в целом должно быть жадным; в тех местах, где я знаю, что это имеет значение, это явно указано в окружающем тексте. - person DevSolar; 30.07.2018