Идентификатор массива уменьшается до указателя на первый элемент массива, в большинстве случаев.Но когда массив является операндом оператора sizeof
, это преобразование не происходит, и оператор выдает размер массива в байтах. Из §6.3.2.1 ¶3 проекта стандарта C11 :
За исключением случаев, когда это операнд оператора sizeof , _Alignof оператор, или унарный оператор & , или строковый литерал, используемый для инициализации массива, выражение с типом '' массив типа '' преобразуется в выражение с указателем типа ''набрать '', который указывает на начальный элемент объекта массива и не является lvalue.
Обратите внимание, что в стандарте C18 оператор _Alignof
был удален из этого отрывка (обсуждение здесь ).
Итак, sizeof(v)
возвращает размер массива v[]
в байтах, который составляет 12 байтов.То есть тип операнда равен int [3]
, поскольку массив не был преобразован в указатель на int
(как это было бы в большинстве выражений), а оператор sizeof
выдаетразмер этого типа (массив 3 int
с) в байтах.
Но с sizeof (v + 0)
тип выражения v + 0
определяет результат, полученный с помощью sizeof
оператор.В выражении v + 0
массив v[]
распадается на указатель на первый элемент v[]
, а затем добавляется 0
в соответствии с правилами арифметики указателей.Результатом является указатель на int
(поскольку &v[0]
сам по себе является указателем на int
), поэтому тип выражения v + 0
равен int *
.Таким образом, оператор sizeof
в этом случае возвращает размер указателя int
.То же самое относится и к аналогичным выражениям sizeof (v + 1)
и т. Д.
Кроме того, обратите внимание, что вы должны печатать адреса с указателем преобразования %p
после первого приведения к void *
, чтобы избежать неопределенного поведения:
printf("%p\n", (void *)v);
printf("%p\n", (void *)(v + 0));