如果指针存储的是变量的地址,并且本身就是一个变量,那不是会创建无限的指针并填满整个系统内存吗?

问题描述 投票:0回答:5

这里还有一个关于指针的问题:

打印某些内容或不影响存储在特定地址的值有何影响?

l-k 的值等于 1,这就是为什么我要检查存储在 k+1 处的值是否等于 88。

#include <iostream>
int main()
{
    int i=55;
    int j=88;
    int *k=&i;
    int *l=&j;
    k++;
//  printf("%p\n",l-k); 
/*  Why does uncommenting previous line changes the output from 0 to 88?  */
    printf("%i",*k);
    return 0;
}
c pointers
5个回答
4
投票

同时

k++;

是允许的(您可以设置一个指针,使其超过标量的地址 并且 读取该指针值),k 的后续

取消引用
的行为是 未定义。有点矛盾的是,这意味着整个程序的行为是未定义的。

l-k
的行为也将是未定义的。指针算术(包括两个指针之间的差异)仅在数组内定义。为此,可以将对象视为单个元素数组。


1
投票

关于标题中的问题:

如果指针存储的是变量的地址,并且本身就是一个变量,那么它不是会创建无限的指针并填满整个系统内存吗?

不。我添加了一些代码来转储每个

i
j
k
l
的地址和内容,结果如下:

       Item         Address   00   01   02   03
       ----         -------   --   --   --   --
          i  0x7ffee31d3a48   37   00   00   00    7...

          j  0x7ffee31d3a44   58   00   00   00    X...

          k  0x7ffee31d3a38   48   3a   1d   e3    H:..
             0x7ffee31d3a3c   fe   7f   00   00    ....

          l  0x7ffee31d3a30   44   3a   1d   e3    D:..
             0x7ffee31d3a34   fe   7f   00   00    ....

希望输出是不言自明的 - 每行显示项目的名称、地址和内容(均以十六进制形式和字节序列形式)。

我使用的是小端系统,因此必须从下到上、从右到左读取多字节对象。

无论如何,

i
位于地址
0x7ffee31d3a48
并存储值
55
0x37
)。
k
位于地址
0x7ffee31d3a38
并存储值
0x7ffee31d3a48
,即
i
的地址。

地址不存在无限回归。

k
只是另一个变量 - 它和
i
之间的唯一区别是它存储不同类型的值。

至于你的另一个问题:

为什么取消注释上一行会将输出从 0 更改为 88?

表达式

k++
改变了
k
所指向的内容 - 它不再指向
i
。 这是该表达式之后程序的状态:

       Item         Address   00   01   02   03
       ----         -------   --   --   --   --
          i  0x7ffee31d3a48   37   00   00   00    7...

          j  0x7ffee31d3a44   58   00   00   00    X...

          k  0x7ffee31d3a38   4c   3a   1d   e3    L:..
             0x7ffee31d3a3c   fe   7f   00   00    ....

          l  0x7ffee31d3a30   44   3a   1d   e3    D:..
             0x7ffee31d3a34   fe   7f   00   00    ....

不再存储

i
(
0x7ffee31d3a48
) 的地址,
k
现在存储地址
0x7ffeee31d3a4c
,它……不是程序中任何对象的地址。 此时,尝试取消引用
k
会调用未定义的行为 - 您的代码可能会崩溃,或者您可能会得到意外的输出,或者通过一些奇迹您可能会得到您期望的结果。 删除
printf
语句会更改程序在内存中的布局,这将影响
k
表达式后面的
k++
所指向的内容。


1
投票

实际上,这是未定义的行为。这里:

k++;

增加指针,使其指向不同的内存位置,并将其前进

int
的大小。如果
i
是多个整数的数组,它将指向行中的下一个。但事实并非如此,因此稍后在打印中从该指针读取是未定义的行为,并且它可能从未指定的位置读取。

当我在 MSVC 中尝试这个程序时,它不会打印

0
88
,它每次都会打印
-858993460
。不同的编译器可能会打印出完全不同的东西,一些改变的东西,或者只是让程序崩溃,甚至做一些与所有这些不同的事情。


0
投票

如果取消注释一行会影响输出,则您的代码可能具有未定义的行为。通过实际阅读代码可以清楚地看出这一点,尤其是这两行。

这条线没问题。

int *k=&i;

但是你希望这条线做什么?

k++;

i
是单个
int
,因此将
k
指向
int
没有任何意义或用途,因为您可以访问内存的任何部分,这一点可以从有时得到 0 或有时得到 88 的事实中看出。 .


0
投票

如有疑问,

如果指针存储的是变量的地址,并且本身就是一个变量,那么它不是会创建无限的指针并填满整个系统内存吗?

不,原因如下。您知道每个变量都存储在程序中的特定地址上(对于不同的编译/用户,它可能会有所不同)。现在,该地址正是变量所在的位置。但是,声明时的指针 - 将收集该地址并将其分配给另一个变量。 例如: 代码1:

int a = 5; 

假设“a”存储在地址 xyz123 处。现在,该地址尚未作为信息存储。 但是,在本守则中:

int a = 5;
int* b = &a;

这会将“a”的地址存储在名为“b”的变量中。其中,b 再次具有尚未作为信息存储在存储器中的地址。 希望有帮助!!!

最新问题
© www.soinside.com 2019 - 2025. All rights reserved.