В чем разница между a и a + 0 в качестве указателей C? - PullRequest
0 голосов
/ 17 сентября 2018

Посмотрите на код C.

#include <stdio.h>
int main(void)
{
    int v[3] = {1, 2, 3};
    printf("%d\n", v);
    printf("%d\n", v + 0);
    printf("%zu\n", sizeof(v));
    printf("%zu\n", sizeof(v + 0));
    printf("%zu\n", sizeof(v + 1));
    printf("%zu\n", sizeof(v + 2));
    return 0;
}

Вот один из выходов:

-587904464
-587904464
12
8
8
8

Я думаю, что v - это то же самое, что и v + 0.

Оба указателя указывают на первый элемент в массиве v [3].

Следовательно, v и v + 0 имеют одинаковое значение.

Но почему они не могут содержать одинаковые байты? (sizeof (v) и sizeof (v + 0) различаются)

1 Ответ

0 голосов
/ 17 сентября 2018

Идентификатор массива уменьшается до указателя на первый элемент массива, в большинстве случаев.Но когда массив является операндом оператора 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));
...