Я немного запутался в чем-то. У меня сложилось впечатление, что правильный способ чтения C-строки scanf()
шел по линии
(не берите в голову возможное переполнение буфера, это просто простой пример)
char string[256];
scanf( "%s" , string );
Тем не менее, следующее, кажется, тоже работает,
scanf( "%s" , &string );
Это только мой компилятор (gcc), чистая удача или что-то еще?
scanf
, и вопрос, и принятый ответ сосредоточены на это, и опустить критически важные ограничения для максимальной длины ввода, которые должны использоваться в реальном коде (но помимо этого вопроса).Ответы:
Массив "разлагается" на указатель на свой первый элемент, поэтому
scanf("%s", string)
эквивалентенscanf("%s", &string[0])
. С другой стороны,scanf("%s", &string)
передает указатель наchar[256]
, но он указывает на то же место.Затем
scanf
, при обработке хвоста своего списка аргументов, попытается вытащить achar *
. Это правильно, когда вы прошлиstring
или&string[0]
, но когда вы прошли,&string
вы зависите от того, что не гарантирует языковой стандарт, а именно от того, что указатели&string
и&string[0]
- указатели на объекты различных типов и размеров, которые начать с того же места - представлены одинаково.Я не верю, что когда-либо сталкивался с системой, в которой это не работает, и на практике вы, вероятно, в безопасности. Тем не менее, это неправильно, и это может дать сбой на некоторых платформах. (Гипотетический пример: реализация «отладки», которая включает информацию о типе с каждым указателем. Я думаю, что реализация C на Symbolics «Lisp Machines» сделала что-то вроде этого.)
источник
&string
работающий так же , какstring
(а в результате случайного повреждения памяти, как и другие ответы неправильно утверждают):printf("%x\n%x\n", string, &string);
string
указатель и&string
адрес этого указателя, поэтому они НЕ взаимозаменяемы. Как объясняет Гарет, даже в случае распада массива,string
и&string
технически они не являются одними и теми же типами (даже если они взаимозаменяемы для большинства архитектур), и gcc выдаст предупреждение для вашего второго примера, если вы включите-Wall
.Я думаю, что это ниже, является точным, и это может помочь. Не стесняйтесь исправлять это, если вы обнаружите какие-либо ошибки. Я новичок в C.
включая нулевой символ завершения
'\0'
&str
,&str[0]
иstr
все три представляют одно и то же место в памяти, которое является адресом первого элемента массиваstr
char * strPtr = & str [0]; // объявление и инициализация
Кроме того, вы можете разделить это на две части:
strPtr
это указатель наchar
strPtr
указывает на массивstr
strPtr
переменная со своим адресом в памятиstrPtr
переменная, которая хранит значение адреса&str[0]
strPtr
собственный адрес в памяти отличается от адреса памяти, который он хранит (адрес массива в памяти aka & str [0])&strPtr
представляет адрес самого strPtrЯ думаю, что вы могли бы объявить указатель на указатель как:
объявляет и инициализирует адресом указателя strPtr
В качестве альтернативы вы можете разделить на две части:
*vPtr
указывает на указатель strPtr*vPtr
переменная со своим адресом в памяти*vPtr
переменная, которая хранит значение адреса & strPtrstr++
,str
адрес естьconst
, но вы можете сделатьstrPtr++
источник