数组从指针索引

0 c++ pointers multidimensional-array

考虑以下代码:

static char a[2][2] = {
    { 1, 2 },
    { 3, 4 },
};

int main()
{
    char **p = (char**)a; // needs cast, or compiler complains (which makes sense)

    printf("%p\n", p);

    printf("%p\n", &a[1][0]);
    printf("%d\n",  a[1][0]);
    printf("%p\n", &p[1][0]); // why null?  why doesn't compiler complain about this?
    printf("%d\n",  p[1][0]); // segfault, of course

    return 0;
}
Run Code Online (Sandbox Code Playgroud)

产生这个输出:

0x804a018
0x804a01a
3
(nil)
Segmentation fault
Run Code Online (Sandbox Code Playgroud)

我知道数组可以衰减到指针.我不明白为什么编译器(g ++)会让我尝试反过来.如果p是char**,为什么它让我使用p [x] [x]而不是警告?它显然甚至没有接近工作,因为结果指针为空.

顺便说一下,我问这个来自第三方的代码,显然对他们有效.(在Windows中编译,而不是使用g ++编译).所以,我不是在寻找有关如何修复此代码的建议,我已经知道如何做到这一点.我只是想了解编译器为什么不抱怨,以及为什么结果是空指针.

谢谢.

Jos*_*eld 6

你根本无法开始治疗的二维数组charchar**.在内存中,数组看起来像这样:

| 1 | 2 | 3 | 4 |
Run Code Online (Sandbox Code Playgroud)

每个元素都遵循前一个元素.数组名称将隐式转换为指向其第一个元素的指针:

| 1 | 2 | 3 | 4 |
  ^
  |
Run Code Online (Sandbox Code Playgroud)

现在,如果你将这个指针转换为a char**,你会说"如果你取消引用这个指针,你会发现char*"这是一个彻头彻尾的谎言.如果你取消引用指针,你将获得一个char有值1,而不是一个指针.

然后,当你这样做时p[1][0],你正在处理值p[1](基本上将pointe p一直移动sizeof(char*))作为指针并试图取消引用它.当然,这会引导您直接进入未定义的行为.

编译器没有让你做那个演员,因为这是一个愚蠢的演员.不要这样做.仅仅因为C风格的演员阵容允许你这样做,这并不意味着它是一个好的操作.reinterpret_cast如果没有其他演员工作,C风格的演员阵容将回归到,在这种情况下,你几乎肯定会遇到未定义的行为.