在 C++ 中使用标准库函数名作为标识符是否有效?

is it valid to use standard library function name as identifier in C++?

考虑以下程序:

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

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

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

使用这个是个糟糕的主意。

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

#define NULL 0

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

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

编辑:我想补充一点 printf 不是 "built in function"。这是一个"C standard library function"。 bultin 函数类似于 __builtin_sin,编译器 "knows about" 以便对其进行优化。请注意,内置函数通常使用 "reserved names",以避免始终与现有库和用户定义的名称发生冲突。

是的,这是定义明确的行为。您正在创建一个名为 printf 的 int,而您的作用域中当前没有任何名为 printf 的内容。在标准作用域和可能在全局作用域中有一个名为 printf 的东西,但是在局部作用域中定义的 int printf 自动优先。

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

3 In addition, some identifiers are reserved for use by C++ implementations and standard libraries (17.6.4.3.2) and shall not be used otherwise; no diagnostic is required.

和(17.6.4.3.2 全局名称)

1 Certain sets of names and function signatures are always reserved to the implementation:

— Each name that contains a double underscore _ _ or begins with an underscore followed by an uppercase letter (2.12) is reserved to the implementation for any use.

— Each name that begins with an underscore is reserved to the implementation for use as a name in the global namespace.

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

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

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

[C++14: 3.3.1/1]: [..] To determine the scope of a declaration, it is sometimes convenient to refer to the potential scope of a declaration. The scope of a declaration is the same as its potential scope unless the potential scope contains another declaration of the same name. In that case, the potential scope of the declaration in the inner (contained) declarative region is excluded from the scope of the declaration in the outer (containing) declarative region.

例如,you generally wouldn't be able to do this at namespace scope.

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

[C++14: 2.11/3]: In addition, some identifiers are reserved for use by C++ implementations and standard libraries (17.6.4.3.2) and shall not be used otherwise; no diagnostic is required.

[C++14: 17.6.4.3.2/1]: Certain sets of names and function signatures are always reserved to the implementation:

  • Each name that contains a double underscore _ _ or begins with an underscore followed by an uppercase letter (2.12) is reserved to the implementation for any use.
  • Each name that begins with an underscore is reserved to the implementation for use as a name in the global namespace.

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

但是,如果您声明

using namespace std;

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

#include<cstdio>
using namespace std;

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

编译器会return

error: ‘printf’ cannot be used as a function

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