Why is implicit declaration of gets() not allowed in C99? - c

I am starting to learn programming in C language the book I am refering to code shows some source code with gets() and my IDLE recognises it as well. But still while compiling it, my compiler doesn't agree with it.
Can anyone help me out? I am using gets() in the main function and using clang as the compiler.

Expanding on my comment:
First, never use gets(), for any reason, even in toy code. If you see it in an example program, ignore the example and move on. It was deprecated in C99 and removed from the standard library completely in C2011 because it was a major security hole. The heartburn caused by that one function was worth breaking 30-some-odd years of legacy code.
Second, under C89 and earlier, if the compiler saw a function call before it saw a declaration or definition, it would assume the function returned int - IOW, the function had an implicit declaration of int. If you had a function definition later in the same translation unit, and the function returned an int, you were fine:
int foo( void )
{
int x = bar(); // bar *implicitly* declared to return int
}
int bar( void ) // implicit declaration matches definition, we're good
{
return some_integer_value;
}
However, if bar did not return an int, you'd get an error because the implicit int declaration did not match up with the non-int definition.
gets() returns char *, not int, so an implicit declaration of gets is incorrect regardless.
C99 removed implicit int declarations entirely - since then, all functions must be declared or defined before they are called.
EDIT
The most likely reason you're getting that implicit declaration error is that your compiler is recent enough that it no longer has a declaration for gets in stdio.h.

You're getting a message like "implicit declaration of gets is not allowed" for the same reason you'd get the message "implicit declaration of my_undeclared_function is not allowed" if you tried to call my_undeclared_function. These days, gets is not a standard C library function.
To explain in more detail: in modern C, if you write
int main()
{
f();
}
int f()
{
return 0;
}
you will typically get a message like "implicit declaration of function 'f' is invalid in C99". Once upon a time, if you called a function the compiler hadn't heard of (yet), it assumed it was going to be a function returning int, but that assumption was removed in C99.
On the other hand, if you write
#include <stdio.h>
int main()
{
char line[100];
printf("type something:\n");
fgets(line, sizeof(line), stdin);
printf("you typed: %s", line);
return 0;
}
you will not get that message about the functions printf and fgets. These are functions that the compiler has heard of: their declarations are in <stdio.h>.
But if you write
#include <stdio.h>
int main()
{
char line[100];
printf("type something:\n");
gets(line);
printf("you typed: %s", line);
return 0;
}
you will get the message again, about function gets(), because gets is not a function the compiler has heard of. It is not a standard function; it is not declared in <stdio.h>.
Now, once upon a time, gets was a standard function and it was declared in <stdio.h>, but it was a spectacularly ill-conceived and dangerous function, so it has been removed from the standard. The book you read recommending it is quite out-of-date.

You didn't #include <stdio.h>, simple as that.
In C99, you get the error if you use this exact code:
int main (void)
{
char buf[10];
gets(buf);
return 0;
}
Including stdio.h fixes the problem. Though notably, gets was flagged as an obsolete function in C99 and removed entirely from the language in C11. So the following code will not compile in standard C (C11):
#include <stdio.h>
int main (void)
{
char buf[10];
gets(buf);
return 0;
}
So possibly you could get the error because you compile as standard C instead of C99.
(Note that the Windows Mingw compiler specifically might use a C11 compiler but a C99 standard lib, so you may get some odd outcomes with that one.)
See Why is the gets function so dangerous that it should not be used? for details.

Related

Why int function works even when they're not declared first in C

