【问题标题】:Scope of a variable and function name变量和函数名的范围
【发布时间】:2015-08-25 07:53:44
【问题描述】:

这是我的代码:

#include <stdlib.h>
#include <stdio.h>

int sum(int,int);

int sum(int x, int size) {
    int sum = 0;
    printf("%p\n", &x);
    printf("%p\n", &size);
    printf("%p\n", &sum);
    sum(x,size);
    return 0;
}

int main() {
    sum(2,4);
    return 0;
}

我得到的错误是:

hello.c:11:5: error: called object type 'int' is not a function or function pointer
sum(x,size);
~~~^

【问题讨论】:

  • 你真的想要一个变量和一个函数同名吗?
  • @SouravGhosh 为什么这是个问题?
  • 不管怎样,打电话给sum(x, size);时你觉得你在做什么?没有什么可以停止递归,所以你的程序会整天循环(至少直到它达到最大堆栈)
  • @Eregrith 我只是在玩堆栈帧并尝试学习。
  • @KorayTugay 因为正如编译器告诉你的那样,你的变量sum 不是函数指针,所以你不能做sum(x, size):。但是,它可能是一个函数指针,指向另一个函数,因此调用sum(x, size);会调用那个函数而不是你的sum()函数。

标签: c scope


【解决方案1】:

如果您为同一名称空间中的不同实体定义了两个单独的同名标识符,它们可能会重叠。 C11 标准,第 §6.2.1 章规定,

如果一个标识符指定了两个不同的同名实体 空间,范围可能重叠......

参考脚注:为什么在这种情况下,sums 都在同一个命名空间中

所以,一旦你重新定义其他类型的标识符,

....如果是这样,一个实体的范围(内部范围)将结束 严格在其他实体的范围之前(外部范围)。在内部范围内,标识符指定在内部范围内声明的实体;在外部范围内声明的实体在内部范围内隐藏(不可见)。

这意味着,在您的情况下,本质上,在函数 sum() 内部,当您定义 int sum 时,基本上是在隐藏 函数 sum。重新定义后,sum 是一个int 类型的标识符,在那个函数范围中。因此,在函数sum() 内,您不能调用sum(),因为它现在是int 类型。

但是,FWIW,在main()(或者更确切地说,在sum() 本身之外)对sum() 的调用应该是有效的,因为此时,int sum 将超出范围。

解决方案:int sum 变量名更改为其他名称。

感谢 @pmg 的更正

编辑:

in the other answer by @juanchopanza 所述,在更改shadowing 变量名称后,您的程序将编译,一旦您运行它,您将面临infinite recursion,因为unconditionalsum() 内部调用sum()。您需要添加一些 break 条件来结束(return from)递归。


脚注:

参考C11第6.2.3章命名空间,我们可以说,有单独的命名空间 对于各种类别的标识符,例如1) 标签名称 2) 结构、联合和枚举的标签,3) 结构或联合的成员和 4) 所有其他标识符。

因此,在这种特殊情况下,函数 sum()int sum 定义将驻留在同一名称空间中,用于 sum() 函数范围

【讨论】:

  • 是的,您可以在不同的时间为不同的事物使用相同的标识符。
  • 重新定义sum(从int (*)(int, int)int)后就不能使用前面的意思了。不过重新定义没问题。
  • 6.2.1 Scopes of identifiers有关。 “对于标识符指定的每个不同实体,标识符仅在称为其范围的程序文本区域内可见(即可以使用)。由相同标识符指定的不同实体具有不同的范围,或者位于不同的名称空间。”
  • 呵呵,对于这个问题,范围比名称空间更重要。我会交换你答案的两个部分(或者可能删除一个名称空间)-1 更改为 +1
  • 按原样,基本上只是无偿的标准行情+最后两段。
【解决方案2】:

变量和函数同名,这就是为什么它同时取消引用函数和变量,这是错误的原因

【讨论】:

    【解决方案3】:

    范围很重要

    1. 这里的函数名sum具有全局作用域。
    2. 变量sum 是本地变量并且具有本地范围。

    3. 冲突是因为在sum() 内部调用sum()。现在在函数 sum() 内部,您有 2 个同名和不同类型的对象,因此出现错误。

    如果你有类似的东西

    int  sum()
    {
       int sum = 0;
       sum = 10;
       printf("%d\n",sum);
    }
    

    那么您的代码就可以了。由于变量 sum 是函数 sum() 的本地变量,并且它是函数 sum() 中唯一具有该名称的对象。

    与其担心这个不如重命名变量并确保变量名和函数名不同

    【讨论】:

      【解决方案4】:

      只需将 sum 函数 中的变量 sum 名称更改为 total

      #include <stdlib.h>
      #include <stdio.h>
      
      int sum(int,int);
      
      int sum(int x, int size) {
          int total = 0;
          printf("%p\n", &x);
          printf("%p\n", &size);
          printf("%p\n", &total);
          sum(x,size);
          return 0;
      }
      
      int main() {
          sum(2,4);
          return 0;
      }
      

      【讨论】:

        【解决方案5】:

        你需要把int sum = 0改成int y = 0,你的程序也会因为你没有在sum(x,sum)停止递归而中断

        【讨论】:

          【解决方案6】:

          你在这里改变了sum的含义:

          int sum = 0;
          

          从现在开始,在它被声明的范围内,sum 是一个int,这就变成了废话:

          sum(x,size); /* Wat? sum is an int!!! */
          

          不要这样做,您的代码将编译。编译后,您可以担心停止递归。

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 2011-10-27
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2021-12-18
            • 2010-12-19
            相关资源
            最近更新 更多