2013-10-01 3 views
-1
#include<stdio.h> 

int main() 
{ 
    printf("%s\n", "Hello"); 
    printf("%s\n", &"Hello"); 
    return 0; 
} 

Output : 
Hello 
Hello 

Может ли кто-нибудь объяснить мне, почему "Hello" и &"Hello" дают одинаковый результат?printf строка литерала с адресом оператора

+4

Нет ссылок в C. Унарный '&' является адресом оператора. – us2012

+1

@alkis Вы не редактировали заголовок? – devnull

+0

Какой компилятор вы используете, BTW? – devnull

ответ

3

Это происходит потому, что строковый литерал рассматривается как const char массив. Код эквивалентен написания этого:

char array [] = "Hello"; 
printf("%s\n", array); 
printf("%s\n", &array); 
  • Когда вы передаете имя массива в функции, ожидающей указатель, массив «затухает» в указатель.
  • Когда вы передаете адрес массива, вы получаете указатель на массив ... который также указывает на тот же адрес.

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


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

printf("%p\n", "Hello"); 
printf("%p\n", "Hello"); 

Он должен печатать один и тот же адрес в два раза, до тех пор, как строки идентичны. Измените одну из строк, и вы получите разные адреса.

+0

Это отличный ответ. Спасибо. – alkis

+0

@alkis Просто убедитесь, что прочитали эту ссылку, которую я разместил, если вы еще этого не сделали :) Это очень хорошее чтение для начинающих и ветеранов. – Lundin

+0

я, безусловно обязательно. Спасибо, сэр за вашу помощь. – alkis

0

Это в контексте с printf «s %s

Базовый адрес для следующих такие же:

&"Hello" ==> &"Hello"[0] ==> "Hello"+0 ==> "Hello"

+0

Try: 'Е («% s \ п»,«Привет»+2)' и видеть то, что я имел в виду – P0W

+2

я не downvote, но я не согласен с Вашим ответом. & "Hello" имеет тип 'char (*) [6]' while '&" Hello "[0]' имеет тип 'char *'. Ваш '==>', по-видимому, означает, что они эквивалентны. – cnicutar

+0

@cnicutar Я знаю, намерение было сказать любой '«String»+ i' поведение с' '% s' printf' в (базовые адреса) – P0W

4

Применение & к "Hello" дает указатель на этот массив (да, является массивом и в этом контексте не распадается на указатель).

Это все еще указывает на том же месте, но имеет другой тип (он имеет char (*)[6], то есть указатель на массив из 6 символов). printf игнорирует реальный тип указателя и обрабатывает его как char *, поэтому он «работает».


Технически используя «неправильный» тип объекта для printf спецификатора является неопределенным поведением. Включение предупреждений должно указывать на это в современных компиляторах.

+0

Спасибо. Вы действительно помогли. – alkis

+0

Как и в буквальном ' "Привет"' распадается на указатель 'полукокс *', но '& "Hello"' не затухает, это указатель массива типа 'полукокса (*) [6]'. – Lundin

+0

@ Lundin Что я имел в виду, так это то, что в контексте применения '&', '" Hello "' не распадается на указатель. – cnicutar

0

"Hello" и &"Hello" оба возвращают базовый адрес массива char (строка).

и вы используете %s, который используют для печати строки переменной