C:通过引用传递自动变量

时间:2017-09-22 09:33:50

标签: c cpu-registers

我遇到了一段目前工作正常的代码,但在我看来,它的未定义行为可能会在将来引入一个错误。

伪代码:

void OpertateLoad(int load_id)
{
   int value = 0;

   /* code to calculate value */

   SetLoadRequest(load_id,&value);

   /*some processing  not involving value**/

}

void SetLoadRequest(int load_id, int* value)
{
   /**some processing**/
   LoadsArray[load_id] = *value; 
   /**some processing**/ 
}

在我的理解中,C编译器不保证将存储Auto个变量。它可以是堆栈/寄存器(如果可用并且适合处理)。

我怀疑如果编译器决定将value存储到通用寄存器中,那么SetLoadRequest函数可能会引用错误的数据。

我说得对吗?或者我在思考它?

我正在为IARARM处理器使用ARM CORTEX M-4编译器。

----------:编辑:----------

答案总结一下"无论变量存储在何处,编译器都将确保数据在调用之间保持不变。

只是想确认一下:如果某个函数返回本地自动变量的地址并且调用者正在取消引用它,这种行为也是如此吗?'。

如果否,那么C标准中是否有任何保证两种情况下的行为?或者正如我之前所说的未定义的行为?

4 个答案:

答案 0 :(得分:9)

你正在思考它。编译器知道,如果value在寄存器中,则必须在将指向该内存的指针传递给SetLoadRequest之前将其存储到内存中。

更一般地说,根本不要考虑堆栈和寄存器。语言说有一个变量(不说它是如何实现的),并且你可以获取它的地址并在另一个函数中使用它来引用变量。所以你可以!

该语言还说当离开块时局部变量不再存在,因此该权限不会扩展到返回指向局部变量的指针(如果调用者对指针执行任何操作,则会导致未定义的行为)。

答案 1 :(得分:3)

  

我正在思考它?

的!

编译器会处理这个问题。如果它将它存储在寄存器中,它将知道如何处理它(带有内存负载)。

答案 2 :(得分:1)

据我了解,value的范围是OpertateLoad的主体。但是,SetLoadRequest会指定指向的值,因此会复制value的实际值。不涉及未定义的行为。

答案 3 :(得分:1)

C11标准草案n1570:

  

6.2.4对象的存储持续时间

     
    

6对于没有可变长度数组类型的对象,其生命周期从entry进入与其关联的块,直到该块的执行以任何方式结束。 (输入一个封闭的块或调用一个函数暂停,但不会结束,执行当前块。)如果以递归方式输入该块,则为新的实例     每次都创建对象。对象的初始值是不确定的。如果     为对象指定初始化,每次声明或执行时都会执行     在块的执行中达到复合文字;否则,价值变为     每次达到声明时都不确定。