首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >C中的解引用局部数组

C中的解引用局部数组
EN

Stack Overflow用户
提问于 2018-09-26 03:49:24
回答 2查看 599关注 0票数 0

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

通常,当需要返回指针时,我会将指针传递给指针(例如char ** pvar),因此我可以看到将指针传递回取消引用的本地数组是多么没有意义,因为您不能更改变量的位置。

我的期望是,如果我尝试这样做,编译器将允许我这样做,然后分段错误或崩溃,当我试图设置返回的指针值。

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

代码语言:javascript
复制
#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;
}

编译它给了我警告

代码语言:javascript
复制
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**)的指针?

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2018-09-26 04:21:16

那么,当我试图取消数组引用时,为什么C会悄悄地传递指针(uint32_t*)而不是指向指针(uint32_t**)的指针?

  • 事实并非如此。
  • C是传递一个指向一个uint32_t (uint32_t(*)[1])数组的指针。
  • 它是一个指向一个uint32_t的数组的指针,因为它是一个uint32_t的数组,并且有一个指向它的指针。
  • 它不是无声的。您会收到编译器的警告:“嘿,这是错误类型的指针!”你觉得这是什么? 测试:c:在函数‘main’:test.c:24:9:警告:从不兼容的指针类型传递‘ptrptr’的参数1- int兼容-指针-类型ptrptr(&test.c:5:6);^ test.c:5:6:注意:预期的‘uint32_t ** {又名无符号int **}’,但参数的类型是‘uint32_t (*)1 {aka unsigned int(*)1}’void ptrptr(uint32_t** dptr)。
  • 您没有取消数组的引用。您正在创建指向数组的指针,将其转换为错误的指针类型,并取消引用。
  • 这给出数字1的原因是,指向数组的指针实际上指向与指向数组中第一件事情的指针相同的地址。但是,它是一种不同类型的指针,这意味着像++这样的东西的工作方式不同,但是您将它转换成相同类型的指针,这样代码就不会注意到。
票数 3
EN

Stack Overflow用户

发布于 2018-09-26 06:38:16

那么,当我试图取消数组引用时,为什么C会悄悄地传递指针( uint32_t*)而不是指向指针(uint32_t**)的指针?

它没有沉默,它给了你一个警告。C标准没有提到“错误”和“警告”,而是提到诊断信息。要遵循C标准,编译器向程序员显示诊断消息就足够了。

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

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

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/52509651

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档