2

考虑以下程序:

#include <cstdio>
int main()
{
    int printf=9;
    std::printf("%d",printf);
}

在变量声明中使用内置函数名作为标识符是否可以?这是定义明确的程序吗?我的意思是上述程序的行为是否定义明确?我很想知道 C++ 标准是否允许使用标准函数名作为变量的标识符

4

5 回答 5

5

它的格式是正确的,因为std::printfnor ::printf(也可能已由<cstdio>! 声明)在与您的整数相同的范围内声明,因此在块的持续时间内自动优先。

[C++14: 3.3.1/1]: [..]要确定声明的范围,有时参考声明的潜在范围很方便。除非潜在范围包含另一个同名声明,否则声明的范围与其潜在范围相同。在这种情况下,内部(包含)声明性区域中的声明的潜在范围被排除在外部(包含)声明性区域中的声明范围之外。

例如,您通常无法在命名空间范围内执行此操作

它的定义很好,因为标准库中的实体名称不是固有的保留名称:

[C++14: 2.11/3]:此外,某些标识符保留供 C++ 实现和标准库 (17.6.4.3.2) 使用,不得以其他方式使用;不需要诊断。

[C++14: 17.6.4.3.2/1]:某些名称和函数签名集始终保留给实现:

  • 每个包含双下划线_ _或以下划线后跟大写字母 (2.12) 的名称都保留给实现以供任何使用。
  • 每个以下划线开头的名称都保留给实现用作全局名称空间中的名称。
于 2015-11-22T15:20:15.343 回答
4

是的,这是定义明确的行为。您正在创建一个名为 printf 的 int,并且您的范围内当前没有任何名为 printf 的内容。在标准范围内有一个名为 printf 的东西,可能在全局范围内,但在本地范围内定义的 int printf 自动优先。

于 2015-11-22T15:08:06.503 回答
3

技术上允许这样做。在全局命名空间中保留了一些名称,但在函数内部,您的变量名无论如何都不会在函数外部可见,因此不是问题。

使用它是一个糟糕的主意。

请注意,这种方法可能存在问题。例如:

#define NULL 0

int main()
{
     int NULL = 42;
     printf("%d", NULL);
}

不允许,因为NULL它是一个宏,而不是一个范围标识符。

编辑:我要补充一点,这printf不是“内置功能”。它是一个“C 标准库函数”。bultin 函数类似于__builtin_sin,编译器“知道”以便对其进行优化。请注意,内置函数通常使用“保留名称”,以避免始终与现有库和用户定义的名称发生冲突。

于 2015-11-22T15:06:04.763 回答
0

这样做是可以的。因为你定义的变量int printf不属于命名空间stdas printf,定义在cstdio. 因此,您的程序名称实际上没有冲突。

但是,如果您声明

using namespace std;

在你的程序之前,而不是std::在你的程序中使用,那么如果你不小心就会导致问题。通常,当存在名称冲突时,编译器会使用定义在最小范围内的名称。所以如果你有这样的程序:

#include<cstdio>
using namespace std;

int main()
{
    int printf = 42;
    printf("%d", printf);
}

编译器将返回

error: ‘printf’ cannot be used as a function

这是因为在这个程序中,printf被定义为一个int函数范围内的函数,以及一个int printf( const char* format, ... )全局范围内的函数。由于函数作用域小于全局作用域,因此在函数中int main()printf被解释为int而不是函数。int不可调用,因此出现错误消息。

于 2015-11-22T15:34:22.313 回答
0

相对于标准库中的标识符,C++ 标准仅规定了标识符的以下重构

3 此外,一些标识符保留供 C++ 实现和标准库 (17.6.4.3.2)使用,不得以其他方式使用;不需要诊断。

和(17.6.4.3.2 全局名称)

1 某些名称和函数签名集始终保留给实现:

— 每个包含双下划线 _ _ 或以下划线后跟大写字母 (2.12) 的名称都保留给实现以供任何使用。

— 每个以下划线开头的名称都保留给实现用作全局名称空间中的名称。

因此,您可以使用与标准函数名称一致的标识符。

另一方面,这会使代码的读者感到困惑并导致歧义。考虑到标准允许编译器将标准 C 函数名称放在全局命名空间中。

于 2015-11-22T15:12:27.617 回答