【问题标题】:How to copy local variable to global variable if both have the same names in C without using a third variable?如果两者在C中具有相同的名称而不使用第三个变量,如何将局部变量复制到全局变量?
【发布时间】:2013-08-14 18:36:25
【问题描述】:

我有一个同名的全局变量和一个局部变量。我可以将局部变量复制到全局变量(分配)而不首先将全局变量的值分配给某个临时变量(使用extern)然后将临时变量分配给全局变量吗? 我需要做这样的事情:

#include<stdio.h>
int myVariable = 50;
void myFunction()
{
    int myVariable;
    myVariable /*global*/ = myVariable /*local*/;
}

C 中有什么方法可以做到这一点(不使用临时变量(或数组中的指针))?我发现在 C++、Java 或 C# 中使用 this、super、base 等关键字是可能的,但在 C 中找不到解决方案。

我已经提到How can I access a shadowed global variable in C?

【问题讨论】:

  • 是的,这是可能的。只是不要在本地范围内使用myVariable
  • @Macattack,不完全是重复的。
  • @SachinJoseph 抱歉,我还没看就跳了。我希望您只是出于理论上的目的。
  • @EdS.,这是一个可信的问题。这是其他语言直接支持的功能。

标签: c


【解决方案1】:

在 C99 中,无法指定要使用的变量/常量的特定范围。引用变量/常量时,它会自动引用最内层的作用域。

来自 C99 标准6.2.1.4

...如果一个标识符在同一个名称空间中指定了两个不同的实体,则范围可能会重叠。如果是这样,一个实体的范围(内部范围)将是另一个实体范围(外部范围)的严格子集。在内部范围内,标识符指定在内部范围内声明的实体;在外部范围内声明的实体在内部范围内隐藏(不可见)...

那么我该如何解决这个问题?

简单,更改最内层范围变量的名称:)

【讨论】:

    【解决方案2】:

    这太可怕了,但在 GNU C 中,你可以这样做:

    * ({ extern int myVariable; &myVariable; }) = myVariable;
    

    想想看,它可以在标准 C 中使用辅助函数:

    static int * GlobalMyVariable(void) { return &myVariable; }
    …
    *GlobalMyVariable() = myVariable;
    

    当然,您要求不提供临时变量,并且这不使用临时变量,但从表面上看,它确实为您的可执行文件添加了“东西”。但是,我通过优化编译了一个简单的用法,辅助函数在生成的汇编代码中完全消失了。因此,当编译器正确优化时,它相当于没有额外的代码或数据。

    【讨论】:

    • +1 我尝试了这个令人难以置信的代码,它确实有效:) 链接:ideone.com/Kmxd1s
    • 第二个解决方案对我来说看起来不错,不使用第三个变量。您在下面启发了我的方法。
    【解决方案3】:

    结构体是否算作另一个变量?

    #include<stdio.h>
    
    struct Global {
        int myVariable;
    } g;
    
    void myFunction()
    {
        int myVariable = 50;
        g.myVariable /*global*/ = myVariable /*local*/;
    }
    

    这应该像你问的那样做。

    【讨论】:

    • (+1),因为这是一个巧妙的解决方法。但是,(-1)因为它隐含地不是 OP 想要做的——如果有的话,这比制作一个临时变量/常量更有效。
    • +1 我见过几次类似的解决方法是将每个全局变量的名称都以“g_”开头。
    【解决方案4】:

    添加一个全局常量 int 指针。

    OP:如果在 C 中两者具有相同的数组名称而不使用第三个变量,如何将局部变量复制到全局变量?
    我作弊了,没有使用第三个变量,而是一个常数。 (我偷偷溜进门了吗?)

    OP:没有先将全局变量的值分配给某个临时变量(使用 extern),然后将临时变量分配给全局变量?
    似乎通过了该测试 - 未使用临时变量。

    OP:C 中的某种方式来做到这一点(不使用临时变量(或在数组的情况下使用指针))?
    好吧,它不使用临时的,因为全局变量是永久性的。而且它没有通过数组使用指针。它使用指针。

    int myVariable = 50;
    int *const myVariableAddress = &myVariable;
    
    void myFunction() {
        // Could be here instead with 
        // static int *const myVariableAddress = &myVariable;
        {
        int myVariable;
        *myVariableAddress = myVariable /*local*/;
        }
    }
    

    【讨论】:

      【解决方案5】:

      这可行,但代码需要在共享对象中,或者程序需要以一种让可执行文件看到自己的全局符号的方式编译(在 GCC 中,您使用-rdynamic 标志):

      int myVariable = 50;
      
      void myFunction () {
          int myVariable = 10;
          *(int *)dlsym(0, "myVariable") = myVariable;
      }
      

      【讨论】:

        【解决方案6】:

        1) 使用返回值:

        #include<stdio.h>
        int myVariable = 50;
        
        int myFunction1()
        {
            int myVariable;
            return  myVariable;
        }
        

        2) 使用指针:

        void myFunction2( int * pp)
        {
            int myVariable;
            *pp = myVariable;
        }
        

        用法:

        int main(void) {
        
        myVariable = myFunction1();
        
         /* or ... */
        myFunction2 ( &myVariable);
        
        return 0;
        }
        

        }

        【讨论】:

        • (-1),我不理解任何示例。在第一个中,您将收到一条错误消息“到达非空函数的末尾”,第二个没有变化,但参数类型和用法不清楚,因为我不知道前两点是做什么的......
        • 我还在忙着编辑。 (理解这个对我来说没有多大意义的问题)两个版本都没有使用任何额外的变量(指针可以看作是一个变量,但实际参数是一个指针表达式,并且这个“变量”一旦函数消失已返回。) – wildplasser 33 秒前
        【解决方案7】:

        您正在做的是“隐藏”全局变量。为了在本地块中取消阴影,请在其自己的嵌套块中使用 extern 声明它。

         void myFunction()
         {
        
          int myVariable
           {
             extern int myVarible; 
             //modify myVariable global here;
        
            }
           //modify myVariable localhere
         }
        

        【讨论】:

        • 这需要一个临时变量,不满足问题。
        • 不是临时变量,是全局变量。
        • 他的问题是询问如何从最内层范围复制到同名的最外层范围变量。您的解决方案不能满足这一点(但它确实解释了变量阴影——不是他所要求的)。
        • 如果没有额外的变量,你怎么能myVariable /*global*/ = myVariable /*local*/
        • @MM。这正是我的问题
        猜你喜欢
        • 2011-08-15
        • 2014-04-24
        • 2021-01-19
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2016-04-06
        • 2011-01-12
        相关资源
        最近更新 更多