为什么这个函数会将一个int参数转换为一个易失性指针并立即取消引用它?

时间:2022-09-06 10:19:08

I just want to know what below function is doing

我只是想知道下面的功能在做什么

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

4 个解决方案

#1


24  

If val is a pointer when you pass it to this function, it makes sure that the value pointed by this pointer is read and returned to the caller.

如果val是将指针传递给此函数时的指针,则确保读取此指针指向的值并将其返回给调用者。

I suspect this might be a trick for embedded devices, where sometimes the operation of reading a value at an address has some effect on the hardware.
For instance, reading from an hardware FIFO will pop the read value from the FIFO.

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

Marking here the pointer as volatile make the compiler not optimize the read if it detects that the value is not used.

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

Example:

例:

#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

}

Note that I would do it differently, probably with a smartly named macro:

请注意,我会以不同的方式执行此操作,可能使用名称灵巧的宏:

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

Could you give us an example of usage in your case?

你能举个例子说明你的情况吗?

#2


5  

It appears to be trying to confuse the optimiser (and possibly the user). It is taking an integer, treating it as a pointer to an integer, and dereferencing it. The 'volatile' ensures that the optimiser will generate code for that dereference at that point and won't let the optimiser omit the fetch from memory. This is usually used for accessing memory mapped hardware registers,

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

#3


2  

It does the following:

它执行以下操作:

  • Passes a signed integer to a function.
  • 将带符号的整数传递给函数。
  • Converts the contents of the signed integer to a pointer. This doesn't make sense, since pointers cannot be signed. Formally, this is also not well-defined behavior and anything can happen.
  • 将有符号整数的内容转换为指针。这没有意义,因为指针无法签名。形式上,这也不是明确定义的行为,任何事情都可能发生。
  • The volatile keyword suggests that the contents of val should equal to a physical hardware address. When reading from such addresses, the volatile keyword is necessary, since the hardware register's contents may change at any time.
  • volatile关键字表明val的内容应该等于物理硬件地址。当从这样的地址读取时,volatile关键字是必要的,因为硬件寄存器的内容可能随时改变。
  • It takes the contents of that address and treats it as int, which is then returned.
  • 它接受该地址的内容并将其视为int,然后返回。
  • static means that the function has local scope.
  • static表示该函数具有局部范围。

Please note that if the target OS uses virtual addressing (such as a PC), the OS will just give you a slap on the fingers should you attempt to run this code.

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

All in all, this is poorly written code, which is neither safe, well-defined nor portable. You won't gain any valuable knowledge by staring at it.

总而言之,这是编写得很糟糕的代码,既不安全,定义明确也不便携。你不会通过盯着它获得任何有价值的知识。

#4


0  

It casts val to a pointer and returns it's value. Calls to myfunc() will work only if thy look like int i, j;

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

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

That should set j to 10

那应该将j设置为10

BUT it won't work on 64bit systems where sizeof(int *) is 8 and thus larger then sizeof(int) or on some old systems with sizeof(int) == 2

但它不能在64位系统上工作,其中sizeof(int *)为8,因此大于sizeof(int)或者在某些旧系统上使用sizeof(int)== 2

#1


24  

If val is a pointer when you pass it to this function, it makes sure that the value pointed by this pointer is read and returned to the caller.

如果val是将指针传递给此函数时的指针,则确保读取此指针指向的值并将其返回给调用者。

I suspect this might be a trick for embedded devices, where sometimes the operation of reading a value at an address has some effect on the hardware.
For instance, reading from an hardware FIFO will pop the read value from the FIFO.

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

Marking here the pointer as volatile make the compiler not optimize the read if it detects that the value is not used.

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

Example:

例:

#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

}

Note that I would do it differently, probably with a smartly named macro:

请注意,我会以不同的方式执行此操作,可能使用名称灵巧的宏:

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

Could you give us an example of usage in your case?

你能举个例子说明你的情况吗?

#2


5  

It appears to be trying to confuse the optimiser (and possibly the user). It is taking an integer, treating it as a pointer to an integer, and dereferencing it. The 'volatile' ensures that the optimiser will generate code for that dereference at that point and won't let the optimiser omit the fetch from memory. This is usually used for accessing memory mapped hardware registers,

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

#3


2  

It does the following:

它执行以下操作:

  • Passes a signed integer to a function.
  • 将带符号的整数传递给函数。
  • Converts the contents of the signed integer to a pointer. This doesn't make sense, since pointers cannot be signed. Formally, this is also not well-defined behavior and anything can happen.
  • 将有符号整数的内容转换为指针。这没有意义,因为指针无法签名。形式上,这也不是明确定义的行为,任何事情都可能发生。
  • The volatile keyword suggests that the contents of val should equal to a physical hardware address. When reading from such addresses, the volatile keyword is necessary, since the hardware register's contents may change at any time.
  • volatile关键字表明val的内容应该等于物理硬件地址。当从这样的地址读取时,volatile关键字是必要的,因为硬件寄存器的内容可能随时改变。
  • It takes the contents of that address and treats it as int, which is then returned.
  • 它接受该地址的内容并将其视为int,然后返回。
  • static means that the function has local scope.
  • static表示该函数具有局部范围。

Please note that if the target OS uses virtual addressing (such as a PC), the OS will just give you a slap on the fingers should you attempt to run this code.

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

All in all, this is poorly written code, which is neither safe, well-defined nor portable. You won't gain any valuable knowledge by staring at it.

总而言之,这是编写得很糟糕的代码,既不安全,定义明确也不便携。你不会通过盯着它获得任何有价值的知识。

#4


0  

It casts val to a pointer and returns it's value. Calls to myfunc() will work only if thy look like int i, j;

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

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

That should set j to 10

那应该将j设置为10

BUT it won't work on 64bit systems where sizeof(int *) is 8 and thus larger then sizeof(int) or on some old systems with sizeof(int) == 2

但它不能在64位系统上工作,其中sizeof(int *)为8,因此大于sizeof(int)或者在某些旧系统上使用sizeof(int)== 2