main;
This is the smallest program that can be compiled in C.
Compilation warnings (gcc):
test.c:1:1: warning: type defaults to ‘int’ in declaration of ‘main’ [-Wimplicit-int]
test.c:1:1: warning: ‘main’ is usually a function [-Wmain]
I'd like to understand what it means, syntactically speaking, namely:
why the semicolon when declaring a function ?
why are the missing parenthesis and curly brackets legal ?
I know that the default return type of a function is int when omitted. I also heard of the _start function which is called before main. This would mean that it is calling a function that hasn't been defined(?).
Why exactly does the executable segfaults when run ?
Because you didn't specify a type for main, the compiler is defaulting to a type of int. Not a function returning an int, but an int. This is legal from a syntactic standpoint, as you could have also had myvar; in your code which would also be declared as int.
But because main is special, that's why you get the second warning. It is letting you know that how you defined main differs from what how it is typically defined.
So when you compile this program an attempt to run it, it is expecting main to be the start of a function when it is actually just an int variable. This is what causes the segfault.
Related
In this c program
a=8;
main()
{
printf("%d", a);
}
variable a has been declared without any data type and still this program compiles successfully and gives the desired output.
output ::
8
see it on ideone.
but, when i declared the same variable inside main, it gives compilation error.
main()
{
a=8;
printf("%d", a);
}
output ::
prog.c:2: warning: return type defaults to ‘int’
prog.c: In function ‘main’:
prog.c:3: error: ‘a’ undeclared (first use in this function)
prog.c:3: error: (Each undeclared identifier is reported only once
prog.c:3: error: for each function it appears in.)
prog.c:4: warning: implicit declaration of function ‘printf’
prog.c:4: warning: incompatible implicit declaration of built-in function ‘printf’
see here.
How the first program is working but the second?
What you see here is the "Implicit Int Rule" at work. Simply put the rule says:
"A variable declared without an explicit type name is assumed to be of type int."
Note that this rule was revoked in the c99 Standard[Ref 1].However, depending on your compiler and its settings, the first example might compile with a warning, or will fail to compile(with strict compilation settings)
If you compile your first example with strict settings adhering to c99 Standard the compiler will tell you the root cause.
check here.
cc1: warnings being treated as errors
prog.c:1: error: data definition has no type or storage class
prog.c:1: error: type defaults to ‘int’ in declaration of ‘a’
prog.c:3: error: return type defaults to ‘int’
prog.c: In function ‘main’:
prog.c:4: error: implicit declaration of function ‘printf’
prog.c:4: error: incompatible implicit declaration of built-in function ‘printf’
EDIT:
why does the first example work but second does not?
Note the emphasis on the words "variable declared" in the rule.
In first example, since the statement is at the global scope it is treated as an Implicit declaration, and the Implicit Int Rule gets applied to it.
In Second example, the statement acts as an Assignment and not a Declaration. Since there is no declaration the Implicit int rule does not apply here. In the absence of any type the compiler cannot determine what is the type of a and hence reports the error.
[Ref 1]
C99 Standard: Foreword
Para 5:
This edition replaces the previous edition, ISO/IEC 9899:1990, as amended and corrected
by ISO/IEC 9899/COR1:1994, ISO/IEC 9899/COR2:1995, and ISO/IEC 9899/AMD1:1995.
Major changes from the previous edition include:
.....
.....
— remove implicit int
.....
.....
a=8; outside of the function looks like a declaration statment, where a is the declaration specifier and = 8 is the initializer. C used to allow to omit types in declaration specifiers and defaults to int in that case. (Since C99, this is no longer allowed.)
However, in a function, a=8; looks like an expression statement (an assignment expression) and symbol a isn't resolved. (Note that you don't have expression statements outside of functions.)
If you tried to do, for instance static a = 8;, then it would again look like a declaration, and should compile because the type would default to int.
Anyway, don't rely on that :-) Write your types clearly.
It's because in C, any variable / function is implicitly int.
This is the same reason that you can use register instead of register int, or unsigned instead of unsigned int, auto instead of auto int, and static instead of static int. I personally always explicitly qualify my variables with int, but whether you do or not is your option.
Your variable does have a data type (int) even though you didn't write the data type.
It is bad practice to take advantage of that feature.
Apparently your compiler doesn't allow that to happen inside a function. That makes sense because if it did allow "a=8;" in a function it would be very hard to catch certain typoes.
In C++11, there is the auto
keyword.Unfortunately, C and C++ are strongly-typed languages, whose require defining a strict type for the each declared variable. Some compliers assume int as default , but it's their well-mind and it should not be used, because it's acknowledged
as a wrong programming habit.
even a function parameter can be written as implicit int.
example:
fun(n){printf("%d",n);}
The above code works fine but once a fixed datatype is included in parameters,like
fun(n,char c){ printf("%d",n);}
It shows error:
error: expected ')' before 'char'|
#include<stdio.h>
int main()
{
//void foo();
int c= 5;
c=foo();
printf("\n%d",c);
return 0;
}
void foo()
{
printf("I am foo");
}
When I am commenting the prototype declaration then it gives the output:
I am foo
8
With prototype it gives the error saying:
void value not ignored as it ought ought to be.
My question is, what is internally happening which result into the output when there is no prototype declaration? What is the reason behind it?
I am using Dev C++ editor with TDM-GCC 4.9.2 64bit compiler.
The sole reason this is built successfully is the implicit int rule (now removed in the latest revision of the C standard).
The compiler sees no forward declaration of foo, so it assumes that its return type is int. It then proceeds to build and call your void foo(). After all is said and done, the behavior of your program is undefined.
Gcc compiler give warning and successfully run and return number of character with whitespace but some compiler give an error.
pp.c:10:6: warning: conflicting types for ‘foo’ [enabled by default]
void foo()
^
pp.c:6:6: note: previous implicit declaration of ‘foo’ was here
c=foo();
when there is no prototype declaration
Well, that is invalid C.
To elaborate,
Point 1: You cannot have a function called which is not declared earlier. It is against the C standard rule.Note
Point 2: As soon as you add the forward declaration, you'll be getting compilation error, as a void type cannot be the RHS operand of an assignment operator and this is a constraint violation for assignment operator.
Note:
Pre C99, it was allowed to have a function being called without the prototype known, it was assumed that the function will be returning an int and will be accepting any number of parameters. However, this is precisely forbidden as per C99 and later, as the "implicit int rule" is removed from the standard. (Refer Foreword, paragraph 5, _"remove implicit int"_ in C99 standard).
In your case, for legacy reasons, the compiler still supports the implicit int rule, so it compiles fine, however, the assumption by compiler and the actual function definition is a mismatch. This invokes undefined behavior.
Quoting C11, chapter §6.5.2.2, Function calls
If the function is defined with a type that is not compatible with the type (of the
expression) pointed to by the expression that denotes the called function, the behavior is
undefined.
I'm reading a bit of code in C, and in the variable declaration line, there's "char *p, *getenv();"
I understand "char *p" of course. What does "char *getenv()" do? Later on in the code, the function getenv() is called with a variable passed to it. But what's the point of "char *getenv();" without any arguments?
Sorry if this is basic. I'm just starting to learn C.
It is "valid C" (I would almost say "unfortunately") - but it is not particularly useful. It is a "declaration without declaration" - "I will be using a function getenv() but I'm not going to tell you what the arguments will be". It does have the advantage of preventing a compiler warning / error - something that would normally be prevented with a "real" function prototype, for example by including the appropriate .h file (in this case, stdlib.h).
To clarify: the following code
#include <stdio.h>
int main(void) {
char *p;
p = getenv("PATH");
printf("the path is %s\n", p);
return 0;
}
will throw a compiler warning (and you should never ignore compiler warnings):
nonsense.c: In function ‘main’:
nonsense.c:5: warning: implicit declaration of function ‘getenv’
nonsense.c:5: warning: assignment makes pointer from integer without a cast
Either adding #include <stdlib.h> or the line you had above, will make the warning go away (even with -Wall -pedantic compiler flags). The compiler will know what to do with the return value - and it figures out the type of the arguments on the fly because it knows the type when it sees it.
And that is the key point: until you tell the compiler the type of the return value of the function it does not know what to do (it will assume int, and make appropriate conversions for the variable you are assigning to - this can be inappropriate. For example, a pointer is often bigger than an int, so information will be lost in the conversion.)
It's a declaration (an old-style one without a prototype, since the argument list is missing) for the function getenv. Aside from being arguably bad style to hide a function declaration alongside the declaration of an object like this, it's bad to omit the prototype and bad not to be using the standard headers (stdlib.h in this case) to get the declarations of standard functions.
Receiving error: conflicting types for ‘six’ when attempting to compile.
void main(){
const int k = 4;
six(&k);
}
float * six(const int *x)
{
float *p = malloc(sizeof(float));
*p = (float)*x;
return p;
}
Here is what is going on.
When the compiler does not encounter a prototype for a function before a call to it, it deduces the prototype from the call itself, and assumes the return type to be int. This is what it does in your example.
Later it finds the definition of the function, and it finds that the return type is actually float, which does not match with the prototype it has deduced earlier. Hence the error of conflicting types (instead of, say, missing prototype).
The solution is to, of course, provide a prototype for the function before a call to it is made.
You didn't declare six to the compiler before you called it, so the compiler was forced to guess what the signature of six is (typically, this is something like int func()). When it saw the actual declaration, it threw an error because the actual function declaration didn't match its implicit declaration.
You need to declare functions before they are used; place a declaration like
float *six(const int *x);
before main.
Solution to your problem
Just add the following declaration before main():
float *six(const int *x);
Or put your float *six(const int *x) definition before the main() function.
Why the compiler complain conflicting types
Since there is no declaration of your six() function before the compiler compile the main function, it will deduce the prototype from the function callsite, and will assume the return type to be int. And when it compiles your six() function, the compiler will find two function with the same name but different return type, so it complain the conflicting types error.
Thanks to Ziffusion's comment.
why to adjust your code in the above way
You should declare/define each of your element before use in C.
For your currently code, you need to declare your function type before the main function, so that the compiler knows what six() is when compile the main function.
Why there should be a declaration before use in C
For variables and other data types, since C is strong typed. When the variable is used, it need to be declared first, so that the compiler knows what type the variable is, and could do data type check.
For functions, since the C compiler compiles the code function by function, and will generate a function call statement in the assembly, so the compiler need to know the function parameter and return value data type, so that it could generated correct instructions to do parameter passing, and return value restoring. Normally, the compiler will compile the function in a source code file one by one from the start of the file to the end of the file, so you need to declare the function type before use it.
In this c program
a=8;
main()
{
printf("%d", a);
}
variable a has been declared without any data type and still this program compiles successfully and gives the desired output.
output ::
8
see it on ideone.
but, when i declared the same variable inside main, it gives compilation error.
main()
{
a=8;
printf("%d", a);
}
output ::
prog.c:2: warning: return type defaults to ‘int’
prog.c: In function ‘main’:
prog.c:3: error: ‘a’ undeclared (first use in this function)
prog.c:3: error: (Each undeclared identifier is reported only once
prog.c:3: error: for each function it appears in.)
prog.c:4: warning: implicit declaration of function ‘printf’
prog.c:4: warning: incompatible implicit declaration of built-in function ‘printf’
see here.
How the first program is working but the second?
What you see here is the "Implicit Int Rule" at work. Simply put the rule says:
"A variable declared without an explicit type name is assumed to be of type int."
Note that this rule was revoked in the c99 Standard[Ref 1].However, depending on your compiler and its settings, the first example might compile with a warning, or will fail to compile(with strict compilation settings)
If you compile your first example with strict settings adhering to c99 Standard the compiler will tell you the root cause.
check here.
cc1: warnings being treated as errors
prog.c:1: error: data definition has no type or storage class
prog.c:1: error: type defaults to ‘int’ in declaration of ‘a’
prog.c:3: error: return type defaults to ‘int’
prog.c: In function ‘main’:
prog.c:4: error: implicit declaration of function ‘printf’
prog.c:4: error: incompatible implicit declaration of built-in function ‘printf’
EDIT:
why does the first example work but second does not?
Note the emphasis on the words "variable declared" in the rule.
In first example, since the statement is at the global scope it is treated as an Implicit declaration, and the Implicit Int Rule gets applied to it.
In Second example, the statement acts as an Assignment and not a Declaration. Since there is no declaration the Implicit int rule does not apply here. In the absence of any type the compiler cannot determine what is the type of a and hence reports the error.
[Ref 1]
C99 Standard: Foreword
Para 5:
This edition replaces the previous edition, ISO/IEC 9899:1990, as amended and corrected
by ISO/IEC 9899/COR1:1994, ISO/IEC 9899/COR2:1995, and ISO/IEC 9899/AMD1:1995.
Major changes from the previous edition include:
.....
.....
— remove implicit int
.....
.....
a=8; outside of the function looks like a declaration statment, where a is the declaration specifier and = 8 is the initializer. C used to allow to omit types in declaration specifiers and defaults to int in that case. (Since C99, this is no longer allowed.)
However, in a function, a=8; looks like an expression statement (an assignment expression) and symbol a isn't resolved. (Note that you don't have expression statements outside of functions.)
If you tried to do, for instance static a = 8;, then it would again look like a declaration, and should compile because the type would default to int.
Anyway, don't rely on that :-) Write your types clearly.
It's because in C, any variable / function is implicitly int.
This is the same reason that you can use register instead of register int, or unsigned instead of unsigned int, auto instead of auto int, and static instead of static int. I personally always explicitly qualify my variables with int, but whether you do or not is your option.
Your variable does have a data type (int) even though you didn't write the data type.
It is bad practice to take advantage of that feature.
Apparently your compiler doesn't allow that to happen inside a function. That makes sense because if it did allow "a=8;" in a function it would be very hard to catch certain typoes.
In C++11, there is the auto
keyword.Unfortunately, C and C++ are strongly-typed languages, whose require defining a strict type for the each declared variable. Some compliers assume int as default , but it's their well-mind and it should not be used, because it's acknowledged
as a wrong programming habit.
even a function parameter can be written as implicit int.
example:
fun(n){printf("%d",n);}
The above code works fine but once a fixed datatype is included in parameters,like
fun(n,char c){ printf("%d",n);}
It shows error:
error: expected ')' before 'char'|