use*_*534 2 c arrays pointers reference
我刚读了一些关于指针的问题.这是代码:
int a[5]={1, 2, 3, 4, 5};
int *p = (int*)(&a + 1);//second line
cout<<(*p)<<endl;
Run Code Online (Sandbox Code Playgroud)
我的编译器输出是0.什么是*p?它是指向数组的指针a吗?什么&a+1意思?
&a 是数组的地址.
&a + 1也是一个地址,但这是什么1?它是指向sizeof a字节的指针a.所以这就像写作一样int *p = &a[5];,然后你就把它投射到了int *.
现在为什么0?因为a[5]碰巧是0- 注意它超出界限,可能是其他任何东西(未定义的行为).
请注意,数组是从零开始的,这意味着索引来自0.所以实际上a[4]是最后一个元素,a[5]是出界的.
这是您的声明声明的含义:
p
|
v
a[0] a[1] a[2] a[3] a[4] | a[5]
---------(Length)------->
Run Code Online (Sandbox Code Playgroud)
但是你想要得到这个(我假设):
p
|
v
a[0] a[1] a[2] a[3] a[4] |
---------(Length)------->
Run Code Online (Sandbox Code Playgroud)
您需要从声明语句中删除第二组括号,以获得a[1]:
int * p = (int *)(&a + 1);
// change to this:
int * p = (int *) &a + 1;
Run Code Online (Sandbox Code Playgroud)
获得错误值的原因与sizeof运算符,运算符优先级和指针算法有关.在解释错误之前,让我解释一下.
的sizeof运算符计算一个数据类型的大小(以字节计).立即示例:
sizeof (char) // always returns 1
sizeof (int) // usually returns 4 or 8
sizeof (int *) // usually returns 4 or 8
Run Code Online (Sandbox Code Playgroud)
请注意这个有趣的例子:
int a[5];
sizeof (a) // returns sizeof (int) * 5
Run Code Online (Sandbox Code Playgroud)
运算符优先级是评估一系列运算符的顺序.括号中的任何内容都将首先进行评估.在计算括号之后,由运算符优先级决定表达式将被解决的顺序.
这是相关的运算符,它们在优先级表中排序:
Operator Description Associativity
() Parenthesis Left-to-right
(cast) Cast Right-to-left
& Address of Right-to-left
+, - Plus, Minus Right-to-left
Run Code Online (Sandbox Code Playgroud)
指针算法主要是关于用整数(或其他指针)添加,减去和乘以指针.你需要知道的(对于这个问题的范围)是这样的:
int * p;
p = p + 1;
Run Code Online (Sandbox Code Playgroud)
即使它说 + 1,它实际上是添加sizeof (int)到指针.这是一个设计选择C标准的作家,因为它是很多更常见的程序员要添加sizeof (int)指针(这使他们的下一个整数数组)比增加1(这使在第一之间的指针和数组中的第二个元素).
更一般地说:
datatype p;
p = p + 1;
// actually means
p = p + sizeof (datatype);
Run Code Online (Sandbox Code Playgroud)
这是一个相关的例子:
int a[5];
a = a + 1;
// actually means
a = a + sizeof (a);
// remember that sizeof (a) is going to be sizeof (int) * 5?
Run Code Online (Sandbox Code Playgroud)
回到你的声明声明:
int * p = (int *)(&a + 1);
Run Code Online (Sandbox Code Playgroud)
你可能已经看到它有什么问题了:a + 1真的意味着a + sizeof (a),这会让你超出数组的范围.这可能是0(通常是)或者可能是其他随机值.
您可能没有注意到的是:
int * p = (int *) &a + 1;
Run Code Online (Sandbox Code Playgroud)
实际上给你数组中的第二个元素.这与运算符优先级有关.如果你看一下,我把在一个链接的运算符优先级表,铸就具有更高的优先级比&和+运营商.因此,如果在表达式的其余部分被计算之前a被转换为a (int *)而不是a[5]之前,则它变为等效于:
int * a;
a = a + 1; /* and this would
give you the second element
in the array */
Run Code Online (Sandbox Code Playgroud)
所以简单地说,如果要访问数组中的第二个元素,请更改:
int * p = (int *)(&a + 1);
// to this:
int * p = (int *) &a + 1;
Run Code Online (Sandbox Code Playgroud)
运算符&用于获取变量的地址.因此,&a是指向5个int数组的类型指针:int (*)[5].
指针运算意味着当你有一个指针p,然后p+1将指向下一个元素,即sizeof(*p)字节之外.这意味着&a+1指向5*sizeof(int)块之外,即数组中最后一个元素之后的块.
转换&a+1为int *意味着现在您希望将此新指针解释为指向指针int而不是指向5个整数的数组的指针.你是说,从现在开始,这个指针引用了一些sizeof(int)字节长的东西,所以如果你增加它,它将向前移动sizeof(int)单位.
因此,*p正在访问a[5],这是一个超出界限的位置(超出最后一个位置),因此程序具有未定义的行为.它打印0,但它可能已经崩溃或打印其他东西.发生未定义的行为时可能发生任何事情.