Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/63.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
在C语言中取消对局部数组的引用_C_Arrays_Pointers_Language Lawyer_Dereference - Fatal编程技术网

在C语言中取消对局部数组的引用

在C语言中取消对局部数组的引用,c,arrays,pointers,language-lawyer,dereference,C,Arrays,Pointers,Language Lawyer,Dereference,根据我对C的理解,可以将指针变量和数组变量视为等价的,因为它们最终都是指针(一个指向本地函数堆栈,另一个指向内存中的任意点) 当我需要返回指针时,我通常会将指针传递给指针(例如,char**pvar),因此我可以看出将其传递回未引用的局部数组没有什么意义,因为您无法更改变量的位置 我的期望是,如果我尝试这样做,编译器会让我这样做,然后在我尝试设置返回指针值时发生segfault或崩溃 但是,当尝试取消引用数组类型(&array)时,编译器会生成一个关于使用不兼容类型的警告,然后将指针传递到数组,

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

当我需要返回指针时,我通常会将指针传递给指针(例如,
char**pvar
),因此我可以看出将其传递回未引用的局部数组没有什么意义,因为您无法更改变量的位置

我的期望是,如果我尝试这样做,编译器会让我这样做,然后在我尝试设置返回指针值时发生segfault或崩溃

但是,当尝试取消引用数组类型(&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;
}
当我使用gcc、clang和cl来编译它时,我得到了相同的结果,所以我非常确信这不是一个编译器错误。接下来的问题是,当我尝试取消对数组的引用时,为什么C会默默地传递指针(
uint32\u t*
),而不是指向指针(
uint32\u t**
)的指针

接下来的问题是,当我尝试取消对数组的引用时,为什么C会默默地传递指针(
uint32\u t*
),而不是指向指针(
uint32\u 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\u t*
),而不是指向指针(
uint32\u 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\u t*)而不是指向指针(uint32\u t**)的指针

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

如果您希望在使用gcc或clang违反C标准时出现错误而不是警告,则必须使用
-std=c11-pedantic errors
进行编译

至于代码不正确的原因,
&array
以数组指针的形式给出数组的地址,
uint32\u t(*)[1]
。此类型与
uint32\u t**
不兼容。如果在程序包含C标准约束冲突的情况下运行该程序,将发生什么?没有指定:这是未定义的行为。无法保证seg故障或崩溃,这只是未定义行为的许多潜在结果中的两个

接下来的问题是,当我尝试取消对数组的引用时,为什么C会无声地传递指针(uint32\u t*)而不是指向指针(uint32\u t**)的指针

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

如果您希望在使用gcc或clang违反C标准时出现错误而不是警告,则必须使用
-std=c11-pedantic errors
进行编译


至于代码不正确的原因,
&array
以数组指针的形式给出数组的地址,
uint32\u t(*)[1]
。此类型与
uint32\u t**
不兼容。如果在程序包含C标准约束冲突的情况下运行该程序,将发生什么?没有指定:这是未定义的行为。无法保证seg故障或崩溃,这只是未定义行为的许多潜在结果中的两个。

数组名称在许多(虽然不是全部)上下文中衰减为指针,但它与指针不同。您发现了一种不同的情况:
&array
的类型是指向数组的指针,而不是指向指针的指针。另一个是,通常,
sizeof(ptr)!=sizeof(array)
。我很清楚这个警告:在最后一个例子中传递给
ptrptr
的不是,正如您似乎相信的那样,一个
uint32\u t*
,而是一个<