关于"运营商地址"的问题(&)和c和c ++中的数组

时间:2015-12-30 20:30:33

标签: c++ c arrays pointers

我在使用c编译时发现了一个区别,而我在c ++中编译时我并不完全理解......假设我声明了一个大小为5的字符数组:

char my_array[5];

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

char* a = my_array;

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

char* b = &my_array; // compiler error in c++, not in c
char** c = &my_array; // compiler error in c++, not in 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%X\n", a);
    printf("0x%X\n", b);
    printf("0x%X\n", c);
    printf("0x%X\n", d);
    printf("0x%X\n", e);
    printf("\n");

    while(1);

    return 1;
}

2 个答案:

答案 0 :(得分:4)

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

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

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

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

答案 1 :(得分:1)

定义数组时,会在内存中为其元素分配空间。整个空间(在您的情况下为5个字节)分配给数组。因此,为数组元素以及数组本身分配空间。

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

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