21

我只想知道下面的函数在做什么

static int myfunc(int val)
{
    return *(volatile int *)val;
}
4

4 回答 4

24

如果val是一个指针,当你将它传递给这个函数时,它会确保这个指针指向的值被读取并返回给调用者。

我怀疑这可能是嵌入式设备的一个技巧,有时在地址处读取值的操作会对硬件产生一些影响。
例如,从硬件 FIFO 读取将弹出 FIFO 中的读取值。

在此处将指针标记为volatile会使编译器在检测到未使用该值时不会优化读取。

例子:

#define FIFO_ADDRESS 0x800050

static int myfunc(int val)
{
    return *(volatile int *)val; // the address *will* be read
}

static int bad( int val )
{
    return *(int*)val; // might be optimized to nop()  
                       // by the compiler if the value 
                       // is not used by the caller
}

int main(){
   bad( FIFO_ADDRESS );    // could be NOP since return value is not used

   myfunc( FIFO_ADDRESS ); // *WILL* perform a READ operation on the FIFO, 
                           // even though the result is not used, because 
                           // of the volatile keyword

}

请注意,我会以不同的方式进行操作,可能会使用一个巧妙命名的宏:

#define FORCE_INT_PTR_READ( address ) *(volatile int *)address 

你能给我们举一个你的例子吗?

于 2013-07-02T12:49:59.340 回答
5

它似乎试图混淆优化器(可能还有用户)。它采用一个整数,将其视为指向整数的指针,然后取消引用它。'volatile' 确保优化器将在此时为该取消引用生成代码,并且不会让优化器忽略从内存中提取。这通常用于访问内存映射的硬件寄存器,

于 2013-07-02T12:50:22.740 回答
3

它执行以下操作:

  • 将有符号整数传递给函数。
  • 将有符号整数的内容转换为指针。这是没有意义的,因为指针不能被签名。形式上,这也不是明确定义的行为,任何事情都可能发生。
  • volatile 关键字表明 的内容val应该等于物理硬件地址。从这些地址读取时,需要使用 volatile 关键字,因为硬件寄存器的内容随时可能发生变化。
  • 它获取该地址的内容并将其视为 int,然后返回。
  • static表示该函数具有本地范围。

请注意,如果目标操作系统使用虚拟寻址(例如 PC),如果您尝试运行此代码,操作系统只会给您一记耳光。

总而言之,这是写得很糟糕的代码,既不安全、定义明确也不可移植。盯着它看,你不会获得任何有价值的知识。

于 2013-07-02T12:52:48.267 回答
0

它转换val为一个指针并返回它的值。myfunc()只有当你看起来像 int i, j 时,调用才会起作用;

i = 10;
j = myfunc( (int)&i )` 

那应该将 j 设置为 10

它不适用于sizeof(int *)8 位的 64 位系统,因此更大,sizeof(int)或者在一些旧系统上sizeof(int) == 2

于 2013-07-02T12:52:37.030 回答