指针表现得很奇怪

时间:2015-01-14 09:28:04

标签: c++ c pointers

我是编程和c ++新手。我很感激你的帮助。

以下程序(在c ++中)在编译或运行时都没有遇到任何问题:

int main()
{
    int b = 5;
    int*a = &b;
    *(a+5) = 6;
    return 0;

}

但根据我所学到的一切,它不应该起作用,因为a是指向单个变量的指针。我在这里缺少什么?

4 个答案:

答案 0 :(得分:6)

您的程序在编译时确实不会遇到任何问题。它是关于编译的所有有效代码。

但是,它会在运行时遇到未定义的行为,因为a+5不是有效的地址。

如果你想知道它为什么要编译,你可以写这样的代码:

int func( int * buf, size_t size )
{
    for( size_t i = 0; i < size; ++i )
    {
       *(buf + size) = static_cast<int>(i); // or (int)i in C
    }
}

int main()
{
   int buf[ 6 ];
   func( buf, 6 );
}

在您的代码中a是指向内存的指针。 a + 5表示地址5&#34; ints&#34;从a点开始。由于a指向单个整数b,因此无法保证此类地址。有趣的是,它被明确定义为引用a+1,即使它指向内存中您不应该读取或写入的位置。但是指针本身有一些保证,即它会大于a,如果你从它中减去1,你将回到a,如果你在它和a之间做了一个ptrdiff你会得到1.但这只是一个特殊的属性&#34;一个过去的结束&#34;它允许程序员指定内存范围。

答案 1 :(得分:1)

程序确实有未定义的行为

int main()
{
    //This cause the loading of the "main" function to allocate memory for variable b
    //It could be in a memory page that was already allocated to the program
    //or in a new allocated page.
    int b = 5;

    //Here a just getting the address of variable b.
    int*a = &b;

    //This is the undefined behavior and can end up in two cases:
    // 1. If (a+5) value is in a memory space that is allocated to the application.
    //    Then no runtime error will happen, and the value will be writing there.
    //    probably dirting some other value, and can cause an undefined behavior later
    //    in the application execution.
    // 2. If (a+5) value is in a memory space that wasn't allocated to the application.
    //    the application will crash
    *(a+5) = 6;
    return 0;

}

现在,由于页面大小可能是4096而b在页面中的某个位置,因此* b + 5在大多数情况下仍然在同一页面中。如果你想挑战它,可以将它从5改为5000或更高,崩溃的几率会增加。

答案 2 :(得分:0)

是的,当您访问不在您的进程区域中的内存空间时,它应该不起作用,但可能没有人拥有该特定区域((a + 5)),该区域不会导致运行时非法内存访问或它能够。因此它是一个UB。

答案 3 :(得分:0)

只需添加现有答案。

访问

*(a+5) = a[5]

所以这是您未分配的位置。

在数组的情况下说

int a[6];

您拥有从a[0]a[5]的有效访问权限,其中a[5]是数组的最后一个元素,而a[6]之类的任何进一步访问都会导致未定义的行为地点不是由您分配的。

同样,你只需要一个像

这样的整数
int b=5;

int *a = &b;

a是指向&b的指针,即b的地址。

因此对此的有效访问只是a[0],这是您在堆栈上分配的唯一位置。

a[1] a[2]...之类的任何其他访问都会导致未定义的行为。

如果您有类似

的内容,则访问权限为有效
int b[6];
int *a = b;

现在a[5]将给出数组b

的最后一个元素的值