GCC default includes and math.h?

J

John

What headers does GCC include by default and is there any way to
change the behavior?

It seems on my system that math.h is being included by default and I
don't need to include it in source for
math functions. The code below compiles just fine as long as I
include the math library -lm.
I don't even include stdio.h and it works just fine. I'm not sure I
like this.

gcc version 3.4.6 20060404 (Red Hat 3.4.6-11)

gcc -lm mathtest.c

main()
{
printf("exp(3.3) %f \n", exp(3.3));
printf("2^5 %f \n", pow(2,5));
}
 
R

Rob Kendrick

What headers does GCC include by default and is there any way to
change the behavior?

It seems on my system that math.h is being included by default and I
don't need to include it in source for
math functions. The code below compiles just fine as long as I
include the math library -lm.
I don't even include stdio.h and it works just fine. I'm not sure I
like this.

rjek@trite:~$ cat > tst.c
main()
{
printf("exp(3.3) %f \n", exp(3.3));
printf("2^5 %f \n", pow(2,5));
}
rjek@trite:~$ gcc tst.c
tst.c: In function ‘main’:
tst.c:3: warning: incompatible implicit declaration of built-in
function ‘printf’ tst.c:3: warning: incompatible implicit declaration
of built-in function ‘exp’ tst.c:4: warning: incompatible implicit
declaration of built-in function ‘pow’
rjek@trite:~$ gcc --version
gcc (Ubuntu 4.4.1-4ubuntu9) 4.4.1


I'd find it pretty incredible if it did. However, your earlier version
of GCC may not generate the warnings I get with 4.4.1 by default, but
that doesn't mean it's #including math.h by default.

Try this:

rjek@trite:~$ cat > tst.c
main()
{
printf("%f", M_PI);
}
rjek@trite:~$ gcc tst.c
tst.c: In function ‘main’:
tst.c:3: warning: incompatible implicit declaration of built-in
function ‘printf’ tst.c:3: error: ‘M_PI’ undeclared (first use in this
function) tst.c:3: error: (Each undeclared identifier is reported only
once tst.c:3: error: for each function it appears in.)

M_PI is defined in math.h; if this doesn't generate a binary for you,
it's not including math.h by default.

B.
 
S

Seebs

What headers does GCC include by default and is there any way to
change the behavior?

This question is incoherent.
It seems on my system that math.h is being included by default and I
don't need to include it in source for
math functions. The code below compiles just fine as long as I
include the math library -lm.
I don't even include stdio.h and it works just fine. I'm not sure I
like this.

In general, so far as I know, there's no particular guarantee that standard
library functionality *won't* be included by default, only that it *will*
if you include the headers.

I don't see a problem.

-s
 
A

Andrew Poelstra

What headers does GCC include by default and is there any way to
change the behavior?

It seems on my system that math.h is being included by default and I
don't need to include it in source for
math functions. The code below compiles just fine as long as I
include the math library -lm.
I don't even include stdio.h and it works just fine. I'm not sure I
like this.

gcc version 3.4.6 20060404 (Red Hat 3.4.6-11)

gcc -lm mathtest.c

main()
{
printf("exp(3.3) %f \n", exp(3.3));
printf("2^5 %f \n", pow(2,5));
}

Try compiling with
gcc -Wall -Wextra -ansi -pedantic -O2 src.c
or
gcc -Wall -Wextra -std=c99 -pedantic -O2 src.c

Whatever suits your fancy.
 
J

John

rjek@trite:~$ cat > tst.c
main()
{
printf("exp(3.3) %f \n", exp(3.3));
printf("2^5 %f \n", pow(2,5));}

rjek@trite:~$ gcc tst.c
tst.c: In function ‘main’:
tst.c:3: warning: incompatible implicit declaration of built-in
function ‘printf’ tst.c:3: warning: incompatible implicit declaration
of built-in function ‘exp’ tst.c:4: warning: incompatible implicit
declaration of built-in function ‘pow’
rjek@trite:~$ gcc --version
gcc (Ubuntu 4.4.1-4ubuntu9) 4.4.1

