【问题标题】:What does this function return这个函数返回什么
【发布时间】:2012-03-04 06:56:25
【问题描述】:

如果在函数中传递了一个 volatile 变量,如下所示...

这个函数是否总是返回一个平方值,我的意思是有时值可以改变,因为声明了一个 volatile 变量。

基本上,我想说的是传递的变量是易失性的。希望,我很清楚。但是,如果我通过引用传递会改变整个场景......我是对的吗??

volatile int a;
int main()
{
   function(a);
   return 1;
}
int function b(int a)
{

    int x=a;

    int y=a;

    return x*y;

}

【问题讨论】:

    标签: c compiler-construction embedded volatile


    【解决方案1】:

    volatile 限定符告诉编译器变量可能会改变而不是它会改变。在任何情况下都不能自发改变;某些事情必须导致它发生变化——即使该原因是代码外部的。

    在这种情况下代码是错误的(或者至少没有以您可能想要的方式举例说明volatile 的效果),因为传递给function() 的参数没有 声明为易失性。它与全局变量同名这一事实可能令人困惑,但通过将全局变量a 分配给函数参数a,您可以立即将其与波动性解耦。

    如果代码被修改(并使其有效且可编译):

    volatile int a;
    
    int function( void )
    {
        int x=a;
        int y=a;
    
        return x*y;
    }
    
    int main()
    {
       function();
       return 1;
    }
    

    那么volatile 的效果只是编译器将显式分配xy,而不应用任何可能的优化。如果没有限定符,编译器可能会(在启用优化时)将function() 减少为:

    int function( void )
    {
        return a * a ;
    }
    

    甚至可能内联整个函数。此外,由于函数的返回值没有分配给任何东西,编译器可能会将整个代码优化为只是

    int main()
    {
       return 1;
    }
    

    如果a 是易变的,那么在调用function() 时,对xy 的赋值必须发生。

    volatile 的目的是向编译器指示变量可能会在编译器生成的代码之外发生更改(而不是它更改)。当变量引用硬件寄存器或在线程、进程甚至处理器或处理器内的内核之间共享的内存时,它通常用于确保正确的行为。它还可以用于防止“优化”所需的代码(例如空的忙等待循环计数器)。在您的示例(或者更确切地说是我对它的修订)中,a 没有引用任何此类实体,因此代码将按预期运行,但效率可能不如其他情况。

    【讨论】:

    • int square(volatile int *ptr) { int a,b; a = *ptr; b = *ptr;返回 a * b; }
    • 并调用 Square(&a)....现在这会给我不同的值...我希望我是对的...我是吗??
    • 我认为我对 thjis 的回答很明确;为什么你认为会有所不同?如果没有改变全局a 的值,那么该值不会改变!在您的情况下,a 没有显式初始化,而是static,因此答案始终为零。
    • 很好的答案,但并不完全正确。编译器可能永远不会优化该函数,因为读取 volatile 变量是一种副作用。根据 C99 5.1.2.3,编译器只能优化代码,如果它可以确保没有副作用发生。在某些硬件上,CPU 寄存器的(易失性)读取访问可能会清除/设置某些标志,这意味着读取本身实际上会修改外部源。并且某些硬件可能需要在使用之前进行虚拟读取等。由于 OP 将他们的帖子标记为嵌入式,因此这一点尤为重要。
    【解决方案2】:

    全局作用域volatile int a 和函数作用域int a 参数之间没有关系。它们是完全独立的,函数内部对a 的任何引用都是指int a 参数。 volatile int a 从未在此程序中使用过。

    如果您将 volatile int a 作为参数传递给函数,则不会有任何区别,因为该 a 的值将被读取一次并复制到函数的 a 参数,这不是本身volatile

    【讨论】:

    • 所以,你的意思是,如果我有一个函数 b(volatile int a) 作为参数......它会有所作为.....??
    • 那将是最不寻常的。你想完成什么?
    • 我想说如果我声明函数 b(volatile int a).. 然后值被复制但如果值是 volatile 是否告诉编译器复制其内存位置.. . 这是我的困惑。
    • 如果我创建函数 b(volatile int *a) 将返回不同的值...只是想澄清一下...
    【解决方案3】:

    它总是返回一个正方形,除非发生整数溢出,在这种情况下行为是未定义的。 volatile 完全不相关(我称之为红鲱鱼)但是因为全局 volatile 变量 a 在读取另一个 a 时甚至不在范围内.函数参数a 隐藏了全局变量,并且由于它具有自动存储持续时间并且它的地址永远不会被占用,因此它完全不受任何形式的外部修改。

    当然,仍然有很多方法可以通过调用未定义的行为并发现返回值不是正方形来破坏程序状态。 UB就是这么好玩..

    【讨论】:

      猜你喜欢
      • 2020-02-21
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-03-21
      • 2018-01-28
      • 1970-01-01
      相关资源
      最近更新 更多