为什么使用函数参数'foo'这样:*(& foo)?

编程入门 行业动态 更新时间:2024-10-27 05:26:07
本文介绍了为什么使用函数参数'foo'这样:*(& foo)?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧! 问题描述

Linux内核中的代码片段使用了一个这样的函数参数:

int do_signal(int signr,int eax / *其他参数... * /){ / * ... * / *(& eax)= - EINTR; / * ... * / }

代码的目的是将-EINTR放在eax存在的内存中,但是我不能告诉为什么只是分配给eax将不会工作:

eax = -EINTR

编译器如何在

一个可能的目的是保持寄存器中的 eax 变量。如果我们查看 C99草案标准,请参阅 6.5.3.2 地址和间接运算符

一元&运算符产生其操作数的地址。 [...]如果操作数是一元运算符的结果,那么运算符和&运算符,并且结果是,如同两个省略,除了运算符的约束仍适用 ,结果不是lvalue。[...]

在脚注 (强调我的进展):

因此,& * E等同于E是空指针)和&(E1 [E2])到((E1)+(E2))。 总是如此,如果E是函数指示符或者是一元运算符的有效操作数的左值, 运算符,*& E是等于E 的函数指示符或左值。

在&运算符:

运算符应该是一个函数指示符,一个[]或一元*运算符的结果,或者一个左值指定一个不是位字段并且未声明为寄存器存储类别说明符

这是有意义的,因为我们不能取寄存器的地址并且因此通过执行操作的地址,它们可能已经试图防止编译器完全在寄存器中执行操作并且确保修改特定存储器位置中的数据。

由于ouah指出,这并不妨碍编译器优化有效的无操作,而是 Linux内核中的GCC入侵。 Linux依赖于许多 gcc 扩展,并且考虑到 0.12 是一个非常旧的内核 gcc 可能已经保证行为或可能有意外可靠工作的方式,但我找不到任何文档说。

A code snippet in Linux kernel 0.12 use a function parameter like this:

int do_signal(int signr, int eax /* other parameters... */) { /* ... */ *(&eax) = -EINTR; /* ... */ }

The purpose of the code is to put -EINTR to the memory where eax lives, but I can not tell why it won't work if just assigning to eax:

eax = -EINTR

How would the compiler make a difference between eax and *(&eax)?

解决方案

One possible intention could be to keep the eax variable out of a register. If we look at the C99 draft standard we see that section 6.5.3.2 Address and indirection operators says (emphasis mine):

The unary & operator yields the address of its operand. [...]If the operand is the result of a unary * operator, neither that operator nor the & operator is evaluated and the result is as if both were omitted, except that the constraints on the operators still apply and the result is not an lvalue.[...]

in footnote 87 it says (emphasis mine going forward):

Thus, &*E is equivalent to E (even if E is a null pointer), and &(E1[E2]) to ((E1)+(E2)). It is always true that if E is a function designator or an lvalue that is a valid operand of the unary & operator, *&E is a function designator or an lvalue equal to E.

we find the following constraint on & operator:

The operand of the unary & operator shall be either a function designator, the result of a [] or unary * operator, or an lvalue that designates an object that is not a bit-field and is not declared with the register storage-class specifier.

Which makes sense since we can not take the address of a register and so by performing an address of operation they may have been trying to prevent the compiler from performing the operations completely in registers and ensure that data in specific memory locations are modified.

As ouah points out this does not prevent the compiler from optimizing what is effectively a no-op away but as documented in GCC hacks in the Linux kernel. Linux has relied on many gcc extensions and considering that 0.12 is a very old kernel gcc may have guaranteed that behavior or may have by accident reliably worked that way but I can not find any documentation that says so.

更多推荐

为什么使用函数参数'foo'这样:*(& foo)?

本文发布于:2023-10-16 15:53:26,感谢您对本站的认可!
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:函数   参数   foo   amp

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!