Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/70.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C原型范围_C_Prototype_Scope_Designer_Specifications - Fatal编程技术网

C原型范围

C原型范围,c,prototype,scope,designer,specifications,C,Prototype,Scope,Designer,Specifications,我知道了 声明 参数列表中的标识符 函数原型中的声明 (不是函数定义的一部分), 标识符具有功能原型 作用域,它终止于 函数声明器 请参阅下面提到的C程序 void fn (struct st {int a;} a, struct st b) ; struct st obj ; 编译器会立即发出错误,因为“obj”大小未知(或)struct st不是“type”。这是正确的!结构“struct st”的声明在原型声明处结束 我相信prototype有这个限制,因为我们也可以在prototyp

我知道了

声明 参数列表中的标识符 函数原型中的声明 (不是函数定义的一部分), 标识符具有功能原型 作用域,它终止于 函数声明器

请参阅下面提到的C程序

void fn (struct st {int a;} a, struct st b) ;

struct st obj ;
编译器会立即发出错误,因为“obj”大小未知(或)struct st不是“type”。这是正确的!结构“struct st”的声明在原型声明处结束

我相信prototype有这个限制,因为我们也可以在prototype声明中使用一些变量名。这些名称可能与同一范围内的变量冲突(与函数原型的名称相同)。如下图所示

void fn (int a) ;
int a ;
void fn(int a);
int a;
因此,为了允许上述声明,原型的范围是有限的。(如果我错了,请纠正我)


但是,对于原型声明,参数变量名没有任何用处。那么,为什么它是“范围狭窄的”?参数变量名的意义是什么?语言设计者(或)规范对此有何想法?

参数名称可以帮助记录参数的使用

考虑内存设置功能:

void mem_set(void *, int, int);

void mem_set(void *buffer, int value, int nbytes);
哪个更容易理解


编写的结构类型声明是函数原型的本地声明。正如您可能知道的(现在,如果不是以前),您需要在原型范围之外定义类型,以便成功地使用它。也就是说,你必须写:

struct st {int a;};
void fn(struct st a, struct st b);
你说:

我相信prototype有这个限制,因为我们也可以在prototype声明中使用一些变量名。这些名称可能与同一范围内的变量冲突(与函数原型的名称相同)。如下图所示

void fn (int a) ;
int a ;
void fn(int a);
int a;
因此,为了允许上述声明,原型的范围是有限的。(如果我错了,请纠正我)

带有'-Wshadow'的GCC可能会警告隐藏全局变量'a'的参数'a'-它肯定会在函数定义中发出警告,也可能在函数声明中发出警告。但这不是强制性警告;所编写的代码是合法的C语言-尽管由于阴影的存在有些可疑


在“C为什么限制(阻止)您在参数列表中声明类型”的评论中有一个冗长的讨论,其中的子文本“因为C++允许您这样做”:

评论 如果允许/**/,程序员有责任(根据编码实践)添加关于语言使用的适当注释。我相信除了为评论提供帮助之外,还必须有其他的“东西”Ganesh Gopalasubramanian

好吧,相信吧。与C++的兼容性是其余的原因,并且在那里增加了参数名以提高可读性。请参阅Stroustrup的“C++的设计和发展”。请注意,原型中参数的名称不是接口的一部分-请参阅关于按名称而不是位置提供参数的讨论乔纳森·莱夫勒


我相信OP提出的问题是“拥有功能原型范围到底有什么意义?”。不幸的是,你的回答并没有说明问题。坦白说,我也不知道。如果他们只想将命名参数声明的范围(在非定义声明中)限制为OP猜测,那么它们可以在不引入范围的情况下完成它(例如,在C++中这样做)。安德烈

@AndreyT:在函数定义中,参数是函数体的局部变量(不再可能通过函数体最外层的块中的局部变量隐藏参数)。原型在逻辑上在函数内部声明了一个类型,因此应该按照定义的范围来定义-因此,仅在函数原型中定义的类型不能在函数外部使用,不能调用的函数对任何人都没有什么好处乔纳森·莱夫勒

@Jonathan Leffler:您似乎在解释为什么允许使用参数名(“与C++兼容”-OK)。我想知道的是引入“功能原型范围”的基本原理。为什么他们认为有必要引入这样一个范围?C++并不是这样做的。C++中没有函数原型作用域。安德烈

@叶安德烈!我们都在同一条船上溺水:)–甘尼什·戈帕拉苏布拉曼尼安

反例 这说明C++是这样做的。

错误发生在警告/错误的默认级别以及迂腐的级别


因此,在这种情况下,说“C行为像C++”是公平和准确的。你能用计数器来演示如何在C++中定义函数原型中的一个类型,指定哪个C++编译器和平台允许它?

两个-让我们在函数原型中有参数名称的三个明显的原因:

  • 名称表示每个参数的用途
  • 通过名称,您可以更容易地在API文档中引用参数(例如在Doxygen中)
  • 您可以更容易地从定义生成原型(剪切和粘贴,或自动化)
我会附和你说的话。将标识符限定在原型的范围内是很有用的。比没有它们更有用。此外,它允许原型遵循与函数声明相同的语法,从语言设计的角度以及从实现者的角度来看,这可能很好

我不认为这是您的建议,但为了完整性,让这些标识符的范围超出原型范围将毫无意义,并可能导致问题

事实上,你可以在原型中声明一些在原型之外没有用的东西,这是一个缺点(我猜),但它是无害的。解决办法是“不要那样做”。我不知道让你申报有什么隐藏的问题
struct {
    int obj;
};
int f(void *);
int f(struct dummy *);