I'd find it pretty incredible if it did.  However, your earlier version
of GCC may not generate the warnings I get with 4.4.1 by default, but
that doesn't mean it's #including math.h by default.

Try this:

rjek@trite:~$ cat > tst.c
main()
{
printf("%f", M_PI);}

rjek@trite:~$ gcc tst.c
tst.c: In function ‘main’:
tst.c:3: warning: incompatible implicit declaration of built-in
function ‘printf’ tst.c:3: error: ‘M_PI’ undeclared (first use in this
function) tst.c:3: error: (Each undeclared identifier is reported only
once tst.c:3: error: for each function it appears in.)

M_PI is defined in math.h; if this doesn't generate a binary for you,
it's not including math.h by default.

B.

M_PI is not defined:

main()
{
printf("%f", M_PI);
}

[] gcc tst.c
tst.c: In function `main':
tst.c:3: error: `M_PI' undeclared (first use in this function)
tst.c:3: error: (Each undeclared identifier is reported only once
tst.c:3: error: for each function it appears in.)

Note that I don't get any error/warning on the printf like you do.

Also, tried this which works fine, despite needing -lm but not having
math.h declared. Any ideas why this is happening? Do exp, pow and cos
not need declarations?

main()
{
printf("exp(3.3) %f \n", exp(3.3));
printf("2^5 %f \n", pow(2,5));
printf("cos(almost pi) %f \n",cos(3.14));
}
[]$ gcc mathtest.c -lm
[]$ ./a.out
exp(3.3) 27.112639
2^5 32.000000
cos(almost pi) -0.999999
 
R

Rob Kendrick

Also, tried this which works fine, despite needing -lm but not having
math.h declared. Any ideas why this is happening? Do exp, pow and cos
not need declarations?

What happens is what I described; your compiler is "inventing" them,
and assuming the take an int, and return an int.

B.
 
E

Eric Sosman

What headers does GCC include by default and is there any way to
change the behavior?

It seems on my system that math.h is being included by default and I
don't need to include it in source for
math functions. The code below compiles just fine as long as I
include the math library -lm.
I don't even include stdio.h and it works just fine. I'm not sure I
like this.

gcc version 3.4.6 20060404 (Red Hat 3.4.6-11)

gcc -lm mathtest.c

main()
{
printf("exp(3.3) %f \n", exp(3.3));
printf("2^5 %f \n", pow(2,5));
}

This code snippet is wrong, r-o-n-g, wrong. Does gcc
know it's r-o-n-g? Yes! Even with no command-line flags
to crank up warning levels, I get:

foo.c: In function 'main':
foo.c:3: warning: incompatible implicit declaration of built-in function
'printf'
foo.c:3: warning: incompatible implicit declaration of built-in function
'exp'
foo.c:4: warning: incompatible implicit declaration of built-in function
'pow'

With -Wall added, gcc becomes chattier:

foo.c:2: warning: return type defaults to 'int'
foo.c: In function 'main':
foo.c:3: warning: implicit declaration of function 'printf'
foo.c:3: warning: incompatible implicit declaration of built-in function
'printf'
foo.c:3: warning: implicit declaration of function 'exp'
foo.c:3: warning: incompatible implicit declaration of built-in function
'exp'
foo.c:4: warning: implicit declaration of function 'pow'
foo.c:4: warning: incompatible implicit declaration of built-in function
'pow'
foo.c:5: warning: control reaches end of non-void function

Neither of these results gives evidence to support the idea
that gcc includes headers by default, nor that there is any
behavior you should seek to change. Except your own, of course,
for writing such r-o-n-g code to begin with.
 
W

William Hughes

 What headers does GCC include by default and is there any way to
change the behavior?

 It seems on my system that math.h is being included by default and I
don't need to include it in source for
 math functions. The code below compiles just fine as long as I
include the math library -lm.
 I don't even include stdio.h and it works just fine. I'm not sure I
like this.

