Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/spring-boot/5.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_Reference - Fatal编程技术网

C 指向一个引用加上一个数组的指针

C 指向一个引用加上一个数组的指针,c,arrays,pointers,reference,C,Arrays,Pointers,Reference,我刚读到一些关于指针的问题。代码如下: int a[5]={1, 2, 3, 4, 5}; int *p = (int*)(&a + 1);//second line cout<<(*p)<<endl; inta[5]={1,2,3,4,5}; int*p=(int*)(&a+1)//第二线 cout&a是数组的地址 &a+1也是一个地址,但这1是什么?它是指向a的大小的指针。这就像写int*p=&a[5],然后将其强制转换为int* 现在为什么是0?因为a[5

我刚读到一些关于指针的问题。代码如下:

int a[5]={1, 2, 3, 4, 5};
int *p = (int*)(&a + 1);//second line
cout<<(*p)<<endl;
inta[5]={1,2,3,4,5};
int*p=(int*)(&a+1)//第二线

cout
&a
是数组的地址

&a+1
也是一个地址,但这1是什么?它是指向
a
大小的指针。这就像写
int*p=&a[5],然后将其强制转换为
int*

现在为什么是0?因为
a[5]
恰好是
0
——请注意,它超出了范围,可能是任何其他行为(未定义的行为)


请注意,数组是基于零的,这意味着索引来自
0
。因此实际上
a[4]
最后一个元素,
a[5]
是不允许的。

运算符
&
用于获取变量的地址。因此,
&a
属于指向5个整数数组的指针类型:
int(*)[5]

指针算术意味着当您有一个指针
p
时,
p+1
将指向下一个元素,即
sizeof(*p)
字节。这意味着
&a+1
指向
5*sizeof(int)
块,即数组中最后一个元素后面的块

&a+1
转换为
int*
意味着现在您希望将此新指针解释为指向
int
的指针,而不是指向5个int数组的指针。你是说,从现在开始,这个指针引用的是
sizeof(int)
字节长的内容,所以如果你增加它,它将向前移动
sizeof(int)
单位


因此,
*p
正在访问
a[5]
,这是一个越界位置(超出最后一个),因此程序具有未定义的行为。它打印了0,但可能崩溃或打印了其他内容。当发生未定义的行为时,任何事情都可能发生。

这就是您的声明的意思:

                           p
                           |
                           v
a[0] a[1] a[2] a[3] a[4] | a[5]
---------(Length)------->
但你想得到这个(我想):

您需要从声明语句中删除第二组括号才能获得
a[1]

int * p = (int *)(&a + 1);
// change to this:
int * p = (int *) &a + 1;
获取错误值的原因与
sizeof
运算符和指针算法有关。在解释错误之前,让我先解释一下


Sizeof运算符
sizeof
运算符计算数据类型的大小(以字节为单位)。直接例子:

sizeof (char)  // always returns 1
sizeof (int)   // usually returns 4 or 8
sizeof (int *) // usually returns 4 or 8
请注意这个有趣的例子:

int a[5];
sizeof (a) // returns sizeof (int) * 5

运算符优先级 运算符优先级是一系列运算符的求值顺序。括号中的任何内容都将首先计算。计算括号后,由运算符优先级决定表达式的求解顺序

以下是相关运算符及其在优先级表中的顺序:

Operator    Description    Associativity

()          Parenthesis    Left-to-right
(cast)      Cast           Right-to-left
&           Address of     Right-to-left
+, -        Plus, Minus    Right-to-left

指针算法 指针算法主要是关于加、减、乘指针和整数(或其他指针)。你需要知道的是(在这个问题的范围内):

即使它说的是
+1
,它实际上是在向指针添加
sizeof(int)
。 这是C标准编写者的设计选择,因为它更为常见 程序员希望将
sizeof(int)
添加到指针(这会将他们带到数组中的下一个整数),而不是添加
1
(这会将指针带到数组中的第一个和第二个元素之间)

更一般地说:

datatype p;
p = p + 1;
// actually means
p = p + sizeof (datatype);
下面是一个相关的例子:

int a[5];
a = a + 1;
// actually means
a = a + sizeof (a);
// remember that sizeof (a) is going to be sizeof (int) * 5?

声明 回到你的声明:

int * p = (int *)(&a + 1);
您可能已经看到了它的问题所在:
a+1
实际上意味着
a+sizeof(a)
,这使您超出了数组的范围。这可能是
0
(通常是),也可能是其他一些随机值

您可能没有注意到的是:

int * p = (int *) &a + 1;
实际上给出了数组中的第二个元素。这与运算符优先级有关。如果您查看我放在链接中的运算符优先级表,则强制转换的优先级高于
&
+
运算符。因此,如果在对表达式的其余部分求值之前,将
a
转换为
(int*)
,而不是
a[5]
,则它将等效于:

int * a;
a = a + 1; /* and this would
    give you the second element
    in the array */
简单地说,如果要访问数组中的第二个元素,请更改:

int * p = (int *)(&a + 1);
// to this:
int * p = (int *) &a + 1;
什么是
*p
?: 在代码中,
*p
是指向类型为
int
的未知元素的指针

让我们来解释一下:

&a
是有效的指针表达式。可以将整数添加到指针表达式中

&a
的结果:指向整个数组
a[5]
。它的类型是
int(*)[5]

sizeof*(&a)
的结果是
5
,即数组的大小

&a+1
的结果是指针表达式,它保存当前指向的
&a
之外的第一个
int
的地址

因此,
1
对象经过
&a
就是
*p
指向的对象。因此,它是
int
类型的未知元素。因此,访问
未知元素
是未定义的行为。这也回答了为什么输出为零。


旁注:

如果您确实想访问数组中的第二个元素,那么应该将
1
添加到指向数组第一个元素的指针
a
指向数组中的第一个元素,大小为
sizeof(int*)

a+1的结果是数组中第二个元素的地址


*(a+1)
的结果是数组中第二个元素的值<代码>2

+1为什么
a[5]=0
是因为
a[4]=5
a[5]
是不允许的。。。在数组长度之外,它恰好发生在
int * a;
a = a + 1; /* and this would
    give you the second element
    in the array */
int * p = (int *)(&a + 1);
// to this:
int * p = (int *) &a + 1;
int *p = (int*)(&a+1);