在 C 中取消引用本地数组



根据我对 C 的理解,您可以将指针变量和数组变量视为等效的,因为它们最终都是指针(一个指向本地函数堆栈,另一个指向内存中的任何随机点(。

我通常将指针传递给指针(例如char ** pvar(当我需要返回指针时,所以我可以看到将其传递回取消引用的局部数组是没有意义的,因为您无法更改变量的位置。

我的期望是,如果我尝试这样做,编译器会让我这样做,然后在我尝试设置返回指针值时出现段错误或崩溃。

但是,当尝试取消引用数组类型(&array(时,编译器会生成有关使用不兼容类型的警告,然后将指针传递给数组,从接收函数的角度来看,基本上失去了一个间接级别。

#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
void ptrptr(uint32_t** dptr)
{
printf("%x, %xn",  dptr, *dptr);
}
void oneptr(uint32_t* ptr)
{
printf("%08x, %xt",  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**( 的指针?

那么问题是,当我尝试取消引用数组时,为什么C静默地传递指针(uint32_t*(而不是指向指针(uint32_t**(的指针?

  • 其实不然。

  • C 正在传递指向一个uint32_t数组的指针 (uint32_t(*)[1](。

  • 它是一个指向一个uint32_t数组的指针,因为它是一个uint32_t数组,并且你得到了一个指向它的指针。

  • 它不是沉默的。您会收到一个编译器警告,指出"嘿,这是错误的指针类型!你以为这是什么?

    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)
    
  • 您不会取消引用数组。您正在创建一个指向数组的指针,将其转换为错误的指针类型,并取消引用该数组。

  • 之所以给你数字 1,是因为指向数组的指针
  • 实际上指向与指向数组中第一件事的指针相同的地址。虽然,它是一种不同类型的指针,这意味着像++这样的东西的工作方式不同,但随后你将其转换为相同类型的指针,这样你的代码就不会注意到。

那么问题是,当我尝试取消引用数组时,为什么 C 静默地传递指针 (uint32_t*( 而不是指向指针 (uint32_t**( 的指针?

它不是沉默的,它给了你一个警告。C 标准没有提到术语"错误"和"警告",但谈到了诊断消息。要遵循 C 标准,编译器向程序员显示诊断消息就足够了。

如果你想要一个错误而不是警告 ccc 或 clang 违反 C 标准,你必须使用-std=c11 -pedantic-errors进行编译。

至于为什么代码不正确,&array以数组指针的形式给出了数组的地址,uint32_t(*)[1]。此类型与uint32_t**不兼容。如果未指定未指定包含 C 标准约束冲突但仍运行程序会发生什么:这是未定义的行为。不能保证SEG故障或崩溃,这些只是未定义行为的许多潜在结果中的两个。

相关内容

  • 没有找到相关文章

最新更新