使用gcc上的指针将值存储在手动位置时出错

时间:2022-08-09 21:41:13
#include<stdio.h>

int main(void){

    int a[3] = {1,2,3};
    int *p;

    p = &a+2;

    // here p and &a+2 will going to be same...having some particular address on memory

    *p = 56;

    // m writing 56 on *(p) or *(&a+2)...

    printf("%d %d\n",*p,*(&a+2));

    return 0;
}

o/p showing me is what!! *p = 56 but *(&a+2) = same as &a+2...

o / p显示我是什么!! * p = 56但*(&a + 2)=与&a + 2相同...

For p = &a+1 it's giving me a stack smashing...

对于p =&a + 1,它给了我一堆粉碎......

On *(*(&a+2)) giving me the desired result 56...

在*(*(&a + 2))给我想要的结果56 ...

Can anyone explain to me what the exact reason behind this is?

任何人都可以向我解释这背后的确切原因是什么?

3 个解决方案

#1


1  

p = &a+2;

is functionally equivalent to

在功能上等同于

p = &(a[6]);

because adding two to &a adds sizeof(a)*2 to &a, and sizeof(a)*2 is equal to sizeof(a[0])*3*2. Dereferencing the resulting pointer evokes undefined behaviour because it's beyond the end of the array.

因为添加两个&a将sizeof(a)* 2添加到&a,而sizeof(a)* 2等于sizeof(a [0])* 3 * 2。取消引用生成的指针会引发未定义的行为,因为它超出了数组的末尾。


#include <stdio.h>

int main(void) {
    int a[3] = {1,2,3};
    int *p = &a+2;
    printf("a    @ %p\n", (void*)a);
    printf("a    @ %p\n", (void*)&a);
    printf("a[0] @ %p\n", (void*)&(a[0]));
    printf("a[2] @ %p\n", (void*)&(a[2]));
    printf("p    = %p\n", (void*)p);
    printf("a[6] @ %p\n", (void*)&(a[6]));
    return 0;
}

gives

$ gcc -Wall -Wextra -pedantic --std=c99 a.c -o a && a
a.c: In function ‘main’:
a.c:5:14: warning: initialization from incompatible pointer type [enabled by default]
     int *p = &a+2;
              ^
a    @ 0x3878b9c3030
a    @ 0x3878b9c3030
a[0] @ 0x3878b9c3030
a[2] @ 0x3878b9c3038
p    = 0x3878b9c3048
a[6] @ 0x3878b9c3048

#2


0  

You mean p=a+2;, not p=&a+2;. The latter forms a pointer to the array a (with &a) and then tries to form a pointer to a non-existent other array (which would be a row in a multidimensional array if it existed). Pointers to arrays are rarely used, which helps people confuse arrays and the pointers into which they decay.

你的意思是p = a + 2 ;,而不是p =&a + 2;。后者形成一个指向数组a(带有&a)的指针,然后尝试形成一个指向不存在的其他数组的指针(如果它存在,它将是多维数组中的一行)。很少使用指向数组的指针,这有助于人们混淆数组和它们衰变的指针。

#3


0  

Can anyone explain to me what the exact reason behind this is?

任何人都可以向我解释这背后的确切原因是什么?

The reasoning is that you are invoking undefined behavior, so your compiler and thus your program is allowed to do whatever the hell it wants. That is pretty much the definition of "undefined behavior": the standard doesn't say what the correct thing to do is, so the program can do anything.

原因是您正在调用未定义的行为,因此您的编译器以及您的程序可以执行它想要的任何操作。这几乎就是“未定义行为”的定义:标准没有说明正确的事情是什么,所以程序可以做任何事情。

Just because *(*(&a+2)) gives you the right answer doesn't mean that &a+2 is valid code. There are plenty of cases where undefined behavior can result in a working program, but there's no guarantee that such a program will continue to work or even continue to compile as you make further changes.

