`*(volatile T*)0x1234;` 是否保证转换为读取指令? [英] Is `*(volatile T*)0x1234;` guaranteed to translate into read instruction?

查看:32
本文介绍了`*(volatile T*)0x1234;` 是否保证转换为读取指令?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在使用硬件时,有时需要从特定寄存器读取数据并丢弃实际值(例如清除某些标志).一种方法是显式读取并丢弃该值,例如:

When working with hardware it is sometimes required to perform a read from a specific register discarding the actual value (to clear some flags, for example). One way would be to explicitly read and discard the value such as:

int temp = *(volatile int*)0x1234; // 0x1234 is the register address
(void)temp;                          // To silence the "unused" warning

另一种似乎有效的方法很简单:

Another way that seem to work is simply:

*(volatile int*)0x1234;

但这似乎并不明显意味着读取访问权限,但它似乎在我检查过的编译器上转换为访问权限.这是标准保证的吗?

But this doesn't seem to obviously imply the read access, yet it seems to translate to one on compilers I checked. Is this guaranteed by the standard?

带有 -O3 的 ARM GCC 示例:https://arm.godbolt.org/z/9Vmt6n

Example for ARM GCC with -O3: https://arm.godbolt.org/z/9Vmt6n

void test(void)
{
    *(volatile int *)0x1234;
}

翻译成

test():
        mov     r3, #4096
        ldr     r3, [r3, #564]
        bx      lr

推荐答案

C 2018 6.7.3 8 说:

C 2018 6.7.3 8 says:

具有 volatile 限定类型的对象可能会以实现未知的方式进行修改或具有其他未知的副作用.因此,任何引用此类对象的表达式都应严格按照抽象机器的规则进行评估,如 5.1.2.3....

An object that has volatile-qualified type may be modified in ways unknown to the implementation or have other unknown side effects. Therefore any expression referring to such an object shall be evaluated strictly according to the rules of the abstract machine, as described in 5.1.2.3.…

由于 *(volatile int*)0x1234; 是引用具有 volatile 限定类型的对象的表达式,因此评估它必须访问该对象.(当然,这假定 0x1234 代表对 C 实现中某个对象的有效引用.)

Since *(volatile int*)0x1234; is an expression referring to an object with volatile-qualified type, evaluating it must access the object. (This presumes that 0x1234 stands for a valid reference to some object in the C implementation, of course.)

根据 C 2018 5.1.2.3 4:

Per C 2018 5.1.2.3 4:

在抽象机中,所有表达式都按照语义指定的方式进行评估.如果实际实现可以推断出表达式的值未被使用并且不会产生任何需要的副作用(包括由调用函数或访问易失性对象引起的任何副作用),则它不需要计算表达式的一部分.

In the abstract machine, all expressions are evaluated as specified by the semantics. An actual implementation need not evaluate part of an expression if it can deduce that its value is not used and that no needed side effects are produced (including any caused by calling a function or accessing a volatile object).

根据 C 2018 6.5 1:

Per C 2018 6.5 1:

表达式是一系列运算符和操作数,用于指定值的计算,或指定对象或函数,或产生副作用,或执行它们的组合.

An expression is a sequence of operators and operands that specifies computation of a value, or that designates an object or a function, or that generates side effects, or that performs a combination thereof.

因此,表达式指定值的计算.5.1.2.3 4 段告诉我们这个评估是由抽象机执行的,6.7.3 8 段告诉我们实际实现执行了抽象机执行的这个评估.

Thus, an expression specifies computation of a value. Paragraph 5.1.2.3 4 tells us that this evaluation is performed by the abstract machine, and 6.7.3 8 tells us the actual implementation performs this evaluation that the abstraction machine performs.

需要注意的是,访问"的构成是由实现定义的.C 标准定义的访问"包括读取和写入 (C 3.1 1),但 C 标准无法指定它意味着读取或写入某些特定硬件.

One caveat is that what constitutes "access" is implementation-defined. "Access" as defined by the C standard includes both reading and writing (C 3.1 1), but the C standard is unable to specify that it means reading from or writing to some particular piece of hardware.

为了进一步了解语言律师、领域,C 6.3.2.1 2 告诉我们:

To go further into language-lawyer, territory, C 6.3.2.1 2 tells us:

除非它是 sizeof 运算符的操作数,一元 & 运算符,++ 运算符,--操作符,或者的左操作数.操作符或者赋值操作符,一个没有数组类型的左值被转换为存储在指定对象中的值(并且不是更长的左值);这称为左值转换.

Except when it is the operand of the sizeof operator, the unary & operator, the ++ operator, the -- operator, or the left operand of the . operator or an assignment operator, an lvalue that does not have array type is converted to the value stored in the designated object (and is no longer an lvalue); this is called lvalue conversion.

因此,由于 *(volatile int*)0x1234; 是左值,根据 * 运算符的定义,它不是所列运算符的操作数,它转换为存储在对象中的值.因此,这个表达式指定了存储在对象中的值的计算.

Thus, since *(volatile int*)0x1234; is an lvalue, by dint of the * operator, and is not the operand of the listed operators, it is converted to the value stored in the object. Thus, this expression specifies the computation of the value that is stored in the object.

这篇关于`*(volatile T*)0x1234;` 是否保证转换为读取指令?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