C++ 我不知道';我不懂C++;指针算法
我有下面的程序,它定义了2个整数和一个指向整数的指针C++ 我不知道';我不懂C++;指针算法,c++,c,pointers,integer,pointer-arithmetic,C++,C,Pointers,Integer,Pointer Arithmetic,我有下面的程序,它定义了2个整数和一个指向整数的指针 #include <stdio.h> int main() { int bla=999; int a=42; int* pa=&a; printf("%d \n", *pa); printf("%d \n", pa); pa++; //*pa=666; //runs (no error), but the console is showing nothing
#include <stdio.h>
int main() {
int bla=999;
int a=42;
int* pa=&a;
printf("%d \n", *pa);
printf("%d \n", pa);
pa++;
//*pa=666; //runs (no error), but the console is showing nothing at all
printf("%d \n", *pa);
printf("%d \n", pa);
pa++;
//*pa=666; //runs and changes the value of *pa to 666;
printf("%d \n", *pa);
printf("%d \n", pa);
}
#包括
int main(){
int bla=999;
INTA=42;
int*pa=&a;
printf(“%d\n”,*pa);
printf(“%d\n”,pa);
pa++;
//*pa=666;//运行(无错误),但控制台没有显示任何内容
printf(“%d\n”,*pa);
printf(“%d\n”,pa);
pa++;
//*pa=666;//运行并将*pa的值更改为666;
printf(“%d\n”,*pa);
printf(“%d\n”,pa);
}
输出为:
42
2686740
2686744
2686744//我认为这个值很奇怪
999
2686748
地址对我来说是有意义的,但第四个值很奇怪,因为它正是int的地址。有人能解释这种行为吗
当我在中注释*pa=666(第一次出现)时,控制台没有显示任何内容,因此这里有某种错误,但编译器没有显示错误。也许这是因为我的系统中int的大小,我有一个64位的windows操作系统,所以int可能是64位而不是32位?正因为如此,*pa值在第二次增量之后是999,而不是第一次增量之后
我敢肯定,有很多C语言程序员可以解释发生了什么:)您使用了错误的格式说明符来打印地址。这将调用未定义的行为,一旦调用UB,所有赌注都将取消。改用
%p
printf("%p \n", (void *)pa);
另一个问题是执行pa++代码>,您正在访问未分配的内存,这是UB的另一个原因
int* pa=&a;
pa
是指向整数的指针,定义了访问*pa
一旦你增加了指针,指针就指向了一些你没有分配的或者你不知道的内存(p之后),所以取消对它的引用会导致未定义的beahvior
pa++;
*pa
是UB
编辑:
使用适当的格式说明符打印指针值%p
,正如@haccks在您第一次分配指针指向的指针2686740
时指出的那样。指针是一个整数指针,整数使用4个字节(通常在您的计算机上使用4个字节)。这意味着pa++
将增加值4,即2686744
。再次这样做会导致2686748
如果要查看生成的汇编代码,则局部变量的顺序将被切换。代码运行时,顺序为a
,pa
,bla
。由于您无法明确控制此排序,因此打印输出被视为未定义
在你第一次做了pa++
之后,指针指向了它自己,这就是为什么你得到了“奇怪的值”
正如许多其他答案所提到的,这不是指针的良好使用,应该避免。在这种情况下,您无法控制指针指向的对象。指针算法的更好用法是指向数组的开头,然后执行pa++
以指向数组中的下一个元素。然后,您可能遇到的唯一问题是递增超过数组的最后一个元素。输出并不奇怪,这是意料之中的:在main()
中有三个变量,所有这些变量都存储在堆栈中,并且恰好是一个接一个的。其中一个变量是指针本身。因此,当您在第三行中取消对指针的引用时,您将获得指针本身的当前值
然而,这个输出是不可预测的,它是未定义的行为:您只允许使用指针算法访问单个内存对象中的数据,在您的情况下,内存对象只是一个int
。因此,在第一个pa++
之后访问*pa
是非法的,从那时起,程序可以执行任何操作
更具体地说,无法保证哪些其他变量遵循某个变量,它们遵循的顺序,或者是否有可访问的内存。即使在第一次pa++
之后阅读*pa
,也会导致程序崩溃。正如您所看到的,在许多情况下,您不会遇到崩溃(这很容易调试),但代码仍然被严重破坏。您并不比编译器聪明
正如另一个答案所说,你所做的是未定义的行为。对于pa
来说,你只是在做无意义的事情,它不符合任何针对某个既定目标的合理算法:它是无意义的
不过,我会向你提出一个可能发生的情况。尽管其中大部分可能是错误的,因为编译器进行了优化
int bla=999;
int a=42;
int* pa=&a;
这些变量在堆栈上分配
在编写pa=&a
时,您会说“我希望指针pa
等于a
的地址”
编译器可能已经按照顺序或声明分配了内存,这将给出如下结果:
bla
将具有地址0x00008880
a
的地址为0x00008884
pa
的地址为0x00008888
当你这样做时,pa++
你在说:把我的int指针移到内存中int的下一个位置。
由于整数是32位的,所以您正在执行pa=pa+4bytes
即pa=0x00008888
请注意,这是偶然的!,您可能正在指向pa
指针的地址。
所以现在指针pa
包含它自己的地址。。。这是相当深奥的,可以称之为
然后你又在问pa++
。。。因此pa=pa+4字节
因此,现在您可能正在访问一个未知的内存区域。这可能是访问权限冲突。如果你想读或写,这是未定义的行为。你在尝试吗