Подтвердить что ты не робот

Струнда сходит с ума, если я не дам ему немного дополнительной комнаты. Может ли кто-нибудь объяснить, что здесь происходит?

Во-первых, я хотел бы сказать, что я новичок в C/С++, я изначально являюсь разработчиком PHP, поэтому меня разводят, чтобы злоупотреблять переменными любым способом, который мне нравится.

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

Во всяком случае, это мой простой кусок кода:

char IP[15] = "192.168.2.1";
char separator[2] = "||";   

puts( separator );

Вывод:

||192.168.2.1

Но если я изменил определение separator на:

char separator[3] = "||";

Я получаю желаемый результат:

||

Итак, почему мне нужно было дать человеку дополнительное пространство, чтобы он не спал с человеком перед ним?

4b9b3361

Ответ 1

Это потому, что вы получаете строку с нулевым завершением, когда длина separator принудительно равна 2.

Всегда помните, чтобы выделить дополнительный символ для нулевого терминатора. Для строки длины N вам нужны символы N+1.

Как только вы нарушите это требование, любой код, который ожидает строки с нулевым завершением (включенная функция puts()), будет работать в undefined.

Лучше всего не форсировать определенную длину:

char separator[] = "||";

выделит массив точно соответствующего размера.

Ответ 2

Строки в C заканчиваются NUL. Это означает, что для строки из двух символов требуются три байта (два для символов и третий для нулевого байта, обозначающий конец строки).

В вашем примере можно опустить размер массива, и компилятор выделит правильную сумму хранения:

char IP[] = "192.168.2.1";
char separator[] = "||";

Наконец, если вы кодируете С++, а не C, вам лучше использовать std::string.

Ответ 3

Если вы все равно используете С++, я бы рекомендовал использовать класс std::string вместо строк C - намного проще и менее подвержен ошибкам IMHO, особенно для людей с языком сценариев.

Ответ 4

В конце каждой строки есть скрытый нулевой символ '\ 0'. Вы должны оставить для этого пространство.

Если вы делаете

char seperator[] = "||";    

вы получите строку размера 3, а не размер 2.

Ответ 5

Потому что в строках C nul завершается (их конец помечен 0 байтом). Если вы объявляете разделитель как массив из двух символов и даете им оба ненулевых значения, то нет терминатора! Поэтому, когда вы puts массив почти все можно было бы привязать к концу (что бы ни случилось, когда он сидит в памяти за концом массива), в этом случае кажется, что это массив IP).

Изменить: это неверно. См. комментарии ниже.

Когда вы создаете длину массива 3, у дополнительного байта в нем есть 0, что завершает строку. Однако вы, вероятно, не можете полагаться на это поведение - если значение не инициализировано, оно может действительно содержать что-либо.

Ответ 6

В строках C заканчивается специальный символ '\0', поэтому ваш разделительный литерал "||" на самом деле один символ длиннее. Функция puts просто печатает каждый символ, пока не встретит '\0' - в вашем случае один после строки IP.

Ответ 7

В C строки включают в себя (невидимый) нулевой байт в конце. Вы должны учитывать этот нулевой байт.

char ip[15] = "1.2.3.4";

в приведенном выше коде, ip имеет достаточно места для 15 символов. 14 "обычных символов" и нулевой байт. Он слишком короткий: должен быть char ip[16] = "1.2.3.4";

ip[0] == '1';
ip[1] == '.';
/* ... */
ip[6] == '4';
ip[7] == '\0';

Ответ 8

Поскольку никто не указал на это до сих пор: если вы объявите свою переменную как это, строки будут автоматически завершаться нулями, и вам не нужно будет вмешиваться в размеры массива:

const char* IP = "192.168.2.1"; 
const char* seperator = "||";

Обратите внимание, однако, что я предполагаю, что вы не собираетесь изменять эти строки.

Но, как уже упоминалось, безопасный способ в С++ будет использовать класс std::string.

Ответ 9

A C "String" всегда заканчивается в NULL, но вы просто не передаете его в строку, если вы пишете char разделитель [2] = "||". И puts ожидает, что этот \0 на ned в первом случае он пишет до тех пор, пока не найдет \0, и здесь вы можете увидеть, где он находится в конце IP-адреса. Интересный enoiugh вы даже можете увидеть, как локальные переменные выкладываются в стеке.

Ответ 10

Линия: char seperator[2] = "||"; должен получить вам поведение undefined, так как длина этого массива символов (включая нуль в конце) будет равна 3.

Кроме того, с компилятором вы скомпилировали вышеуказанный код? Я скомпилировал с g++, и он отметил указанную выше строку как ошибку.

Ответ 11

String в C\С++ завершают нуль, т.е. имеют скрытый нуль в конце.

Итак, ваша строка разделителя будет:

{'|', '|', '\0'} = "||"