Разница между char * и char [] (2) [дубликаты]

0

Я попытался вычислить длину массива символов следующими способами:

char *s="abcde";
int n=sizeof(s)/sizeof(s[0]);
cout<<n;

n выводится как постоянное значение 4, независимо от того, как долго длится строка. Принимая во внимание, что я объявил массив как

char s[]="abc";
int n=sizeof(s)/sizeof(s[0]);
cout<<n;

Выход по-прежнему остается 4. Я понимаю, что во втором случае он включает заключительный символ '\ 0', следовательно, вывод. Единственное, что я не понял, - это то, почему я получаю постоянный вывод в первом случае.

Теги:
string
arrays
pointers

4 ответа

2
Лучший ответ

В этом фрагменте кода

char *s="abcde";
int n=sizeof(s)/sizeof(s[0]);
cout<<n;

s - указатель. Поэтому sizeof (s) равен размеру указателей в системе. В вашей системе размер указателя равен 4. Поскольку тип s [0] является char, тогда его размер равен 1, и вы получите значение 4.

Во втором фрагменте кода

char s[]="abc";
int n=sizeof(s)/sizeof(s[0]);
cout<<n;

s - массив. Его размер определяется размером инициализатора. Поскольку строковый литерал "abc" имеет размер, равный 4, так как нулевой конец также подсчитывается, тогда размер массива s равен 4. Если вы, например, напишете

char s[]="abcde";
int n=sizeof(s)/sizeof(s[0]);
cout<<n;

то размер строкового литерала равен 6, и соответственно размер массива будет равен 6.

Вы можете переписать один и тот же код следующим образом

char s[6]="abcde";
int n=sizeof(s)/sizeof(s[0]);
cout<<n;

Если вы напишете этот код как

char s[10]="abcde";
int n=sizeof(s)/sizeof(s[0]);
cout<<n;

то размер массива будет равен 10, хотя размер строкового литерала равен 6. Все остальные элементы массива, которые не имеют инициализатора, будут инициализированы нулем. Это будет выглядеть так:

[a][b][c][d][e]['\0']['\0']['\0']['\0']['\0']
3

char *s является указателем на символ или последовательность символов char. В 32-битной архитектуре она будет иметь ширину 4 байта, поэтому sizeof(s) будет 4. Один символ (обычно) 1 байт, поэтому sizeof(s[0]) будет 1. Следовательно, n будет равно 0.

Когда вы используете тип char[] компилятор рассматривает его как последовательность фиксированной длины, он просто определяет, как долго последовательность будет для вас, в вашем случае это 4 символа. Однако, если бы у вас было:

char s[]="Hello, world";
int n=sizeof(s)/sizeof(s[0]);

Тогда n будет 13, так как там введен 12 символов, плюс нулевой ограничитель в конце.

  • 2
    Я так счастлив, что C ++ 11, наконец, запрещает присваивать строковые литералы char* .
3

С char *s вы создаете указатель s, указывающий на другую память. С char s[] =... вы создаете массив из N символов.

Может быть, это проще, если вы посмотрите на это следующим образом:

Для версии указателя char *s = "abcde" это будет что-то вроде

+---+      +-----------+
| s | ---> | "abcde\n" |
+---+      +-----------+

Хотя для случая с массивом char s[] = "abc" это будет похоже на

+---------+
| "abc\0" |
+---------+

Это должно помочь вам понять, почему вы не можете использовать sizeof для указателя, поскольку он возвращает размер указателя, а не то, на что он указывает. Я также добавил ограничитель строк, который существует для всех строковых литералов, и именно поэтому вы получаете размер 4 для массива, на самом деле это четыре символа.

0

В первом случае s является объектом типа char*. sizeof(s) оценивает размер этого объекта "указатель на символ", который равен 4 (в вашей среде исполнения), а не длина строки, на которую указывает s (для чего оценивается strlen(s)).

Ещё вопросы

Сообщество Overcoder
Наверх
Меню