Программирование на C: печать строки, заканчивающейся нулем, с использованием символьного указателя

#arrays #c #char

#массивы #c #символ

Вопрос:

Я просто привыкаю к указателям в C. Я думал об использовании %s для печати первого символа массива символов.

Почему в следующем коде %s не работает, но %c работает? Если *my_string разыменовывает первое значение массива символов, не будет ли %s пытаться напечатать все символы в памяти, начиная с этого адреса, и продолжать до тех пор, пока не будет достигнут нулевой символ?

Кроме того, как это printf("%s", my_string) работает, а printf("%s" *my_string) нет?

 char* my_string = "The original value.";
printf("Value of my_string: %sn", my_string);
my_string = "The new value.";
printf("Value of my_string: %sn", *my_string); // Error
printf("Value of my_string: %cn", *my_string); // Prints only the first letter 'T', but does not have any errors
  

Комментарии:

1. %s ожидает строку, заканчивающуюся нулем, которая *my_string не является указателем, это char значение, и %s пытается использовать это значение в качестве указателя, что, очевидно, неверно.

2. » Если *my_string разыменовывает первое значение», так и есть. Это означает, что он переходит по адресу и извлекает оттуда содержимое. «разве %s не попытался бы напечатать все символы в памяти, начинающиеся с этого адреса», но my_string это адрес, *my_string это содержимое этого адреса. %s ожидается первое, а не второе.

Ответ №1:

Звездочка * отменяет ссылку указателя на тип, на который она указывает, поэтому, когда my_string это указатель на символ, *my_string это символ. Ваш компилятор C видит строку вашего формата, содержащую a %s и параметр *my_string , который является символом, и выдает вам ошибку.

Чтобы вывести всю строку, выведите ее, как при вашем первом вызове printf , чтобы напечатать только один символ, сделайте, как вы делали при вашем последнем вызове printf .

Ответ №2:

почему %s не работает, но %c работает?

Это правило, по которому работает функция printf. Для «%s» ожидается указатель на строку, заканчивающуюся нулем, а для «%c» — один символ.

Если *my_string разыменовывает первое значение массива символов, не будет ли %s пытаться напечатать все символы в памяти, начиная с этого адреса, и продолжать до тех пор, пока не будет достигнут нулевой символ?

ДА. Поэтому вы должны быть осторожны, если это слишком длинная строка, и эти символы могут быть напечатаны перед нулевым окончанием.

Кроме того, почему работает printf(«%s», my_string), а printf(«%s» *my_string) — нет?

Для «%s» ожидается указатель. «*my_string» — это символ.

Комментарии:

1. Хороший первый ответ.

Ответ №3:

Чтобы понять это, нам нужно разобраться в том, как строка "The original value." хранится в памяти и на что char* my_string указывает.

Мы можем ожидать структуру памяти, подобную этой

 0xDEADBEEF    ASCII T
0xDEADBEEF 1  ASCII h
0xDEADBEEF 2  ASCII e
0xDEADBEEF 3  ASCII <space>
...
0xDEADBEEF 16 ASCII u
0xDEADBEEF 17 ASCII e
0xDEADBEEF 18 ASCII .
0xDEADBEEF 19       0
  

Итак, когда у вас есть a, char* my_string это указывает на первый символ или, в данном случае, на адрес 0xDEADBEEF . Поэтому, когда вы используете %s в printf , он будет перебирать все символы, начиная с первого, на который вы указали, пока не достигнет . Но *my_string считывается только первый символ по этому адресу. По этой причине нам нужно присвоить ей указатель.