This is a basic C code, which according to me should have thrown three errors (function not defined, function not returning anything, function argument missing). But to my surprise it threw nothing, it compiled and gave some garbage results:
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char *argv[])
{
int a=f1();
printf("a %d\n",a);
system("PAUSE");
return 0;
}
f1(int *t)
{
printf("t %d", t);
}
PS: I am using a gcc compiler on windows.
In C when a function is not declared is is assumed to return int and compilation continues (btw this can lead to nasty bugs). If the function is declared without a type (as f1() is in your code it is assumed to return int. Not returning a value from a non-void function (as in your code) is undefined behavior.
So none of the points you mention are required to cause a compilation error. Undefined behavior is not required to prevent your program from running - the program might run and might even produce good looking results.
Firstly, you were not compiling with warnings enabled. You should usually invoke gcc with at least the -Wall switch - for your example code, that gives:
x.c: In function 'main':
x.c:7: warning: implicit declaration of function 'f1'
x.c: At top level:
x.c:15: warning: return type defaults to 'int'
x.c: In function 'f1':
x.c:16: warning: format '%d' expects type 'int', but argument 2 has type 'int *'
x.c:17: warning: control reaches end of non-void function
Secondly, the reason that it compiles is that all of the errors in it are of a form called "undefined behaviour", which means that the compiler isn't required to diagnose them and stop compilation - it can simply produce garbage results.
You would probably be happier if you used gcc's -Wall option to enable all warnings. Then you would see this while compiling:
C:\test>make
gcc -Wall prog.c -o prog
prog.c: In function 'main':
prog.c:7:5: warning: implicit declaration of function 'f1'
prog.c: At top level:
prog.c:14:1: warning: return type defaults to 'int'
prog.c: In function 'f1':
prog.c:16:8: warning: format '%d' expects type 'int', but argument 2 has type 'int *'
prog.c:17:1: warning: control reaches end of non-void function
You can also use -Werror to turn all warnings in to errors (so you are forced to fix them).
Try compiling again with the -Wall flag. That turns on all warnings, then you'll see plenty:
c.c: In function ‘main’:
c.c:7: warning: implicit declaration of function ‘f1’
c.c: At top level:
c.c:15: warning: return type defaults to ‘int’
c.c: In function ‘f1’:
c.c:16: warning: format ‘%d’ expects type ‘int’, but argument 2 has type ‘int *’
c.c:17: warning: control reaches end of non-void function
Since you don't have any compile time errors, just warnings, the code compiles fine. It just won't execute very well.
f1 is considered to have the implicit prototype 'int f1(int)'.
Hence the call is valid.
f1 does not return anything whereas it is implicitly suppoed to return an int: the behaviour is undefined.
The compiler could warn you that the implicit prototype does not agree with the definition. It could also ask for a proper return. This is part of the checks that the static analysis inside the compiler could perform: gcc does not do it, others may.
In any case compilers usually do not guarantee anything about non ISO conforming programs.
If you add -Wall to your gcc commands you should get some warnings. I guess it works as old style C had loose function prototyping. And will assume unknown functions return int. The linker worked because there were no undefined symbols (f1 exists) but you got garbage as what was passed on the stack (i.e. nothing) was not what was expected.
Related
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.
This question already has answers here:
Does this self-assignment do something sensible?
(4 answers)
Compiler not detecting obviously uninitialized variable
(4 answers)
Closed 5 years ago.
While debugging a program of mine, I stumbled upon a weird behaviour of the gcc compiler. I don't know what's the correct title to describe this, but take a look at the code below.
Basically, I had a function which received a void* arg as an argument. It then casted it to a pointer of another type, HTTPRequest*. However, I casted the wrong variable, so the code looked like
void someCallback(void* arg) {
HTTPRequest* req = (HTTPRequest*) req;
FreeRequest(req);
//re-setup request, other stuff..
}
The program then crashed within FreeRequest with a SIGSEGV when it tried to derefrence the pointer. Upon further inspection, req always a had a value of NULL.
It took me a while to realize that the cast I did was just done on the wrong variabe - it should have been
HTTPRequest* req = (HTTPRequest*) arg;
Then it all worked. I was however baffled that gcc allowed me to not only compile this code, but throw no warning whatsoever at this line.
Consider the minimal example
#include <stdlib.h>
#include <stdio.h>
void someFunc(void* arg) {
int* a = (int*) a;
printf("a = %p\n", a);
printf("*a = %d\n", *a);
}
int main() {
int b = 42;
someFunc(&b);
return 0;
}
Compiled with
gcc -Wall -Wextra -Wpedantic -o test -O0 test.c && test.exe
Compiler outputs
test.c: In function 'someFunc':
test.c:7:9: warning: format '%p' expects argument of type 'void *', but argument 2 has type 'int *' [-Wformat=]
printf("a = %p\n", a);
^
test.c:4:21: warning: unused parameter 'arg' [-Wunused-parameter]
void someFunc(void* arg) {
^
And the program outputs:
a = 0061FFCC
*a = 6422500
With optimization at atleast O1 it outputs however:
gcc -Wall -Wextra -pedantic -o test -O1 test.c && test.exe
test.c: In function 'someFunc':
test.c:7:9: warning: format '%p' expects argument of type 'void *', but argument 2 has type 'int *' [-Wformat=]
printf("a = %p\n", a);
^
test.c:4:21: warning: unused parameter 'arg' [-Wunused-parameter]
void someFunc(void* arg) {
^
And outputs
a = 00000000
Then hangs.
So the question is: Why does gcc allow the compilation of expressions of the above form? This is obviously undefined behaviour. Then why are there no warnings about this, even with all warnings enabled?
Why does gcc allow the compilation of expressions of the above form? This is obviously undefined behaviour.
Because the standard allow this. Undefined behavior allow compiler to optimize code write in C. You can read this excellent article from llvm developer.
Then why are there no warnings about this, even with all warnings enabled?
-Wall -Wextra don't active all warning in gcc. clang has -Weverything but, gcc don't have such option.
Compiler are not force to print a warning message for everything. There are few warning that a compiler must print if it want to be standard compliant.
What you do is undefined behavior and this is not mandatory in the standard to print a warning.
clang 4.0.0 has a warning for this -Wuninitialized:
warning: variable 'a' is uninitialized when used within its own initialization [-Wuninitialized]
int* a = (int*) a;
gcc 7.1.1 has a warning for this -Winit-self:
warning: ‘a’ is used uninitialized in this function [-Wuninitialized]
int* a = (int*) a;
Note: Your cast is useless, C will promote any void * to the correct pointer type.
I downloaded this source code (.zip) and would like to compile it on my Mac (OSX 10.11.2) with an XCode Version 7.2 (7C68).
I started to compile the file fdist.c with
gcc -o fdist2 -O fdist.c -lm
but it returns a long series of warnings and errors (see below). Looking at the file I see that indeed it does not quite look as the kind of code I am used to. Typically, it appears that the type of object the functions returned are unspecified.
The README_fdist2 did not help much. There are guidelines on how to compile the code but there is a typo in the first line.
How should I compile this code?
Below are the errors and warnings the command gcc -o fdist2 -O fdist.c -lm returned
fdist2.c:42:1: warning: type specifier missing, defaults to 'int' [-Wimplicit-int]
main()
^
fdist2.c:117:3: warning: implicit declaration of function 'sim1' is invalid in C99
[-Wimplicit-function-declaration]
sim1(init,initot,rm,mu,freq_arr,val_arr,&noall);
^
fdist2.c:119:4: warning: implicit declaration of function 'my_thetacal' is invalid in C99
[-Wimplicit-function-declaration]
my_thetacal(freq_arr,noall,init,Subs,&h0,&h1,&fst);
^
fdist2.c:136:1: warning: type specifier missing, defaults to 'int' [-Wimplicit-int]
sim1(init,initot,rm,mu,freq_arr,val_arr,noall)
^
fdist2.c:222:3: warning: implicit declaration of function 'dfill' is invalid in C99
[-Wimplicit-function-declaration]
dfill();
^
fdist2.c:234:4: warning: implicit declaration of function 'cnode' is invalid in C99
[-Wimplicit-function-declaration]
cnode(k);
^
fdist2.c:237:8: warning: implicit declaration of function 'mnode' is invalid in C99
[-Wimplicit-function-declaration]
else mnode(k);
^
fdist2.c:252:1: warning: control may reach end of non-void function [-Wreturn-type]
}
^
fdist2.c:254:1: warning: type specifier missing, defaults to 'int' [-Wimplicit-int]
thetacal(gen,noall,sample_size,no_of_samples,het0,het1,fst)
^
fdist2.c:293:1: warning: control reaches end of non-void function [-Wreturn-type]
}
^
fdist2.c:301:1: warning: type specifier missing, defaults to 'int' [-Wimplicit-int]
dfill()
^
fdist2.c:312:1: warning: control reaches end of non-void function [-Wreturn-type]
}
^
fdist2.c:315:1: warning: type specifier missing, defaults to 'int' [-Wimplicit-int]
cnode(sp)
^
fdist2.c:349:2: error: non-void function 'cnode' should return a value [-Wreturn-type]
return;
^
fdist2.c:353:1: warning: type specifier missing, defaults to 'int' [-Wimplicit-int]
mnode(sp)
^
fdist2.c:464:2: error: non-void function 'mnode' should return a value [-Wreturn-type]
return;
^
fdist2.c:489:10: warning: implicit declaration of function 'poidev' is invalid in C99
[-Wimplicit-function-declaration]
mutno = poidev(time*mu);
^
fdist2.c:491:12: warning: implicit declaration of function 'addmut' is invalid in C99
[-Wimplicit-function-declaration]
p->dna = addmut(p->dna);
^
fdist2.c:676:1: warning: type specifier missing, defaults to 'int' [-Wimplicit-int]
mom(x,n,x1,x2,x3,x4,min,max)
^
fdist2.c:707:2: error: non-void function 'mom' should return a value [-Wreturn-type]
return;
^
fdist2.c:761:1: warning: type specifier missing, defaults to 'int' [-Wimplicit-int]
my_thetacal(gen,noall,sample_size,no_of_samples,het0,het1,fst)
^
18 warnings and 3 errors generated.
The problem is not the compiler but the fact that your code does not follow the syntax. C99 requires that all variables and functions be declared ahead of time. Function and class definitions should be placed in a .h header file and then included in the .c source file in which they are referenced.
i.e.
mycode.h:
int myFunction (int a, char * s);
mycode.c
#include "mycode.h"
int main(int argc, char **argv) {
int x = 2;
char * str = "Hello";
int r = myFunction(x,str);
return r;
}
Looks like the code doesn't conform to C99 with implicit function declrations, default return (int) etc.
It doesn't seem to be hard to fix it. But if you don't want to or can't then you can attempt to compile in C89/C90 in which implicit int return is valid. This should fix most, if not all, of the warnings you get.
gcc -std=c89 -o fdist2 -O fdist.c -lm
This program goes against everything I have been taught and learned in C. How does this compile? Why does this not need to be int main? Why no return 0? Don't you need an initial declaration of sub() above main? That bugs the crap out of me. I like keeping my functions above main.
#include <stdio.h>
main()
{
sub ();
sub ();
}
sub()
{
static int y = 5;
printf(" y is %d \n",y);
y++;
}
The gcc version is:
gcc version 4.4.7 20120313 (Red Hat 4.4.7-11) (GCC)
This is an old version it seems but not to crazy old.
https://www.gnu.org/software/gcc/releases.html
How do I check if this is c90 or c89?
This code uses an obsolete feature of early C called implicit int. Its only uses are in code-golf competitions. Indeed, even variables may be declared this way. The variable y might easily have been declared
static y = 5;
.
A function may be called without having been prototyped. The function is assumed to receive exactly the number of arguments passed, subject to the "usual promotions". Any type smaller than an int is promoted to int, and floats are promoted to double.
So the functions behave as if they were prototyped as:
int main(void);
int sub(void);
To return any type other than int, the return type must be specified.
You can specify the standard you wish to use when compiling.
gcc -ansi
gcc -std=c99
And add -pedantic to make gcc believe that you really mean it.
Oddly enough, this code does not conform strictly to any standard. C99 disallows implicit int, but permits eliding return 0; from main. C90 or "ansi" C allows implicit int, but requires a return. So, a return should definitely be there.
Btw, C89 is exactly the same thing as C90. It took a while for both hemispheres of the world to agree. Timezones and meridians and such. It's the same standard.
It does not compile. If you don't tell gcc to be a strictly conforming C compiler but just call it with gcc test.c, then it will remain a completely non-standard compiler which allows a whole lot of weird things. It does not conform to any known C standard when left with its default setting.
gcc -std=c11 -pedantic-errors gives:
test.c:3:1: error: return type defaults to 'int'
main()
^
test.c: In function 'main':
test.c:5:4: error: implicit declaration of function 'sub' [-Wimplicit-function-d
eclaration]
sub ();
^
test.c: At top level:
test.c:9:1: error: return type defaults to 'int'
sub()
^
test.c: In function 'sub':
test.c:14:1: warning: control reaches end of non-void function [-Wreturn-type]
}
#lundin, please note:
main()
is not equivalent to
int main(void)
because void means there are no parameters but () means there can be any number of parameters.
Closed. This question is not reproducible or was caused by typos. It is not currently accepting answers.
This question was caused by a typo or a problem that can no longer be reproduced. While similar questions may be on-topic here, this one was resolved in a way less likely to help future readers.
Closed 8 years ago.
Improve this question
I need someone to tell me what I am doing wrong over here.
void main(void) {
int *arr,n,i;
printf("Enter the number of elements you want to enter=");
scanf("%d",&n);
arr = (int*)calloc(n,sizeof(int));
if(!arr)
return;
for(i=0;i<n;i++)
scanf("%d",&arr[i]);
for(i=0;i<n;i++)
printf("%d ",arr[i]);
free(arr);
}
This is nothing but a simple program to input the number of items in an array then take the input and print the inputted values. But whenever I go to input the values in the array after taking the number of items from the user, my program CRASHES. I don't understand what I am doing wrong over here. Need some help immediately. Please run the program and see if it also crashes on other systems. I executed the program using an online compiler and strangely there it was running fine. I am using the Visual Studio 2013 command line compiler to execute my program.
Compiling this piece of code with gcc I get:
calloc.c: In function ‘main’:
calloc.c:4:5: warning: incompatible implicit declaration of built-in function ‘printf’ [enabled by default]
calloc.c:5:5: warning: incompatible implicit declaration of built-in function ‘scanf’ [enabled by default]
calloc.c:7:17: warning: incompatible implicit declaration of built-in function ‘calloc’ [enabled by default]
calloc.c:18:5: warning: incompatible implicit declaration of built-in function ‘free’ [enabled by default]
using clang:
calloc.c:1:1: error: 'main' must return 'int'
void main(void) {
^
calloc.c:4:5: warning: implicitly declaring C library function 'printf' with type 'int (const char *, ...)'
printf("Enter the number of elements you want to enter=");
^
calloc.c:4:5: note: please include the header <stdio.h> or explicitly provide a declaration for 'printf'
calloc.c:5:5: warning: implicitly declaring C library function 'scanf' with type 'int (const char *, ...)'
scanf("%d",&n);
^
calloc.c:5:5: note: please include the header <stdio.h> or explicitly provide a declaration for 'scanf'
calloc.c:7:17: warning: implicitly declaring C library function 'calloc' with type 'void *(unsigned long, unsigned long)'
arr = (int*)calloc(n,sizeof(int));
^
calloc.c:7:17: note: please include the header <stdlib.h> or explicitly provide a declaration for 'calloc'
calloc.c:18:5: warning: implicit declaration of function 'free' is invalid in C99 [-Wimplicit-function-declaration]
free(arr);
^
4 warnings and 1 error generated.
As clang kindly pointed out, you need to add
#include <stdlib.h>
#include <stdio.h>
to the top of your code, as you are using functions that are declared within them. The functions you are using are in the standard C library, so the code will still compile but you should expect the unexpected. The reason your program crashes is likely to be that the compiler has made an incorrect assumption about the return type of calloc, as it doesn't have the correct declaration. Many systems will let you get away with this but at the very least they should warn you.
On a side note, please see this discussion on casting the return value of malloc (don't cast it). This advice also applies to calloc.
edit
Here's a minimal example which might shed some light on the issue:
a.c
#include <stdio.h>
int main()
{
printf("%f\n", f());
return 0;
}
b.c
float f()
{
return 4.2;
}
These two files can be compiled separately into object files:
gcc -c a.c # creates a.o
gcc -c b.c # creates b.o
No warnings or errors are generated. Switching to C99 mode causes an "implicit function declaration" warning. Note that at compile-time, the function definition isn't needed. These two object files can be linked:
gcc a.o b.o
Now, the linker finds the definitions of the functions so there is no error but it is already too late. The implicit declaration of f() when a.c was compiled causes the output to be incorrect when the program is run (I get 0.000000).
The same thing has happened here as in your question. The function calloc can be found, so there is no error at link-time. However, an incorrect assumption is made about the type that it returns, so it doesn't behave as expected on your system.