Как инициализировать массив символов без нулевого терминатора?

Массив символов является частью сетевого сообщения, которое имеет четко определенную длину, поэтому нулевой терминатор не требуется.

struct Cmd {
    char cmd[4];
    int arg;
}

struct Cmd cmd { "ABCD" , 0 }; // this would be buffer overflow

Как я могу инициализировать этот массив символов членов cmd? без использования таких функций, как strncpy?

Вам необходимо инициализировать структурную переменную следующим образом: struct Cmd cmd{ {'A','B','C','D'}, 0}; . Если вы укажете «ABCD», это будет считаться строковым литералом и будет храниться в указателе const char, а строковый литерал заканчивается на «\0».

sonulohani 13.05.2019 06:31

@sonulohani нет, это не «необходимо». Помимо отсутствующего =, данная инициализация в порядке.

Jens Gustedt 13.05.2019 07:55

@JensGustedt Трюк с C, молча пропускающим нулевой терминатор, опасен - на мой взгляд, недостаток языка. Поэтому предоставление инициализатора {'A','B','C','D'} является хорошей практикой: это самодокументирующийся код, показывающий, что программист знает об отсутствии нулевого завершения, но он также позволяет компиляторам/статическим анализаторам выдавать предупреждение в другом месте кода, когда инициализатор строкового литерала приводит к строке, которая не завершается нулем.

Lundin 13.05.2019 09:03

@Lundin «необходимо» и «хорошая практика» - это не одно и то же.

Jens Gustedt 14.05.2019 00:50

@JensGustedt Вы написали, что с инициализацией все в порядке. Но это не так, поскольку он содержит потенциальную скрытую ошибку.

Lundin 14.05.2019 08:28
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
7
5
2 944
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Завершающий нулевой символ игнорируется, если размер массива char совпадает с количеством символов в инициализаторе. Таким образом, у cmd не будет нулевого терминатора.

Соответствующий раздел стандарта C11 (n1570) — 6.7.9/14:

An array of character type may be initialized by a character string literal or UTF−8 string literal, optionally enclosed in braces. Successive bytes of the string literal (including the terminating null character if there is room or if the array is of unknown size) initialize the elements of the array.

И утверждение:

struct Cmd cmd { "ABCD" , 0 };

должно быть:

struct Cmd cmd  = { "ABCD" , 0 };

Обратите внимание, что это еще одна область, в которой C и C++ имеют разные взгляды на то, как все должно работать. C++11 (ISO/IEC 14882:2012) §8.5 Инициализаторы, §8.5.2 Массивы символов, §2: Инициализаторов не должно быть больше, чем элементов массива. [Пример: char cv[4] = "asdf"; // error имеет неправильный формат, так как нет места для подразумеваемого завершающего '\0'. — конец примера]

Jonathan Leffler 13.05.2019 08:21

означает ли это, что C++ отличается от C в этом вопросе?

fluter 13.05.2019 10:41

@флютер: Да. В С++ он имеет неправильный формат. Это означает, что это недопустимая программа (программа, построенная в соответствии с правилами синтаксиса, диагностируемыми семантическими правилами и правилом одного определения).

P.W 13.05.2019 11:02

Другие вопросы по теме