I know that in order to use a function you must either define it above the main function or at least declare it first. However I noticed that C doesn't throw an error message if my function has a int or void return type
#include <stdio.h>
#include <stdlib.h>
int main()
{
printf("Answer: %d", cube(3));
return 0;
}
int cube(int num)
{
return num * num * num;
}
I'm still brand new to C could you explain why that rule doesn't affect int return type
Decades ago, function types defaulted to returning an int. The 1990 C standard said, in clause 6.3.2.2:
… If the expression that precedes the parenthesized argument list in a function call consists solely of an identifier, and if no declaration is visible for this identifier, the identifier is implicitly declared as if, in the innermost block containing the function call, the declaration
extern int identifier();
appeared…
Some C compilers still make provision for this, which is of dubious value in this millennium. You should request the compiler apply a more modern standard, such as by using the Clang switch -std=c17, as well as enabling warnings with -Wmost or -Wall, unless you have occasion to compile code that is more than a third of a century old.

What are the differences between: main(){}, int main(){} and int main(void){} [duplicate]

This question already has answers here:
What should main() return in C and C++?
(19 answers)
Why is the type of the main function in C and c++ left to the user to define? [duplicate]
(6 answers)
Closed 9 years ago.
I am currently learning C and I have written many small programs. However, I have noticed that the main function could start as
main()
{
//code
}
or
int main()
{
//code
return 0;
}
or
int main(void)
{
//code
return 0;
}
Which option should I use? Thanks!
For Standard C
For a hosted environment (that's the normal one), the C99 standard
says:
5.1.2.2.1 Program startup
The function called at program startup is named main. The implementation declares no prototype for this function. It shall be
defined with a return type of int and with no parameters:
int main(void) { /* ... */ }
or with two parameters (referred to here as argc and argv, though any names may be used, as they are local to the function in which they
are declared):
int main(int argc, char *argv[]) { /* ... */ }
or equivalent;9) or in some other implementation-defined manner.
9) Thus, int can be replaced by a typedef name defined as int, or the type of argv can be written as char **argv, and
so on.
This (is valid in C89) main() implicitly meant (previously) int main(void). However the default return type rule has been abandoned in C99. Also:
main() means - a function main taking an unspecified number of arguments of.
main(void) means "a function main taking no arguments.
Your first example uses a feature inherited from the outdated dialect of C which predated the first ANSI(1989) and ISO(1990) standard: namely, that you can write a function which doesn't specify its return type, and in that case the type defaults to int.
In early C, the void keyword and associated type did not exist. When programmers wanted to write procedures ("functions that have a side effect, but do not return anything"), they simulated it using this feature. They wrote a function without any keyword specifying the return type. They allowed the function to execute to it last statement without returning a value (or alternatively, they used return; to exit from the middle without supplying a value), and they wrote the calls to the function such that those calls did not try to use the return value:
parse_input() /* similar to a procedure in Pascal, but fake! */
{
/* ... */
if (condition())
return; /* no value */
/* ... */
/* fall off end here */
}
int main()
{
parse_input(); /* no return value extracted, everything cool! */
return 0;
}
Unfortunately, some programmers also started not caring about the termination status of a program and writing main itself in this procedure style:
main()
{
/* do something */
/* fall off the end without returning a value */
}
(A mixed style also existed: omitting the int declarator but returning an integer value.)
These programs failing to return a value had an indeterminate termination status. To the operating system, their execution could look successful or failed. Woe to the script writer who tried to depend on the termination status of such a program!
Then things took a turn for the worse. C++ came along and introduced void, and it was adopted into C. With the void keyword in C++, one could declare a function that actually returns nothing (and make it an error to have a return; statement in any other kind of function). The dummy programmers who used to write main with no return type got dumber, and started sticking this new-fangled, fresh-out-of-C++ void in front:
void main() /* yikes! */
{
/* do something */
/* fall off the end without returning a value */
}
By this time they had forgotten that when they wrote main(), it actually meant int main(), which made the function have a compatible type with the startup call invoked by the environment (except for the matter of neglecting to return a value). Now they actually had a different function type from the expected one, which might not even be successfully called!
Where things stand now is that in C++ and in the latest C++ standard, main is still required to return an int. But both languages make a concession for the original dummy programmers: you can let execution "fall off" the end of main and the behavior is as if return 0; had been executed there. So this trivial program now has a successful termination status as of C99 and, I think, C++98 (or possibly earlier):
int main()
{
}
But neither language makes a concession for the second-generation dumber programmers (and everyone else who read the C books that those programmers wrote in the 1980's and since). That is, void is not a valid return declarator for main (except where it is documented by platforms as being accepted, and that applies to those platforms only, not to the portable language).
Oh, and allowance for the missing declarator was removed from C in C99, so main() { } is no longer correct in new dialects of C, and isn't valid C++. Incidentally, C++ does have such a syntax elsewhere: namely, class constructors and destructors are required not to have a return type specifier.
Okay, now about () versus (void). Recall that C++ introduced void. Furthermore, though C++ introduced void, it did not introduce the (void) argument syntax. C++ being more rigidly typed introduced prototype declarations, and banished the concept of an unprototyped function. C++ changed the meaning of the () C syntax to give it the power to declare. In C++, int func(); declares a function with no arguments, whereas in C, int func(); doesn't do such a thing: it declares a function about which we do not know the argument information. When C adopted void, the committee had an ugly idea: why don't we use the syntax (void) to declare a function with no arguments and then the () syntax can stay backward compatible with the loosey-goosey legacy behavior pandering to typeless programming.
You can guess what happened next: the C++ people looked at this (void) hack, threw up their arms and copied it into C++ for the sake of cross-language compatibility. Which in hindsight is amazing when you look at how the languages have diverged today and basically no longer care about compatibility to that extent. So (void) unambiguosly means "declare as having no arguments", in both C and C++. But using it in C++ code that is obviously pure C++ never intended to be C is ugly, and poor style: for instance, on class member functions! It doesn't make much sense to write things like class Foo { public: Foo(void); virtual ~Foo(void) /*...*/ };
Of course, when you define a function like int main() { ... }, the function which is defined has no arguments, regardless of which language it is in. The difference is in what declaration info is introduced into the scope. In C we can have the absurd situation that a function can be fully defined, and yet not declared, in the same unit of program text!
When we write main, usually it is not called from within the program, and so it doesn't matter what the definition declares. (In C++, main must not be called from the program; in C it can be). So it is immaterial whether you write int main() or int main(void), regardless of whether you're using C or C++. The thing which calls main does not see any declaration of it (that you write in your program, anyway).
So just keep in mind that if you write:
int main() /* rather than main(void) */
{
}
then although it is perfect C++ and correct C, as C it has a slight stylistic blemish: you're writing an old-style pre-ANSI-C function that doesn't serve as a prototype. Though it doesn't functionally matter in the case of main, you may get a warning if you use some compilers in a certain way. For instance, GCC, with the -Wstrict-prototypes option:
test.c:1:5: warning: function declaration isn’t a prototype [-Wstrict-prototypes]
Because -Wstrict-prototypes is a darn useful warning to turn on when programming in C, for improved type safety, (along with -Wmissing-prototypes), and we strive to eliminate warnings from our compile jobs, it behooves us to write:
int main(void) /* modern C definition which prototypes the function */
{
}
which will make that diagnostic go away.
If you want main to accept arguments, then it is int main(int argc, char **argv) where the parameter names are up to you.
In C++, you can omit parameter names, so this definition is possible, which serves nicely in the place of main().
int main(int, char **) // both arguments ignored: C++ only
{
}
Since the argument vector is null-pointer-terminated, you don't need argc, and C++ lets us express that without introducing an unused variable:
#include <cstdio>
int main(int, char **argv) // omitted param name: C++ only
{
// dump the arguments
while (*argv)
std::puts(*argv++);
}
first :
declares a function main - with no input parameters. Although main should have returns ( your compiler will take care of this )
2nd/3rd:
Declare a function main which returns an int and takes in no input parameters
You should use 3rd format. Rather this is the best way:
int main(int argc, char *argv[]){
return 0;
}
You should use 1 one of these 4 choices:
int main(void);
int main();
int main(int argc, char **argv);
int main(int argc, char *argv[]);
where it's conventional to use the names argc and argv; you can change them but don't.
Take care never to use void main(void); which is too-often seen in production code.
By default main function returns an integer type, hence its "int main()" or you can give simply "main()"
"main(void)" is same as "main()", it tells the compiler that main function has no arguments.
In case if you want to pass arguments via main function:
int main(int argc, char *argv[]){
return 0;
}
main(){}
The above line give you an error. The default return type of any function in c is int. As the above code return nothing it gives you an error.
int main(){
//body
return 0;
}
In above code it fulfill all requirement so the above code will run.In above code we pass no argument in the function. So this function can take global and local variables to process.
int main(void)
{
//code
return 0;
}
In above code we pass no argument in the function. But specifying void tells the compiler that it does not take any argument. void is the default datatype of argument that signifies no input.

Extremely simple C program won't compile in gcc compiler

I have the following program
main()
{
char a,b;
printf("will i get the job:");
scanf("%c",&a);
printf("%c",a);
printf("We did it");
}
I saved the file as Hope.c. When I try to compile the code above with the gcc compiler, I will get the following error:
Hope.c:In function 'main':
Hope.c:4:2:warning:incompatible implicit declaration of built-in function 'printf' [enabled by default]
Hope.c:5:2:warning:incompatible implicit declaration of built-in function scanf[enabled by default]
The compiler gives this error when I use printf() or scanf(), even in a simple "Hello world" program.
Is there something wrong with my code, or is there a problem with the compiler?
You're missing #include <stdio.h> at the top. Note that these were warnings, though, not errors. Your program should still have compiled as is.
Also, for good measure, you should write out the return type and parameters to main() and return a value at the end.
#include <stdio.h>
int main(void)
{
char a,b;
printf("will i get the job:");
scanf("%c",&a);
printf("%c",a);
printf("We did it");
return 0;
}
When you call functions that you're not familiar with, look at the man page and include the headers that are mentioned there. It's #include <stdio.h> in your case.
That's really extermely important, e.g. I have experienced printf( "%s", func( ) ) causing a segmentation fault although func() returned a valid null terminated string, but there was no prototype that declared the return type of func() as char * (doing a little bit research, we found that only the last four bytes of the 64 bit pointer have been passed to printf())
Yes, there's something wrong with the code. You're using the functions printf and scanf without declaring them.
The usual thing to do is use the declarations shipped with the compiler (because they're known to be correct) with
#include <stdio.h>
C.89/C.90 permits implicit declarations of functions. Your warning messages are informing you that you have not provided explicit declarations for scanf and printf. As has been mentioned, you can correct this by adding #include <stdio.h> to the beginning of your program. By not doing so, the behavior of your program is undefined.
Because scanf() and printf() have implicit declarations, they are treated as if their prototypes were given as:
extern int scanf ();
extern int printf ();
These declarations state that scanf() and printf() take an as of yet unknown number of arguments and return and int. However, this kind of declaration still assumes that these functions will take a fixed number of arguments. This is incompatible with their true prototypes, in which they take a variable number of arguments:
extern int scanf (const char *, ...);
extern int printf (const char *, ...);
Your C compiler apparently knows about the true prototypes of these functions because it treats those functions as "built-ins", meaning it can generate special case code when compiling to source code that calls those functions. Since the implicit declaration does not match its built-in knowledge of their prototypes, it generated the warning.
A compiler that did not have this "built-in knowledge" probably would not have generated the warning. It would then have generated code to call scanf() and printf() as if they took a fixed number of arguments. The error then may occur at runtime, since the calling convention for a function that takes a variable number of arguments may differ from the calling convention of a function that takes a fixed number of arguments.
This is all described in C.89 §3.3.2.2.
If the expression that precedes the parenthesized argument list in
a function call consists solely of an identifier, and if no
declaration is visible for this identifier, the identifier is
implicitly declared exactly as if, in the innermost block containing
the function call, the declaration
extern int identifier();
appeared.
...
If the expression that denotes the called function has a type that
does not include a prototype, the integral promotions are performed on
each argument and arguments that have type float are promoted to
double. ... If the function is defined with
a type that includes a prototype, and the types of the arguments after
promotion are not compatible with the types of the parameters, or if
the prototype ends with an ellipsis ( ", ..." ), the behavior is
undefined.
Note that C.99 removes the allowance for implicit function declarations.

How is this pre-standard function declaration compiled with modern compiler?

I found the following declaration code in the very early sources of C compiler
main(argc, argv)
int argv[]; {
return 0;
}
I tried to run it on ideone.com compiling it in "C" mode with gcc-4.7.2 and it compiles fine and even runs successfully
result: Success time: 0s memory: 1828 kB returned value: 0
Now I'm aware that there was a pre-standard way of declaring function parameters this way:
int funct(crc, buf, len)
int crc;
register char* buf;
int len;
{
//function implementation
}
but in the latter style it's quite clear - the parameters are first just listed, then declared as if they were a kind of local variables and I see all the parameters declared and the return type.
Back to the first code
main(argc, argv)
int argv[]; {
return 0;
}
in the former code there're two parameters listed and only one declared and it looks like argv has type array of int.
How is it being treated by the compiler?
You are talking about pre-ANSI C, and the style of prototype known as K&R prototypes. For such function declarations, parameters and return values whose types are not specified are deemed to be of type int.
It is K&R C syntax where compiler won't check the types of arguments and arguments will be default to int.
K&R sysntax still gets suppot from the latest compilers for compatibility.In cases where code must be compilable by either standard-conforming or K&R C-based compilers, the STDC macro can be used to split the code into Standard and K&R sections to prevent the use on a K&R C-based compiler of features available only in Standard C.
main(argc, argv)
int argv[]; {
return 0;
}
The type of argc is int in K&R C and C90 due to the implicit integer conversion rule but it's not a conforming code in C99 & C11. Because the implicit int conversion has been deprecated in C99 and C11. Same goes for the return value of main().
main() receives the arguments passed from the host. Since main() can't receive array of ints but only an array of strings. This could potentially cause undefined behaviour because the actual arguments passed to main() can't be accessed with using an integer array. Compiler can't do type checking for the parameters because main() is called from outside (from the hosted environment). So compiler assumes whatever you say as parameters for main() are correct. You can even do:
int main(argc, argv, a, b,c)
int argc;
int argv[];
int a, b, c;
{
....
}
This is a valid code. But there's no legal way to access all these ints (except argc).
GCC comes with a non-standard setup as default. The code you posted will not compile on a conforming C compiler.
Compile with a C compiler instead. gcc -std=c99 -pedantic-errors will not compile your code.

Why does c allow main() even when it is not int main() or void main()?

While reading the K&R 2nd edition I noticed that the programs always began with
"main(){". I had always thought that main() had to have int or void before it. So that it would look like "int main()" or "void main()". What is just "main()" and what is the difference?
main() is the old K&R style where the int was omitted as the return type defaults to int if not specified (you should specify it). Additionally, empty parentheses is in K&R style to show it takes no arguments.. in C99 this should now be void to indicate such. Empty parentheses means that the function will accept any number of arguments of any type, which is clearly not what you want. So the final result is:
int main(void) { ... }
main() should return int.. convention says a return 0; statement at the end will help indicate to the caller that the program executed successfully - non-0 return values indicate abnormal termination.
A more direct answer to your question would be that main() { ... } works because it's not wrong. The compiler sees that no return type was declared for the main function so it defaults to int. The empty parentheses indicates to it that main takes any number of arguments of any type, which is not wrong either. However, to conform to C99 style/standard, use
int main(void) { ... }
Because this is supported in by an old version of c.
main()
is equivalent to
int main()
Syntax most of times depends on the compiler. For example, when you use visual c++ you write "void main" but when you use GCC, you should write "int main()" and then return 0 or 1 if the program finished good or bad.

Resources