Чем отличается массив String от общего массива в C?
массив - это непрерывная последовательность объектов одного типа. 1
A string - это непрерывная последовательность символов, оканчивающаяся первым нулевым символом. 2 Таким образом, строка - это просто массив символов, в котором мы отмечаем конецпоставив символ со значением ноль.(Часто строки временно хранятся в больших массивах, которые содержат больше элементов после нулевого символа.)
Таким образом, каждая строка является массивом.Строка - это просто массив с двумя дополнительными свойствами: ее элементы являются символами, а ноль обозначает конец.
& str и & str [0] имеют одинаковое значение адреса.
&str
- адрес массива.&str[0]
- это адрес первого элемента.
Это одно и то же место в памяти, потому что первый элемент начинается в том же месте, что и массив.Поэтому, когда вы их печатаете или просматриваете, они часто выглядят одинаково.(Адреса могут иметь разные представления, так же, как вы можете написать «200», «двести» или «2 • 10 2 » для одного и того же номера. Так что один и тот же адрес может иногда выглядеть по-разному. В большинствеВ современных системах адрес - это просто число для места в памяти, и вы не увидите различий. Но это может произойти.)
printf("%x(%d) : %c\n",&str[i], &str[i], str[i]);
Это неправильный способ печати адресов.Чтобы правильно распечатать адрес, преобразуйте его в void *
и используйте %p
3 :
printf("%p(%p) : %c\n", (void *) &str[i], (void *) &str[i], str[i]);
printf("\n\n%x(%d) : %c or %s",&str, &str, str, str);
…
Я использовал str с% c, тогда у него есть первые два числа str .
В приведенном выше printf
,третья спецификация преобразования - %c
, а соответствующий аргумент - str
.%c
предназначен для использования для символа, 4 , но вы передаете ему аргумент, который является указателем.Возможно, здесь произошло то, что printf
использовал указатель, который вы передали ему, как если бы это был int
.Тогда printf
, возможно, использовал часть этого int
, как если бы это был символ, и напечатал его.Итак, вы увидели часть адреса, показанную в виде символа.Тем не менее, немного неясно, когда вы пишете «первые два числа имеют адрес str ».Вы можете показать точный вывод, чтобы уточнить это.
Хотя printf
мог использовать указатель, как если бы он был int
, поведение для этого не определено стандартом C.Передача неправильного типа для printf
преобразования является неправильной, и могут возникнуть другие результаты, в том числе программа, выводящая мусор или сбой.
И как scanf ("% s", & str) распределить строку по каждому пространству массива символов?
Правильный способ передачи str
в scanf
для %s
- передать адрес первого символа, &str[0]
,C имеет специальное правило для массивов, таких как str
: если массив используется в выражении, отличном от операнда sizeof
или оператора адреса &
, он преобразуется в указатель на свой первый элемент. 5 Таким образом, вы можете использовать scanf("%s", str)
, и он будет таким же, как scanf("%s", &str[0])
.
Однако, когда вы используете scanf("%s",&str)
, вы передаете адрес массивавместо адреса первого символа.Хотя это одно и то же место, они бывают разных типов.Напомним, что два разных типа указателей на один и тот же адрес могут иметь разные представления.Поскольку scanf
не знает фактического типа передаваемого вами аргумента, он должен полагаться на спецификатор преобразования.%s
указывает scanf
ожидать указатель на символ. 6 Неправильно передавать указатель на массив.
C имеет этот кодПотому что некоторые машины имеют разные типы указателей, а некоторые системы могут передавать разные типы указателей по-разному.Тем не менее, часто код, который передает &str
вместо str
, ведет себя так, как хотел автор, потому что реализация C использует одно и то же представление для обоих указателей.Таким образом, scanf
может фактически получить значение указателя, необходимое для работы %s
. 7
Сноски
1 C 2018 6.2.5 20. (Это означает, что информация взята из версии C стандарта 2018 года, ISO / IEC 9899, Информационные технологии - Языки программирования - C , пункт 6.2.5, пункт 20.)
2 C 2018 7.1.1 1. Обратите внимание, что завершающий нулевой символ считается частью строки, хотя он не учитывается функцией strlen
.
3 C 2018 7.21.6.1 8.
4 Технически аргумент должен иметь тип int
, а printf
преобразует его в unsigned char
ипечатает символ с этим кодом.C 2018 7.21.6.1 8.
5 C 2018 6.3.2.1 3. Строковый литерал, используемый для инициализации массива, как в char x[] = "Hello";
, также не преобразуется в указатель.
6 C 2018 7.21.6.2 12.
7 Даже если реализация C использует одни и те же представления для разных типов указателей, этоне гарантируйте, что использование одного типа указателя там, где требуется другой, будет работать.Когда компилятор оптимизирует программу, он полагается на то, что автор программы выполнил правила, и оптимизации могут изменить программу таким образом, чтобы это не нарушало программу, которая следовала правилам, но нарушало программу, нарушающую правила.