Строковый литерал 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, который используется для печати строковой переменной

Другие вопросы по тегам