gcc version 3.4.6 20060404 (Red Hat 3.4.6-11)

gcc -lm mathtest.c

main()
{
printf("exp(3.3) %f \n", exp(3.3));
printf("2^5 %f \n", pow(2,5));

}

No, math.h is not being included. What is happening
is that if you use a function without a declaration,
the function is assumed to be int f(), that is to
return int and take an unknown number of parameters.
For printf this is fine, but exp and pow return doubles.
In some cases lying to the compiler about the return
value of a function will cause big problems. This is
not one of them. The compiler thinks that the functions
are returning an int, so it does not apply any default
promotion. You are telling printf to expect a double.
The functions that you are linking to do return doubles
so you were unlucky and things worked. The header math.h
tells the *compiler* what to expect when the code is run.
The -lm tells the *linker* where to find the code.
Crank up your warning levels until you are warned about
implicit declaration.

- William Hughes
 
C

crisgoogle

On Thu, 29 Apr 2010 09:04:20 -0700 (PDT)

John <[email protected]> wrote:

<un-snip>
main()
{
printf("exp(3.3) %f \n", exp(3.3));
printf("2^5 %f \n", pow(2,5));
printf("cos(almost pi) %f \n",cos(3.14));
}
What happens is what I described; your compiler is "inventing" them,
and assuming the take an int, and return an int.

Almost. They implicitly return int, but take as arguments (double),
(int, int), and (double), respectively.
 
K

Kenny McCormack

<un-snip>
main()
{
printf("exp(3.3) %f \n", exp(3.3));
printf("2^5 %f \n", pow(2,5));
printf("cos(almost pi) %f \n",cos(3.14));
}


Almost. They implicitly return int, but take as arguments (double),
(int, int), and (double), respectively.

This thread is actually kinda interesting - although, of course, CLC can
not go beyond the stock "It's UB - you are a schmuck!" type answers.

When I ran the tests, I noticed a few interesting things (that are, as I
note above, beyond the ken of CLC):

1) All 4 of the non-declared functions (printf, exp, pow, cos) generate
a message like:
x.c:3: warning: incompatible implicit declaration of built-in function '...'
This does seem to support OP's original idea that math.h is somehow
being magically included. I.e., the compiler does seem to "know" about
these functions in some way. Obviously, it is unlikely that it is
actually including the file (although the standard does not forbid it
from doing so), but it seems that GCC somehow considers these to be
"built-in" functions.

2) Failing to supply -lm results in the linker complaining about 'exp'
and 'cos', but not, interestingly, 'pow', even though 'man pow' does
mention math.h and -lm.

--
No, I haven't, that's why I'm asking questions. If you won't help me,
why don't you just go find your lost manhood elsewhere.

CLC in a nutshell.
 
J

John

No, math.h is not being included.  What is happening
is that if you use a function without a declaration,
the function is assumed to be int f(), that is to
return int and take an unknown number of parameters.
For printf this is fine, but exp and pow return doubles.
In some cases lying to the compiler about the return
value of a function will cause big problems.  This is
not one of them.  The compiler thinks that the functions
are returning an int, so it does not apply any default
promotion. You are telling printf to expect a double.
The functions that you are linking to do return doubles
so you were unlucky and things worked.  The header math.h
tells the *compiler* what to expect when the code is run.
The -lm tells the *linker* where to find the code.
Crank up your warning levels until you are warned about
implicit declaration.

                      - William Hughes

Thanks for the responses. I understand what is happening now.
We are porting some code between several systems with different
versions of GCC and the Intel compiler and I wanted to understand
the behavior. btw, I do know that is not good code :) I didn't write
it but we are having to deal with it. A programmer left off the
math.h in some of the routines and it compile/worked just fine.
 
K

Kenny McCormack

William Hughes said:
In some cases lying to the compiler about the return
value of a function will cause big problems. This is
not one of them. The compiler thinks that the functions
are returning an int, so it does not apply any default
promotion. You are telling printf to expect a double.
The functions that you are linking to do return doubles
so you were unlucky and things worked.

