有关 C 和 C++ 中的"Address-of operator" (&) 和数组的问题

Questions about "Address-of operator" (&) and arrays in c and c++

本文关键字:问题 数组 Address-of C++ 中的 有关 operator      更新时间:2023-10-16

我发现用c编译时与用c++编译时有一个我不完全理解的区别。。。假设我声明一个大小为5:的字符数组

char my_array[5];

根据我的理解,"my_array"实际上是一个字符指针,它允许我这样做:

char* a = my_array;

现在,我明白了,当我声明我的数组时,我只分配了5个字节(其中每个值一个),这意味着"&my_array"不应该存在,因为没有为指向my_arrays的指针分配内存。为了证明这一点,我这样做了:

char* b = &my_array; // compiler error in c++, not in c
char** c = &my_array; // compiler error in c++, not in c

我不明白其中的区别,为什么c会允许这样做?尽管如此,假设我想将我的char[5]转换为char*,而不使用a的方法,我发现我也可以这样做:

char* c = (char*)&my_array; // works both in c and c++

我真的不明白。我还没有确定"&my_array"不存在吗?更令人担忧的是,这两行返回的值完全相同:

// a and c have the same value (both in c and c++)
char* a = my_array;
char* c = (char*)&my_array;

接下来,假设我想在运行时执行这5个字节,所以我声明了一个新类型:

// pFunc is a pointer to function returning void
typedef void (*pFunc)();

然后我尝试声明一个指向函数的指针,该函数将执行我的字节数组:

pFunc pFunc1 = (pFunc)&my_array; // works, but I don't really understand why
pFunc pFunc2 = (pFunc)my_array;  // compiler error in c++, not in c

突然间,不仅是&my_array编译没有问题,但这也是在c++(据我所知)中实现这一功能的唯一方法。有人介意向我解释一下发生了什么事吗?这是完整的代码:

#include <stdio.h>
typedef void (*pFunc)();
int main()
{
    char my_array[5];
    char* a = my_array;
    char* b = &my_array; // compiler error in c++, not in c
    char* c = (char*)&my_array;
    char** d = &my_array; // compiler error in c++, not in c
    char** e = (char**)&my_array;
    pFunc pFunc1 = (pFunc)&my_array; // works, but I don't really understand why
    pFunc pFunc2 = (pFunc)my_array;  // compiler error in c++, not in c
    printf("char*:n");
    printf("0x%Xn", a);
    printf("0x%Xn", b);
    printf("0x%Xn", c);
    printf("0x%Xn", d);
    printf("0x%Xn", e);
    printf("n");
    while(1);
    return 1;
}

C++中的数组不是指针。当使用数组名称初始化适当类型的指针时(例如,当数组传递给适当指针类型的函数参数时),它将衰减为指针,但它本身不是指针。

当您声明char my_array[5]时,您正在创建一个由5个chars组成的数组;没有创建指针,但是存在char[5]并且可以由其他指针指向。

如果执行char* a = my_array;my_array将衰减为指针;创建指向CCD_ 7的第一元素的新CCD_
char* b = &my_array;失败是因为my_array不是char,因此&my_array不是char*char** d = &my_array;失败,因为my_array不是char*,因此&my_array不是char**&my_arraychar (*)[5](指向5个chars的数组的指针)。这些"工作"在C中,因为C只要求编译器对不相关的指针类型之间的隐式转换发出警告,但C++根本不允许这些隐式转换;它们会导致编译错误。您需要在C++中进行显式强制转换,但即使这样,如果取消引用结果指针,行为也是未定义的。

最后,pFunc pFunc1 = (pFunc)&my_array;在类似地表示函数指针和对象指针的平台上"工作"(大多数现代系统),但并不要求它在所有平台上都工作。同样,使用结果指针将调用未定义的行为
pFunc pFunc2 = (pFunc)my_array;实际上也使用GCC进行编译,但未能在MSVC下进行编译。实际上,我不确定哪个编译器的行为是正确的,但无论哪种方式,结果都不太可能有用。

定义数组时,会为其元素在内存中分配空间。整个空间,在您的例子中是5字节,被分配给数组。因此,空间被分配给数组元素以及数组本身。

应该注意的是,数组不是指针,反之亦然。my_array是一个数组,而不是指针。在大多数情况下,数组转换为指向其第一个元素的指针,但这并不意味着数组就是指针。

数组my_array的地址类型为char (*)[5],是指向5个char s的数组的指针。它与类型char **pFunct不兼容。指定不兼容的指针类型会导致错误。