如何将两个数据保存在 C 的同一内存位置?
How is it possible to save two data in the same memory location on C?
我正在学习 C 语言,特别是指针,我有这个小问题。
如何将两个数据保存在 C 的同一个内存位置?看我的代码:
#include <stdio.h>
int main()
{
const int y = 2;
int *const ptr_y = &y;
*ptr_y = 4;
//Values
printf("%d\n", y);
printf("%d\n\n", *ptr_y);
//Memory locations
printf("%p\n", &y);
printf("%p\n", ptr_y);
return (0);
}
输出:
2
4
0x7ffeeb501788
0x7ffeeb501788
我期望的输出:
4
4
0x7ffeeb501788
0x7ffeeb501788
我想知道这段代码在内部是如何工作的。
重要提示:我知道常量指针未正确声明 (const int *ptr_y)。
代码调用 undefined behavior 因为您不能更改 const
变量的内容,因此输出没有意义,根据上面链接的未定义行为的定义,它可以是任何东西.
您没有将数据保存在两个不同的位置,它是同一个位置。
y
存储在某个(内存)位置,该位置有一个地址,ptr_y
是一个指针,它包含相同的内存地址,因为您使用 address-of
分配了它运算符 &
:
int *const ptr_y = &y;
上面的赋值丢弃了 const
限定符,因此,编译器允许您尝试将 y
的值更改为 *ptr_y = 4
,这仍然无效但由于错误的分配,它成为可能。如果您使用:
,您应该始终尊重指针中的 const
限定符
const int y = 2;
const int* ptr_y = &y;
编译器不会让你这样做的:
*ptr_y = 4;
error: assignment of read-only location '*ptr_y'
使用正确的代码,通过使用 *
运算符取消对 ptr_y
的引用,您将访问存储在 ptr_y
中的地址,顺便说一下,它是 y
的地址,所以它是相同的内存地址,您只是以两种不同的方式访问它:
int y = 2; // non const
int *const ptr_y = &y; // constant pointer is allowed
*ptr_y = 4;
//Values
printf("%d\n", y);
printf("%d\n\n", *ptr_y);
//Memory locations
printf("%p\n", (void*)&y); // %p specifier expects void*
printf("%p\n", (void*)ptr_y);
4
4
0x7ffd0f9aee34
0x7ffd0f9aee34
首先,int *const ptr_y = &y;
不是有效的 C,所以如果你的编译器生成了一个可执行文件,尽管有这段代码,它的所有行为都是无效的。如果您没有收到来自编译器的消息,则意味着您的编译器配置为 non-standard。参见 What compiler options are recommended for beginners learning C?
严格来说printf("%p\n", &y);
也应该转换为(const void*)&y
。
C 标准未指定 const int y = 2;
存储值 2 的位置。它可以在寄存器中,在堆栈上,在标记为“只读”(.rodata
或类似)的 read/write 内存中,或者它可以存储在真正的 read-only 内存中,例如闪存,以防万一嵌入式系统。
如果您对该内存位置进行写访问,则该行为未由 C 标准定义。 Undefined behavior = 任何事情都可能发生,包括:
- 它可以更新内存,下次你读回
4
。
- 它可以更新内存,但编译器优化器不会生成代码来读回它,所以你仍然得到
2
。
- 编译器可以忽略生成写入尝试的代码。
- 它可能是真实的 read-only 内存,所以当您尝试写入它时,没有任何反应。
- 它可能是 read-only 内存并受到保护,因此写入尝试会导致硬件异常或类似情况。
总的来说,分析调用未定义行为时到底发生了什么(症状)并没有太大意义。重要的是理解为什么代码包含未定义的行为(根本原因)。
我正在学习 C 语言,特别是指针,我有这个小问题。
如何将两个数据保存在 C 的同一个内存位置?看我的代码:
#include <stdio.h>
int main()
{
const int y = 2;
int *const ptr_y = &y;
*ptr_y = 4;
//Values
printf("%d\n", y);
printf("%d\n\n", *ptr_y);
//Memory locations
printf("%p\n", &y);
printf("%p\n", ptr_y);
return (0);
}
输出:
2
4
0x7ffeeb501788
0x7ffeeb501788
我期望的输出:
4
4
0x7ffeeb501788
0x7ffeeb501788
我想知道这段代码在内部是如何工作的。
重要提示:我知道常量指针未正确声明 (const int *ptr_y)。
代码调用 undefined behavior 因为您不能更改 const
变量的内容,因此输出没有意义,根据上面链接的未定义行为的定义,它可以是任何东西.
您没有将数据保存在两个不同的位置,它是同一个位置。
y
存储在某个(内存)位置,该位置有一个地址,ptr_y
是一个指针,它包含相同的内存地址,因为您使用 address-of
分配了它运算符 &
:
int *const ptr_y = &y;
上面的赋值丢弃了 const
限定符,因此,编译器允许您尝试将 y
的值更改为 *ptr_y = 4
,这仍然无效但由于错误的分配,它成为可能。如果您使用:
const
限定符
const int y = 2;
const int* ptr_y = &y;
编译器不会让你这样做的:
*ptr_y = 4;
error: assignment of read-only location '*ptr_y'
使用正确的代码,通过使用 *
运算符取消对 ptr_y
的引用,您将访问存储在 ptr_y
中的地址,顺便说一下,它是 y
的地址,所以它是相同的内存地址,您只是以两种不同的方式访问它:
int y = 2; // non const
int *const ptr_y = &y; // constant pointer is allowed
*ptr_y = 4;
//Values
printf("%d\n", y);
printf("%d\n\n", *ptr_y);
//Memory locations
printf("%p\n", (void*)&y); // %p specifier expects void*
printf("%p\n", (void*)ptr_y);
4
4
0x7ffd0f9aee34
0x7ffd0f9aee34
首先,int *const ptr_y = &y;
不是有效的 C,所以如果你的编译器生成了一个可执行文件,尽管有这段代码,它的所有行为都是无效的。如果您没有收到来自编译器的消息,则意味着您的编译器配置为 non-standard。参见 What compiler options are recommended for beginners learning C?
严格来说printf("%p\n", &y);
也应该转换为(const void*)&y
。
C 标准未指定 const int y = 2;
存储值 2 的位置。它可以在寄存器中,在堆栈上,在标记为“只读”(.rodata
或类似)的 read/write 内存中,或者它可以存储在真正的 read-only 内存中,例如闪存,以防万一嵌入式系统。
如果您对该内存位置进行写访问,则该行为未由 C 标准定义。 Undefined behavior = 任何事情都可能发生,包括:
- 它可以更新内存,下次你读回
4
。 - 它可以更新内存,但编译器优化器不会生成代码来读回它,所以你仍然得到
2
。 - 编译器可以忽略生成写入尝试的代码。
- 它可能是真实的 read-only 内存,所以当您尝试写入它时,没有任何反应。
- 它可能是 read-only 内存并受到保护,因此写入尝试会导致硬件异常或类似情况。
总的来说,分析调用未定义行为时到底发生了什么(症状)并没有太大意义。重要的是理解为什么代码包含未定义的行为(根本原因)。