您可以在块范围内或在结构、联合或枚举的标记的名称空间中或在结构和联合成员的名称空间中或在函数原型范围内使用名称 scanf 和 printf。
在块范围内声明的名称如scanf 或printf 将隐藏在文件范围内声明的相应函数名。但您不得在文件范围内重新声明这些名称。
这是一个演示程序。
#include <stdio.h>
int main(void)
{
int printf = 10;
{
int *scanf = &printf;
extern int printf(const char * restrict format, ...);
printf( "printf = %d\n", *scanf );
}
return 0;
}
它的输出是
printf = 10
这是另一个演示程序,显示了使用名称 printf 的其他方式
#include <stdio.h>
struct printf
{
int printf;
};
void f( int printf );
void f( int x )
{
printf( "x = %d\n", x );
}
int main(void)
{
struct printf printf = { .printf = 10 };
f( printf.printf );
return 0;
}
程序输出是
x = 10
这样使用 printf 这个名字自然只会让代码的读者感到困惑。
至于以下划线开头的名称则根据 C 标准(7.1.3 保留标识符)
1 每个标头都声明或定义其列于其中的所有标识符
相关的子条款,并且可选地声明或定义标识符
在其相关的未来图书馆方向子条款中列出和
始终保留用于任何用途或用作
文件范围标识符。
——所有以下划线开头的标识符
大写字母或其他下划线始终保留给任何
使用。
因此,您不能在文件范围或块范围内使用此声明中的标识符
int __;
名称由实现保留。
至于你的代码sn-p中的这个声明
int _;
那么因为它没有文件范围(它有一个块范围),那么在声明中使用的标识符(使用这个标识符的声明)是有效的。
但是,如果您将在文件范围内声明名称,例如
int _;
int main( vpid )
{
//...
}
那么这样的标识符声明将是无效的。
你也不能在文件范围内使用这样的标识符作为标签名。例如
struct _
{
int x;
};
int main( void )
{
//...
}
——所有以下划线开头的标识符总是被保留
在普通和标签中用作具有文件范围的标识符
命名空间。