#define address (*((unsigned int *)10))
void main()
{
unsigned int *p;
p = &(address);
}
'p' 的值为 10。如何评估上述表达式?不是从最里面的支架到最外面的支架吗?但如果是这样,那么 '&' 有一个没有意义的左值。我知道它会转换为 &*(10) ,其值为 10。
p = &(0)
不是在编译期间归结为吗?
不,一点也不:编译器不知道地址 10 处有值 0。
它是高度不可移植的,可能应该提供一个方便的标识符 -address
可用于从内存中定义的位置读取值。我想它来自嵌入式编程。
address
可以解释为unsigned int
位于地址 10 的变量,因此拼写错误,因为它的地址 - 10 - 只能由&address
.
通常,当您正在处理您不理解的事情时,最容易采取这一步骤。您的问题是正确的:
不是从最里面的支架到最外面的支架吗?
所以让我们从那里开始。如果您使用宏的最内层大括号中的((unsigned int *)10)
内容,它会做什么?此语句将文字 value 类型转换10
为指向 unsigned int 的指针。我们现在有一个指向地址 10 的指针。正如@glglgl 所说,您的宏命名不正确。如果您希望宏成为地址,那么您将在此处结束。这是嵌入式编程中经常使用的一种技术,因此您可以准确地知道地址的用途(例如特定的外围寄存器)。
下一组大括号,(*((unsigned int *)10))
取消引用我们刚刚类型转换的指针。所以宏实际上给了我们当前存储在 address 的值10
。
最后,当您将值分配给指针p = &(address);
时,您只是获取存储在 address 的值的地址10
,即 10。您可以很容易地陈述p = (unsigned int *)10;
并得到相同的结果。
void main()
应该是int main(void)
。告诉您使用void main()
的任何书籍或教程都是由不太了解 C 语言的人编写的。
宏展开后的主体main
等价于:
unsigned int *p = &(*((unsigned int *)10));
如果一元运算符的操作数是一元运算&
符的结果*
,则两个运算符都被省略(这在标准中明确说明),因此上述等价于:
unsigned int *p = (unsigned int *)10;
这将获取int
值10
并将其从 转换int
为unsigned int*
。
整数到指针转换的结果是实现定义的,但“旨在与执行环境的寻址结构一致”。
因此,如果“内存地址 10”的想法有意义,那么上面的内容可能会设置p
为该地址。
结果指针可能未正确对齐。在许多系统上,unsigned int
是 4 个字节并且需要 4 个字节对齐;10 不是 4 的倍数。
该代码似乎是故意混淆的。简化版更直接,不太可能有用。
万一您知道unsigned int
系统上的地址 10 有一个对象,并且您需要访问它,那么
unsigned int *p = (unsigned int *)10;
将是这样做的方法。
address 是指向内存地址(内存地址 10)的指针,二级间接。所以 &adress 是内存地址 10,所以 p 是内存地址 10。