Присвоение после инициализации конкретному индексу в массиве - PullRequest
0 голосов
/ 21 сентября 2018

После назначения 26-го элемента при печати все еще печатается «Компьютер», несмотря на то, что я присвоил символ 26-му индексу.Я ожидаю что-то вроде этого: «Компьютер K»

В чем причина?

#include <stdio.h>
int main()
{
  char m1[40] = "Computer";
  printf("%s\n", m1);   /*prints out "Computer"*/
  m1[26] = 'K';
  printf("%s\n", m1);   /*prints out "Computer"*/
  printf("%c", m1[26]); /*prints "K"*/
}

Ответы [ 6 ]

0 голосов
/ 21 сентября 2018

Так же, как дополнение к ответам других пользователей, вы должны попытаться ответить на свой вопрос, проявляя большую активность в процессе обучения.Достаточно написать простую программу, чтобы понять, что происходит.

int main()
{
  char m1[40] = "Computer";
  printf("%s\n", m1);   /*prints out "Computer"*/
  m1[26] = 'K';


  for(size_t index = 0; index < 40; index++)
  {
      printf("m1[%zu] = 0x%hhx ('%c')\n", index, (unsigned char)m1[index], (m1[index] >=32) ? m1[index] : ' ');
  }

}
0 голосов
/ 21 сентября 2018

Всякий раз, когда вы частично инициализируете массив, оставшиеся элементы заполняются нулями.(Это правило в стандарте C, C17 6.7.9 §19.)

Поэтому char m1[40] = "Computer"; заканчивается в памяти следующим образом:

[0] = 'C'
[1] = 'o' 
... 
[7] = 'r'
[8] = '\0' // the null terminator you automatically get by using the " " syntax
[9] = 0    // everything to zero from here on
... 
[39] = 0

Теперь, конечно, \0и 0 означает то же самое, значение 0. Любой из них будет интерпретирован как нулевой терминатор.

Если вы перезапишете индекс 26, а затем распечатаете массив как строку, он будет печататься только до тех пор, пока не встретит первый нулевой терминатор в индексе 8.

Если вы сделаете это такоднако:

#include <stdio.h>

int main()
{
  char m1[40] = "Computer";
  printf("%s\n", m1); // prints out "Computer"
  m1[8] = 'K';
  printf("%s\n", m1); // prints out "ComputerK"
}

Вы перезаписываете нулевой терминатор, и следующий ноль, который оказался в массиве, вместо этого обрабатывается как нулевой терминатор.Этот код работает только потому, что мы частично инициализировали массив, поэтому мы знаем, что больше нулей в конце.

Если бы вы вместо этого написали

int main()
{
  char m1[40];
  strcpy(m1, "Computer");

Это не инициализация, а присвоение во время выполнения.strcpy будет устанавливать только индекс от 0 до 8 («Компьютер» с нулевым термином в индексе 8).Оставшиеся элементы будут оставлены неинициализированными для значений мусора, и запись m1[8] = 'K' уничтожит строку, так как она больше не будет надежно завершаться нулем.При попытке распечатать вы получите неопределенное поведение: что-то вроде вывода мусора или сбоя программы.

0 голосов
/ 21 сентября 2018

Это потому, что после "Computer" в вашем массиве есть нулевой терминатор (\0).Если вы добавите символ после этого \0, он не будет напечатан, потому что printf() прекращает печать, когда встречает нулевой терминатор.

0 голосов
/ 21 сентября 2018

В 8-м индексе этой строки найден символ \0 и %s печатается только до тех пор, пока не найдет \0 (конец строки, отмеченный \0) - в 26 символ k есть, но он не будет напечатан, поскольку \0 найден до этого.

0 голосов
/ 21 сентября 2018
char s[100] = "Computer";

в основном совпадает с

char s[100] = { 'C', 'o', 'm', 'p', 'u','t','e','r', '\0'};

Поскольку printf останавливается, когда строка заканчивается на 0, он не печатает символ 26

0 голосов
/ 21 сентября 2018

В строках Си 0-концевые.Ваша инициализация заполняет все элементы массива после 'r' значением 0. Если вы поместите не-0 символ в любое случайное поле массива, это ничего не изменит в полях до или после этого элемента.

Это означает, что ваша строка по-прежнему оканчивается нулем сразу после 'r'.Как любая функция должна знать, что после этой строки может следовать какая-то другая строка?

...