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