c - C中的取消引用本地数组
问题描述
根据我对 C 的理解,您可以将指针变量和数组变量视为等效的,因为它们最终都是指针(一个指向本地函数堆栈,另一个指向内存中的任何随机点)。
当我需要返回一个指针时,我通常将一个指针传递给一个指针(例如char ** pvar
),所以我可以看到将它传递回一个取消引用的本地数组是多么没有意义,因为你不能改变一个变量的位置。
我的期望是,如果我尝试这样做,编译器会让我这样做,然后当我尝试设置返回的指针值时会出现段错误或崩溃。
然而,当试图取消引用一个数组类型(&array)时,编译器会生成一个关于使用不兼容类型的警告,然后它将指针传递给数组,从接收函数的角度来看,实际上失去了一层间接性。
#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**
解决方案
那么问题是,当我尝试取消引用数组时,为什么 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++ - C++ 覆盖句柄的内容
- css - CSS:高级行布局,一列具有相对最大宽度
- javascript - 遍历 JSX 中的对象属性
- python - 如何从输入的工资中减去固定费率的医疗保健费用?
- android - 当多个 PageViews 附加到同一个 PageController.Failed 断言时,无法读取页面属性:第 184 行 pos 7:
- java - 试图用 Java 中的对象为 ArrayList 创建一个私有字段
- device - 为什么它在 Hyper-V 要求下显示“检测到管理程序”,即使在删除 Hyper-V 功能之后也是如此
- java - 无法使用 mysql 在 maven eclipse 中使用休眠创建表
- c - 动态初始化大型数组时的 Segfault 11
- flutter - Dart 包版本如何工作以及我应该如何对我的 Flutter 插件进行版本控制?