繁体   English   中英

以下语句是否将物理地址或虚拟地址分配给指针?

[英]Do the following statements assign either physical or virtual address to a pointer?

https://stackoverflow.com/a/2761494/156458

C和C ++都没有提供严格定义的功能,该功能不允许您将特定的物理地址分配给指针。 因此,您有关“如何将0地址分配给指针”的问题正式没有答案。 您根本无法为C / C ++中的指针分配特定的地址。 但是,在实现定义的功能领域中, 显式的整数到指针的转换旨在实现这种效果。 因此,您可以按照以下步骤进行操作

 uintptr_t address = 0; void *p = (void *) address; 

请注意,这与执行操作不同

 void *p = 0; 

后者总是产生空指针值,而前者通常不会。 前者通常会产生一个指向物理地址0的指针,该地址可能为也可能不是给定平台上的空指针值。

我很惊讶地发现void *p = 0并没有分配物理或虚拟地址0,而是将空指针void分配给了指针。

引号还说,“显式整数到指针转换”可以为指针分配地址。

问题:

  1. void *p = 0 ,是否存在从0void*隐式转换?

    隐式转换是否与显式转换(void *)0 ,即void *p = 0void *p = (void*) 0吗?

    void *p = (void*) 0产生指向物理地址或虚拟地址0的指针或void的空指针?

  2. 如果我使用非零数字,例如void *p = 123 ,是否存在从123void *隐式转换?

    隐式转换与显式转换(void *) 123吗?

    void *p = 123void *p = (void *)123会使p指向物理或虚拟地址123的指针吗?

    如果void *p = (void *)123无法生成指向物理或虚拟地址123的指针,则可以int addr = 123; void *p = (void *)addr; int addr = 123; void *p = (void *)addr; 我通过在引用的第一个示例中将int替换为unitptr_t创建它。

谢谢。

如果你说

char *p = 0x12345;

您可能会分配p指向地址0x12345 无论是虚拟地址还是物理地址,我们都不能说。 这取决于您的计算机及其配置。 (但是,如果您的计算机使用虚拟内存,并且正在编写普通的用户程序,那么它肯定是虚拟地址。)

在上面我说“大概”,部分原因是严格来讲,为指针分配整数并不明确。 为了安全起见,您应该写

char *p = (char *)0x12345;

同样,这将分配p指向地址0x12345

但是接下来我们来谈谈特殊情况。 如果你写

char *p = 0;

要么

char *p = (char *)0;

问题是,您是否已分配p指向地址0 答案可能是在任何传统机器上,但这不能保证,因为空指针存在特殊情况。

不是说p = 0 不会分配p指向地址0 ,而是可能不会 在空指针的内部表示形式不是全零的机器上,分配p = 0会将p设置为该空指针值,因此p 不会指向地址0。

TL; DR:您所要求的大部分是特定于实现的行为和语言扩展领域。 如果您确实需要这种行为,请查阅编译器文档。

  1. void *p = 0 ,是否存在从0void*隐式转换?

初始化是不合格的,但是许多编译器都接受它作为扩展。 那些确实定义了所需结果的人,但实际上,它们确实提供了对void *的隐式转换。

因为文字0是“空指针常量”,因为初始化程序执行与简单赋值相同的转换,并且因为简单赋值为将空指针常量赋值给指针提供了特殊情况,所以, 0被隐式转换为void * 此外,因为0是空指针常量,所以这种转换会导致类型为void *的空指针。

隐式转换是否与显式转换(void *)0 ,即void *p = 0void *p = (void*) 0吗?

有充分的理由期望接受前一种形式的编译器将与后一种形式完全相同,但是同样,前者是不合格的,并且将其接受为扩展名的实现为其定义了自己的语义。

是。 C无处可区分通过强制转换和相同类型之间的自动转换显式指定的转换效果。

void *p = (void*) 0产生指向物理地址或虚拟地址0的指针或void的空指针?

它初始化p包含一个空指针(类型为void * )。 根据C,空指针不会指向任何对象,并且C除了对象或函数的地址之外没有任何地址意义,因此至少在这种意义上,将此类指针解释为指向任何特定地址是不正确的。 取消引用这样的指针的效果不是由C定义的,而是可以由某些实现定义的-可能试图访问地址0的对象。

  1. 如果我使用非零数字,例如void *p = 123 ,是否存在从123void *隐式转换?

该初始化不符合要求,但是某些编译器提供了隐式转换作为扩展。

隐式转换与显式转换(void *) 123吗?

有很好的理由期望编译器完全实现这种隐式转换,但同样要实现“扩展”。

void *p = 123void *p = (void *)123会使p指向物理或虚拟地址123的指针吗?

那是实现定义的。 同样,C除了对象或函数的地址之外,没有其他意义的地址,特别是它本身拒绝指定将整数转换为指针类型的结果,除了首先通过将指针转换为整数而获得的整数外,对于值为0的整数常量表达式。

但是,在某些实现中,将整数(值为0的整数常量除外)转换为指针具有将整数解释为地址,并转换为指向该地址的指针的效果,就像存在一个带有该地址的对象一样地址。 托管 C实现中,这通常是虚拟地址。 独立实现中,它通常是物理地址。 一些实现方式也可以将此行为扩展为值为0的整数常量,该常数可能或可能不是固有地不一致。

如果void *p = (void *)123无法生成指向物理或虚拟地址123的指针,则可以int addr = 123; void *p = (void *)addr; int addr = 123; void *p = (void *)addr; 我通过在引用的第一个示例中将int替换为unitptr_t创建它。

完全有理由期望,显式转换值为123的int变量的结果与显式转换值为123的整数常量的结果完全相同,但是从技术上讲,它是实现定义的,可能为编译器提供了遵循的空间。区分。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM