Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/asp.net/35.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++;指针算法_C++_C_Pointers_Integer_Pointer Arithmetic - Fatal编程技术网

C++ 我不知道';我不懂C++;指针算法

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

我有下面的程序,它定义了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 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字节

因此,现在您可能正在访问一个未知的内存区域。这可能是访问权限冲突。如果你想读或写,这是未定义的行为。

你在尝试吗