Строковый литерал printf с адресным оператором
#include<stdio.h>
int main()
{
printf("%s\n", "Hello");
printf("%s\n", &"Hello");
return 0;
}
Output :
Hello
Hello
Может кто-нибудь объяснить мне, почему "Hello"
а также &"Hello"
дать тот же результат?
4 ответа
Это потому, что строковый литерал рассматривается как const char
массив. Код эквивалентен написанию этого:
char array [] = "Hello";
printf("%s\n", array);
printf("%s\n", &array);
- Когда вы передаете имя массива функции, ожидающей указатель, массив "разлагается" на указатель.
- Когда вы передаете адрес массива, вы получаете указатель массива... который также указывает на тот же адрес.
Это довольно запутанно, и я думаю, что C FAQ хорошо это объясняет. Вся эта глава о массивах и указателях должна быть обязательной для всех программистов на Си.
Еще одна вещь, на которую стоит обратить внимание: оптимизаторы используют что-то, называемое "объединение строк", что означает, что если компилятор дважды встречает один и тот же строковый литерал в исходном коде, он будет хранить его по одному адресу. Таким образом, ваш код фактически просто печатает содержимое одной и той же ячейки памяти дважды. Чтобы увидеть, используется ли пул строк, просто запустите этот код:
printf("%p\n", "Hello");
printf("%p\n", "Hello");
Он должен печатать один и тот же адрес дважды, если строки идентичны. Измените одну из строк, и вы получите разные адреса.
Применение &
"Hello" возвращает указатель на этот массив (да, это массив, и он не затухает до указателя в этом контексте).
Он по-прежнему указывает на то же место, но имеет другой тип (он имеет char (*)[6]
указатель на массив из 6 символов). printf
игнорирует реальный тип указателя и обрабатывает его как char *
так что "работает".
Технически используя "неправильный" тип объекта для printf
спецификатор - неопределенное поведение. Включение предупреждений должно указывать на это в современных компиляторах.
Это в контексте с printf
"s %s
Базовый адрес для следующего одинаков:
&"Hello" ==> &"Hello"[0] ==> "Hello"+0 ==> "Hello"
"Hello"
а также &"Hello"
оба возвращают базовый адрес char
Массив (строка).
и вы используете %s
, который используется для печати строковой переменной