Насколько я понимаю, вы можете рассматривать переменную-указатель и переменную-массив как эквивалентные, поскольку в конечном итоге они оба являются указателями (один для локального стека функций, другой для любой случайной точки в памяти).
Обычно я передаю указатель на указатель (например, char ** pvar
), когда мне нужно вернуть указатель, поэтому я вижу, как бессмысленно передавать его обратно в локальный массив с разыменованными ссылками, поскольку вы не можете изменитьПоложение переменной.
Я ожидал бы, что если я попробую это сделать, компилятор разрешит мне это сделать, а затем при попытке установить значение возвращаемого указателя произойдет сбой или сбой.
Однако при попытке разыменования типа массива (и массива) компилятор предупреждает об использовании несовместимых типов, а затем передает указатель на массив, фактически теряя один уровень косвенности с точки зрения принимающей функции.
#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
void ptrptr(uint32_t** dptr)
{
printf("%x, %x\n", dptr, *dptr);
}
void oneptr(uint32_t* ptr)
{
printf("%08x, %x\t", ptr, *ptr);
ptrptr(&ptr);
}
int main()
{
uint32_t array[] = {1};
uint32_t *ptr = calloc(1, sizeof( uint32_t));
ptr[0] = 3;
oneptr(ptr); /* OK, passes an (uint32_t *) */
oneptr(array); /* OK, passes an (uint32_t *) */
ptrptr(&ptr); /* OK, passes an (uint32_t **) */
ptrptr(&array); /* ??, passes an (uint32_t *) */
return 0;
}
При его компиляции выдается предупреждение
cc test.c -o test
test.c: In function ‘main’:
test.c:24:9: warning: passing argument 1 of ‘ptrptr’ from incompatible pointer type [-Wincompatible-pointer-types]
ptrptr(&array);
^
test.c:5:6: note: expected ‘uint32_t ** {aka unsigned int **}’ but argument is of type ‘uint32_t (*)[1] {aka unsigned int (*)[1]}’
void ptrptr(uint32_t** dptr)
^~~~~~
0061a008, 3 7ebfa144, 61a008
7ebfa154, 1 7ebfa144, 7ebfa154
7ebfa150, 61a008
7ebfa154, 1
При использовании я получаю тот же результатgcc, clang и cl для его компиляции, так что я вполне уверен, что это не ошибка компилятора.Тогда возникает вопрос: почему C молча передает указатель (uint32_t*
) вместо указателя на указатель (uint32_t**
), когда я пытаюсь разыменовать массив?