почему sizeof (* указатель) дает вывод как 1? - PullRequest
0 голосов
/ 08 ноября 2019
#include <stdio.h>
int main()
{
    char *str1 = "Abcde";
    char str2[] = "Abcde";

    printf("sizeof(str1) = %d, sizeof(str2) = %d sizeof(*str1) = %d",
        sizeof(str1), sizeof(str2),sizeof(*str1));

    return 0;
}

приведенный выше код дает вывод sizeof(*str1) =1. Может кто-нибудь объяснить, почему я ожидал, что это будет sizeof("Abcde"), поскольку это разыменование.

Ответы [ 4 ]

2 голосов
/ 08 ноября 2019

sizeof(*str1) равно 1, потому что:

  1. str1 является char *

  2. *str1 является char

  3. Размер char по определению 1.

После назначения "Abcde" для char *вы потеряете весь контекст этой исходной строки, включая ее размер.

1 голос
/ 08 ноября 2019

Другие ответы правильно объясняют, почему sizeof (*str) == 1, но они не решают вашу понятную путаницу.

Массивы C в некотором смысле являются гражданами второго сорта. Объекты массива - это реальные объекты, такие как объекты любого другого типа (целое число, структура и т. Д.), Но язык предоставляет очень мало операций, которые работают непосредственно с массивами.

Вместо этого, объектами массива обычно манипулируют с помощью указателей наих элементы.

В вашем примере у вас есть:

char *str1 = "Abcde";

Строковый литерал "Abcde" соответствует объекту анонимного массива типа char[6] (5 для длины строкиплюс 1 для завершающего '\0' нулевого символа). Таким образом, sizeof "Abcde" == 6.

Но str1 не является указателем на этот объект массива;это просто указатель на его начальный элемент, который содержит символ 'A'. Если мы хотим получить доступ к другим элементам массива (символам 'b', 'c' и т. Д.), Нам нужно выполнить арифметику указателей , чтобы продвигать указатель через элементы объекта массива.

Итак, изначально *str1 == 'A' - но после ++str1, `* str1 == 'b'.

Если вы хотите напечатать значение строки, вы можете сделать:

printf("%s\n", str1);

и функция printf внутренне выполнят арифметику указателя, необходимую для продвижения по символам строки.

И именно поэтому sizeof (*str) == 1. Он указывает только на один элемент объекта массива. Мы можем использовать его для доступа к другим элементам, но само значение указателя не несет никакой информации о том, насколько велик массив. (Для этого и используется терминатор '\0', поэтому мы можем распознать конец строки, не зная заранее, насколько он большой.)

Обратите внимание, что у вас может указатель нацелый объект массива:

char (*array_ptr)[6] = &"Abcde";

и sizeof *array_ptr == 6 - но это не так полезно, как вы могли ожидать. array_ptr может указывать только на массив из ровно 6 элементов, а поскольку такие функции, как printf и strlen требуют указателей char*, вы не можете напрямую манипулировать массивом с помощью array_ptr. (Указатели на объекты массива действительно появляются, когда вы имеете дело с многомерными массивами - массивами массивов.)

Указатели на элементы массива, в отличие от целых объектов массива, гораздо более гибкие, и стандартная библиотекаиспользует их широко. Недостатком является то, что вы должны сами следить за размером массива, например, передавая его в качестве дополнительного аргумента или используя значение Sentinel, например, '\0', чтобы отметить конец массива.

1 голос
/ 08 ноября 2019

Поскольку *str1 - это char.

А char - это байт.

И размер байта равен единице.

0 голосов
/ 08 ноября 2019

Существует две синтаксические формы sizeof:

  • sizeof (TYPE), где TYPE - это тип (например, int, char и т. Д.)
  • sizeof expr, где expr - любое выражение (например, 1 или *ptr и т. Д.)

Обратите внимание на отсутствие () во второй форме! В любом случае TYPE или expr не будут оцениваться (как гласит стандарт: only for its size)

Примечание: существует третья (скрытая) форма:

  • sizeof object;где объект - некоторый идентификатор

В случае:

char buff[123];
size_t sz = sizeof buff;

, sz будет 123, поэтому buff не будет повышен / понижен доуказатель.

Примечание: оператор sizeof имеет очень сильный приоритет (проверьте таблицу!), поэтому после

sz = sizeof 1+2;

sz будет равен sizeof(int) + 2

В вашем случае, *str будет символом со значением 'A': его размер будет один: размер символа.

Вот и все.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...