The implication behind this statement is not true.

Try it with your own defined functions, with and without a prototype.

The reason it works with the built-in type functions is because gcc
"knows" about them.

--
(This discussion group is about C, ...)

Wrong. It is only OCCASIONALLY a discussion group
about C; mostly, like most "discussion" groups, it is
off-topic Rorsharch [sic] revelations of the childhood
traumas of the participants...
 
W

William Hughes

Do exp, pow and cos
not need declarations?


Nope, like any functions, if used without a declaration
they are assumed to return int and take an arbitrary number
of arguments. This is wrong, but you are unlucky and things
work because the functions you are actually using (the ones
the linker finds) return double, and the compiler does not
need to use the fact that you told it (implicitly) the the functions
return int.


- William Hughes
 
E

Eric Sosman

[...]
Thanks for the responses. I understand what is happening now.
We are porting some code between several systems with different
versions of GCC and the Intel compiler and I wanted to understand
the behavior. btw, I do know that is not good code :) I didn't write
it but we are having to deal with it. A programmer left off the
math.h in some of the routines and it compile/worked just fine.

As others have suggested, crank up the warning levels.
With gcc, I'd recommend "-Wall -W -ansi -pedantic" (or use
"-std=c99" instead of "-ansi") as a starting point. Some code
isn't squeaky-clean enough for "-pedantic" and you might wind
up taking it out later, but as a screen for sloppy source it's
a good beginning.

Also, look into the various lint-like tools you can find.
Even if you can't find a lint specifically for Platform X, a
Platform Y lint will be helpful in catching some portability
problems.
 
H

Huibert Bol

John said:
main()
{
printf("exp(3.3) %f \n", exp(3.3));
printf("2^5 %f \n", pow(2,5));
}

Some more GCC fun, the program

char aap[(int) pow (2, 3)];

main()
{
printf("%zu\n", sizeof aap);
}

compiles with just some warnings and prints, as expected, 8.

(Using GCC 4.3.2; I believe 4.5 added a warning about non-standard
constant expression for cases like this.)
 
W

William Hughes

Apparently, this is false. Gcc does not produce working
code if it does not know that the function returns double.
It would appear that gcc knows the return types of the standard
functions, I suspect that it is also inlining code.
Thanks for the responses. I understand what is happening now.
We are porting some code between several systems with different
versions of GCC and the Intel compiler and I wanted to understand
the behavior. btw, I do know that is not good code :) I didn't write
it but we are having to deal with it. A programmer left off the
math.h in some of the routines and it compile/worked just fine.


Well, probably all you have to do is add math.h to the files
where it is missing. (It is possible that you are *really*
unlucky and this will change the behaviour, but this does not
seem likely). If you crank up the warnings you will be told when
math.h was left off, so you can add it back gradually if you want.

- William Hughes
 
K

Keith Thompson

Seebs said:
In general, so far as I know, there's no particular guarantee that standard
library functionality *won't* be included by default, only that it *will*
if you include the headers.

I don't see a problem.

C99 guarantees that if you call a standard library function without
a visible declaration, you'll get a diagnostic. You *can* provide
the declaration yourself, but it's insane not to just #include the
appropriate header unless you have a specific reason not to.
 
K

Keith Thompson

Rob Kendrick said:
Try this:

rjek@trite:~$ cat > tst.c
main()
{
printf("%f", M_PI);
} [...]

M_PI is defined in math.h; if this doesn't generate a binary for you,
it's not including math.h by default.

M_PI is a non-standard extension.
 
W

William Hughes

C99 guarantees that if you call a standard library function without
a visible declaration, you'll get a diagnostic.  You *can* provide
the declaration yourself,



Yes, but you cannot override the function with one of your
own. I was playing around (gcc 4.1.1) and I found that I could
override exp() with int exp (double) but if I used double exp
(double) I got the system exp().

- William Hughes
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,769
Messages
2,569,582
Members
45,070
Latest member
BiogenixGummies

Latest Threads

Top