仅仅因为*(*(&a + 2))给出正确答案并不意味着&a + 2是有效代码。在很多情况下,未定义的行为可能导致工作程序,但不能保证这样的程序将继续工作,甚至在进行进一步更改时继续编译。

The undefined behavior, as several people have already pointed out, is from p = &a+2 which assigns an uninitialized address to an incompatible pointer.

正如几个人已经指出的那样,未定义的行为来自p =&a + 2,它将未初始化的地址分配给不兼容的指针。

#1


1  

p = &a+2;

is functionally equivalent to

在功能上等同于

p = &(a[6]);

because adding two to &a adds sizeof(a)*2 to &a, and sizeof(a)*2 is equal to sizeof(a[0])*3*2. Dereferencing the resulting pointer evokes undefined behaviour because it's beyond the end of the array.

因为添加两个&a将sizeof(a)* 2添加到&a,而sizeof(a)* 2等于sizeof(a [0])* 3 * 2。取消引用生成的指针会引发未定义的行为,因为它超出了数组的末尾。


#include <stdio.h>

int main(void) {
    int a[3] = {1,2,3};
    int *p = &a+2;
    printf("a    @ %p\n", (void*)a);
    printf("a    @ %p\n", (void*)&a);
    printf("a[0] @ %p\n", (void*)&(a[0]));
    printf("a[2] @ %p\n", (void*)&(a[2]));
    printf("p    = %p\n", (void*)p);
    printf("a[6] @ %p\n", (void*)&(a[6]));
    return 0;
}

gives

$ gcc -Wall -Wextra -pedantic --std=c99 a.c -o a && a
a.c: In function ‘main’:
a.c:5:14: warning: initialization from incompatible pointer type [enabled by default]
     int *p = &a+2;
              ^
a    @ 0x3878b9c3030
a    @ 0x3878b9c3030
a[0] @ 0x3878b9c3030
a[2] @ 0x3878b9c3038
p    = 0x3878b9c3048
a[6] @ 0x3878b9c3048

#2


0  

You mean p=a+2;, not p=&a+2;. The latter forms a pointer to the array a (with &a) and then tries to form a pointer to a non-existent other array (which would be a row in a multidimensional array if it existed). Pointers to arrays are rarely used, which helps people confuse arrays and the pointers into which they decay.

你的意思是p = a + 2 ;,而不是p =&a + 2;。后者形成一个指向数组a(带有&a)的指针,然后尝试形成一个指向不存在的其他数组的指针(如果它存在,它将是多维数组中的一行)。很少使用指向数组的指针,这有助于人们混淆数组和它们衰变的指针。

#3


0  

Can anyone explain to me what the exact reason behind this is?

任何人都可以向我解释这背后的确切原因是什么?

The reasoning is that you are invoking undefined behavior, so your compiler and thus your program is allowed to do whatever the hell it wants. That is pretty much the definition of "undefined behavior": the standard doesn't say what the correct thing to do is, so the program can do anything.

原因是您正在调用未定义的行为,因此您的编译器以及您的程序可以执行它想要的任何操作。这几乎就是“未定义行为”的定义:标准没有说明正确的事情是什么,所以程序可以做任何事情。

Just because *(*(&a+2)) gives you the right answer doesn't mean that &a+2 is valid code. There are plenty of cases where undefined behavior can result in a working program, but there's no guarantee that such a program will continue to work or even continue to compile as you make further changes.

仅仅因为*(*(&a + 2))给出正确答案并不意味着&a + 2是有效代码。在很多情况下,未定义的行为可能导致工作程序,但不能保证这样的程序将继续工作,甚至在进行进一步更改时继续编译。

The undefined behavior, as several people have already pointed out, is from p = &a+2 which assigns an uninitialized address to an incompatible pointer.

正如几个人已经指出的那样,未定义的行为来自p =&a + 2,它将未初始化的地址分配给不兼容的指针。