简体   繁体   中英

Why can I call a function without an argument when it is defined with one argument in C?

I know I shouldn't define any function like that. But I like to try the limits, so I wrote some code like that:

#include <stdio.h>

void func(a)
{
    printf("%d\n", a);
}

int main()
{
    func();
    func();
    func();
    return 0;
}

I really wasn't looking for any outputs, but the one I saw was very odd.

The output is

1
0
0

Why? Where did those 1's or 0's came from?

(I'm using CygWin & Eclipse duo btw.)

Your program is invalid.

gcc 8.2 complains:

$ gcc -Wall -Wextra -pedantic -std=c17 t.c
test.c: In function ‘func’:
test.c:3:6: warning: type of ‘a’ defaults to ‘int’ [-Wimplicit-int]
 void func(a)

Since C99, all functions require their arguments to have valid types (there used to be "implicit int" rule - function argument/return types are assumed int if not specified). But your program is not valid in C89 either because you don't actually pass any argument. So what you see is the result of undefined behaviour .

When you don't define type for the variables int is taken as default type by compiler.

warning: type of 'a' defaults to 'int' [-Wimplicit-int]
 void func(a)

Hence it is printing indeterminate values which int a contains.

Prior to the 1989 ANSI C standard, the only way to define a function in C did not specify the number and types of any parameters. (This old version of the language is called "K&R C", since it's described in the first edition of The C Programming Language by Kernighan and Ritchie.) You're using an old-style function definition:

void func(a)
{
    printf("%d\n", a);
}

Here a is the name of the parameter. It is implicitly of type int , but that information is not used in determining the correctness of a call to func .

C89 added prototypes , which allow you to specify the types of parameters in a way that is checked when the compiler sees a call to the function:

void func(int a)
{
    printf("%d\n", a);
}

So in the 1989 version of the C language, your program is legal (in the sense that there are no errors that need to be diagnosed at compile time), but its behavior is undefined. func will probably grab whatever value happens to be in the location in which it expects the caller to place the value of the argument. Since no argument was passed, that value will be garbage. But the program could in principle do literally anything.

The 1999 version of the language dropped the "implicit int " rule, so a is no longer assumed to be of type int even with the old-style definition.

But even the latest 2011 version of C hasn't dropped old-style function definitions and declarations. But they've been officially obsolescent since 1989.

Bottom line: Always use prototypes. Old-style function definitions and declarations are still legal, but there is never (or very rarely) any good reason to use them. Unfortunately your compiler won't necessarily warn you if you use them accidentally.

(You're also using an old-style definition for main . int main() is better written as int main(void) . This is less problematic than it is for other functions, since main is not normally called, but it's still a good habit.)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM