Необъяснимое поведение при печати строк в C - PullRequest
0 голосов
/ 09 января 2020

Следующий код работает как положено и выводит ABC:

#include <stdio.h>

void printString (char toPrint [100]);

int main()
{
  char hello [100];
  hello[0] = 'A';
  hello[1] = 'B';
  hello[2] = 'C';
  hello[3] = '\0';

  printString(hello);

}

void printString (char toPrint [100]) 
{
  int i = 0;

  while (toPrint[i] != '\0')
  {
    printf("%c", toPrint[i]);
    ++i;
  }

}

Но если я удаляю строку, которая добавляет нулевой символ

  hallo[3] = '\0';

, я получаю случайный вывод, например wBCÇL, ╗BCÄL, ┬BCNL et c.

Почему это так? Я ожидал, что l oop в printString () будет работать вечно, потому что он не сталкивается с '\ 0', но что происходит с 'A', 'B' и 'C'? Почему B и C все еще отображаются в выводе, но A заменяется каким-то случайным символом?

Ответы [ 3 ]

1 голос
/ 09 января 2020

Ваше объявление hello оставляет его неинициализированным и заполненным случайными байтами

int main()
{
 char hello [100];
 ...
}

Если вы хотите, чтобы инициализированный массивом был нулевой, используйте

int main()
{
 char hello [100] = {0};
 ...
}
0 голосов
/ 09 января 2020

Когда вы объявляете automati c как char hello [100];, первое, что нужно понять, это то, что байты 100 могут содержать что угодно. Вы должны назначить значения каждому байту в явном виде, чтобы сделать / иметь что-то осмысленное.

Вы прекращаете работу l oop, когда вы обнаружите \0 или символ NUL. Теперь, если вы закомментируете инструкцию, которая ставит \0 после символа c, ваш l oop будет работать до тех пор, пока вы действительно не найдете \0.

Ваш массив может содержать \0 в некоторых указать или не может. Есть шансы, что вы могли бы go за пределами 100 байт, все еще ищущих \0, и вызвать неопределенное поведение . Вы также вызываете UB, когда пытаетесь работать с неназначенным фрагментом памяти.

0 голосов
/ 09 января 2020

Должно быть, по чистой случайности, значение для \ r где-то в ячейках памяти, следующих за значениями в моем массиве привет . Вот почему мой символ «А» был перезаписан.

На других машинах «AB C» выводился, как и ожидалось, за ним следовали случайные символы.

Инициализация массива с 0, намеренно опущена здесь, конечно, решается проблема.

edit: я позволил коду распечатать каждый символ в двоичном виде, и toPrint [5] действительно было 00001101 , что является ASCII для \ r (возврат каретки).

...