函数声明与原型的可选(K&R)C语法
这个函数声明与原型的可选(K&R)C语法,c,function,function-declaration,kernighan-and-ritchie,function-definition,C,Function,Function Declaration,Kernighan And Ritchie,Function Definition,这个C语法有什么有用之处-使用“K&R”风格的函数声明 int func (p, p2) void* p; int p2; { return 0; } 我能在2010年Beta版的Visual Studio中写这篇文章 // yes, the arguments are flipped void f() { void* v = 0; func(5, v); } 我不明白。这种语法有什么意义?我可以写: int func (p, p2) int
C
语法有什么有用之处-使用“K&R”风格的函数声明
int func (p, p2)
void* p;
int p2;
{
return 0;
}
我能在2010年Beta版的Visual Studio中写这篇文章
// yes, the arguments are flipped
void f()
{
void* v = 0;
func(5, v);
}
我不明白。这种语法有什么意义?我可以写:
int func (p, p2)
int p2;
{
return 0;
}
// and write
int func (p, p2)
{
return 0;
}
它似乎只指定了它使用的参数数量和返回类型。我想没有类型的参数有点酷,但是为什么允许它和函数声明符后面的int-name
?真奇怪
这仍然是标准的C吗?这只是一种旧语法,它早于您可能更熟悉的“ANSIC”语法。它通常被称为“”
编译器支持它的完整性,当然也支持它能够处理旧的代码库。这只是一种旧语法,它早于您可能更熟悉的“ANSI C”语法。它通常被称为“”
编译器支持它的完整性,当然也支持它能够处理旧的代码库。这是非常古老的K&R C语法(早于ANSI/ISO C)。现在,您不应该再使用它了(因为您已经注意到它的主要缺点:编译器不会为您检查参数类型)。在您的示例中,参数类型实际上默认为
int
当时,使用这种语法时,有时会发现如下函数
foo(p, q)
{
return q + p;
}
这实际上是一个有效的定义,因为
foo
、p
和q
的类型默认为int
,这是非常古老的K&R C语法(在ANSI/ISO C之前)。现在,您不应该再使用它了(因为您已经注意到它的主要缺点:编译器不会为您检查参数类型)。在您的示例中,参数类型实际上默认为int
当时,使用这种语法时,有时会发现如下函数
foo(p, q)
{
return q + p;
}
这实际上是一个有效的定义,因为
foo
、p
和q
的类型默认为int
,这是C没有函数原型时的遗留。当时,(我认为)函数被假定为返回int
,它的所有参数都被假定为int
。没有对函数参数进行检查
在当前的C语言中使用函数原型会更好。您必须在C99中使用它们(C89仍然接受旧语法)
C99需要声明函数(可能没有原型)。如果您从头开始编写新函数,则需要提供声明。。。让它也成为一个原型:你不会丢失任何东西,并从编译器那里获得额外的检查。这是C没有函数原型时的遗留问题。当时,(我认为)函数被假定为返回
int
,它的所有参数都被假定为int
。没有对函数参数进行检查
在当前的C语言中使用函数原型会更好。您必须在C99中使用它们(C89仍然接受旧语法)
C99需要声明函数(可能没有原型)。如果您从头开始编写新函数,则需要提供声明。。。把它也做成一个原型:你不会丢失任何东西,并从编译器那里获得额外的检查。这是C在1989年标准化之前的原始K&R语法。C89引入了函数原型,从C++中借用,并禁止了K&R语法。没有理由在新代码中使用它(也有很多理由不使用)。这是C在1989年标准化之前的原始K&R语法。C89引入了函数原型,从C++中借用,并禁止了K&R语法。在新代码中没有理由使用它(也有很多理由不使用)。您要问的问题实际上是两个问题,而不是一个。到目前为止,大多数回复都试图用一个通用的“这是K&R风格”的答案来覆盖整个问题,而实际上只有一小部分与所谓的K&R风格有关(除非您以某种方式将整个C语言视为“K&R风格”) 第一部分是函数定义中使用的奇怪语法 它实际上声明了一个函数
foo
,该函数接受未知类型的未指定数量的参数。你可以称之为
foo(2, 3);
作为
j = foo(p, -3, "hello world");
等等(你明白了)
只有带有正确参数的调用才会“起作用”(意味着其他调用会产生未定义的行为),但确保其正确性完全取决于您。编译器不需要诊断错误的参数,即使它神奇地知道正确的参数类型及其总数
实际上,这种行为是C语言的一个特点。一个危险的,但仍然是一个特点。它允许你做这样的事情
int foo();
void foo(int i);
void bar(char *a, double b);
void baz(void);
int main()
{
void (*fn[])() = { foo, bar, baz };
fn[0](5);
fn[1]("abc", 1.0);
fn[2]();
}
i、 e.在一个“多态”数组中混合不同的函数类型,而不使用任何类型转换(虽然这里不能使用可变函数类型)。同样,这种技术的固有危险是非常明显的(我不记得曾经使用过它,但我可以想象它在哪里有用),但这毕竟是C
最后,将答案的第二部分链接到第一部分的位。当您创建K&R风格的函数定义时,它不会为函数引入原型。就函数类型而言,您的func
定义将func
声明为
int func();
func(1, 2, 3, 4, "Hi!");
i、 e.既不声明类型,也不声明参数总数。在你原来的帖子中,你说“…它似乎指定了它使用了多少个参数…”。从形式上讲,它不是!在定义了两个参数K&R-stylefunc
之后,仍然可以按如下方式调用func
int func();
func(1, 2, 3, 4, "Hi!");
而且不会有任何违反约束的情况。(通常,高质量的编译器会给您一个警告)
此外,一个有时被忽视的事实是
int f()
{
return 0;
}
也是一个K&R样式的函数定义,它不支持