Массив символов является частью сетевого сообщения, которое имеет четко определенную длину, поэтому нулевой терминатор не требуется.
struct Cmd {
char cmd[4];
int arg;
}
struct Cmd cmd { "ABCD" , 0 }; // this would be buffer overflow
Как я могу инициализировать этот массив символов членов cmd? без использования таких функций, как strncpy
?
@sonulohani нет, это не «необходимо». Помимо отсутствующего =
, данная инициализация в порядке.
@JensGustedt Трюк с C, молча пропускающим нулевой терминатор, опасен - на мой взгляд, недостаток языка. Поэтому предоставление инициализатора {'A','B','C','D'}
является хорошей практикой: это самодокументирующийся код, показывающий, что программист знает об отсутствии нулевого завершения, но он также позволяет компиляторам/статическим анализаторам выдавать предупреждение в другом месте кода, когда инициализатор строкового литерала приводит к строке, которая не завершается нулем.
@Lundin «необходимо» и «хорошая практика» - это не одно и то же.
@JensGustedt Вы написали, что с инициализацией все в порядке. Но это не так, поскольку он содержит потенциальную скрытую ошибку.
Завершающий нулевой символ игнорируется, если размер массива 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'. — конец примера]
означает ли это, что C++ отличается от C в этом вопросе?
@флютер: Да. В С++ он имеет неправильный формат. Это означает, что это недопустимая программа (программа, построенная в соответствии с правилами синтаксиса, диагностируемыми семантическими правилами и правилом одного определения).
Вам необходимо инициализировать структурную переменную следующим образом: struct Cmd cmd{ {'A','B','C','D'}, 0}; . Если вы укажете «ABCD», это будет считаться строковым литералом и будет храниться в указателе const char, а строковый литерал заканчивается на «\0».