Can't get my C programs to compile if I use math.h

/tmp/ccNLmJiD.o: In function main': /home/me/bin/worm.c:32: undefined reference to exp2l’
collect2: error: ld returned 1 exit status

gcc (SUSE Linux) 4.7.2 20130108 [gcc-4_7-branch revision 195012]
GNU ld (GNU Binutils; openSUSE 12.3) 2.23.1

What do you think? I’ve got no clue why ld returns 1.

PS: Come to think of it, if I use the diet wrapper for dietlibc and printf I get an error too:

diet 0.31

diet gcc arg.c

/opt/dietlibc/lib-x86_64/libc.a(printf.o): In function printf': printf.c:(.text+0x13): undefined reference to __builtin_stdarg_start’
collect2: error: ld returned 1 exit status

On 2013-08-19 22:46, ballsystemlord wrote:
>
> /tmp/ccNLmJiD.o: In function `main’:

/home/me/bin/worm.c:32: undefined reference to `exp2l’
> collect2: error: ld returned 1 exit status

You will have to post a sample.c program with the problem; and do so
inside code tags - the ‘#’ button in the editor bar.


Cheers / Saludos,

Carlos E. R.
(from 12.3 x86_64 “Dartmouth” at Telcontar)

On Mon, 19 Aug 2013 20:46:02 +0000, ballsystemlord wrote:

> What do you think?

I think it would be useful to see your code (as Carlos said), your
makefile (if you’re using one) and/or the command you’re running to do
the compilation.

Jim

Jim Henderson
openSUSE Forums Administrator
Forum Use Terms & Conditions at http://tinyurl.com/openSUSE-T-C

You need to use -lm to link with math library.

On 2013-08-19, ballsystemlord <ballsystemlord@no-mx.forums.opensuse.org> wrote:
>
> /tmp/ccNLmJiD.o: In function `main’:

/home/me/bin/worm.c:32: undefined reference to `exp2l’
> collect2: error: ld returned 1 exit status

Just a quick question. With your header inclusion perceptive, I just want to confirm you’re not a C++ programmer? If you
are, then you just need the cmath header:

e.g.


# include <cstdlib>
# include <iostream>
# include <cmath>

using namespace std;

//----------------------------------------------
int main()
{
// YOUR CODE HERE
return 0;
}

How clumsy of me…

The original:

#include <stdbool.h>
#include <stdio.h>
#include <signal.h>
#include <stdlib.h>
#include <math.h>

#define NUMBER "The resualting number is %lli
"#define TMN "inchworm: too many numbers."
#define TFN "inchworm: too few numbers."
#define VERSION "inchworm: version is 0.0.1"
#define HELP "
Usage: inchworm [options] [1s and 0s]

 -h, --help		"\
"displays this help text.
 -V, --version		output the version information "\
"and exit

 Place space seperated 1s for yeses and 0s for nos to seperate "\
"the 1s so as to create a binary filter for the filter configuration file.
"

//Size Of PrintF
#define SOPF(a) ((signed int)(sizeof(a) - 1))
#define SOPF2(a, b) ((signed int)(sizeof(a) + sizeof(b) - 1))

/** This is just a simple program to dynamically alow a user to create a mask by
* taking advantage of argv.
*/

int main(int argc, char **argv)
{
    int iargc;
    unsigned long long int number = 0;
    
    switch(argv = 1)
    {
        case true:
            ( SOPF( TFN ) != printf( TFN )) ? raise(SIGHUP): \
            exit(EXIT_FAILURE);
            break;
        default
            break;
    }
    
    switch((bool)strncmp("-h", argv[iargc], 2) || \
                (bool)strncmp("--help", argv[iargc], 6) || \
                (bool)strncmp("--usage", argv[iargc], 7))
    {
        case false:
            ( SOPF( HELP ) != printf( HELP )) ? raise(SIGHUP): \
            exit(EXIT_SUCCESS);
        default:
            break;
    }
    
    switch((bool)strncmp("-V", argv[iargc], 2) || \
                (bool)strncmp("--version", argv[iargc], 9))
    {
        case false:
            ( SOPF( VERSION ) != printf( VERSION )) ? raise(SIGHUP): \
            exit(EXIT_SUCCESS);
        default:
            break;
    }
    
    for(iargc = 1; iargc < argc; iargc++)
    {
        switch('1' == argv[iargc][0])
        {
            case false:
                switch(65 < iargc)
                {
                    case true:
                        ( SOPF( TMN ) != printf( TMN )) ? raise(SIGHUP): \
                        exit(EXIT_FAILURE);
                    default:
                        break;
                }
                number = number + \
                (unsigned long long int) exp2l((long double)iargc);
                break;
            default:
                break;
        }
    }

    ( SOPF2( NUMBER, number ) != printf( NUMBER,  number)) ? raise(SIGHUP): \
    exit(EXIT_SUCCESS);

    return(0);
}


I’m not using a make file yet (It’s small.)

gcc -wall -other-warning-wall-like-options -g inchworm.c

I thought that I should ask here as it seems kind of a strange bug.
Yes I’m using C not C++ as I’ve herd it’s bloated and I prefer functional programming anyhow.

And did you try to add “-lm” to the compiler line as was already suggested?
The math functions are contained in libm, which you explicitely have to link against if you want to use them.

From “man exp2l”:

NAME
       exp2, exp2f, exp2l - base-2 exponential function


SYNOPSIS
       #include <math.h>


       double exp2(double x);
       float exp2f(float x);
       long double exp2l(long double x);


       Link with -lm.

On Wed, 21 Aug 2013 20:46:01 +0000, ballsystemlord wrote:

> Code:
> --------------------
> gcc -wall -other-warning-wall-like-options -g inchworm.c
> --------------------
>
>
> I thought that I should ask here as it seems kind of a strange bug.

Not a bug, you just haven’t (as wolfi said) included the library in the
command to compile it.

Jim

Jim Henderson
openSUSE Forums Administrator
Forum Use Terms & Conditions at http://tinyurl.com/openSUSE-T-C

Hey, I’ll try that.

Ok, it works now! I think it’s strange though that -lm needs to be at the end of the command line, I mean, the order of options is even stated gcc [options] [files].
But what about diet not liking stdio.h?

Have you tried to put it anywhere else? It should work as well.
You can intertwine options and files.

Btw, “man gcc” says this here:

SYNOPSIS
       gcc -c|-S|-E] -std=standard]
           -g] -pg] -Olevel]
           -Wwarn...] -pedantic]
           -Idir...] -Ldir...]
           -Dmacro=defn]...] -Umacro]
           -foption...] -mmachine-option...]
           -o outfile] @file] infile...


       Only the most useful options are listed here; see below for the
       remainder.  g++ accepts mostly the same options as gcc.

But what about diet not liking stdio.h?

What problem do you have with stdio.h?

Your code has other problems though:

switch (argv = 1)

This should be

switch (argc == 1)

But why are you using “switch” instead of a simple “if”?

And you should #include <string.h> as well for “strncmp()”.

Ah, ok. I’ve seen it now:

According to this: Bug #381215 “undefined reference to `__builtin_stdarg_start'” : Bugs : dietlibc package : Ubuntu it seems to be an incompatibility between diet and newer gcc versions.
Use the following patch:

diff -pruN dietlibc-0.31.orig/include/stdarg.h dietlibc-0.31/include/stdarg.h
--- dietlibc-0.31.orig/include/stdarg.h    2009-05-28 10:53:06.000000000 +0200
+++ dietlibc-0.31/include/stdarg.h    2009-05-28 10:55:12.000000000 +0200
@@ -9,7 +9,11 @@ __BEGIN_DECLS
 #if (__GNUC__ > 2) || ((__GNUC__ == 2) && (__GNUC_MINOR__ >= 96))
 
 typedef __builtin_va_list va_list;
+#if (__GNUC__ > 4) || ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 4))
+#define va_start(v,l)    __builtin_va_start((v),l)
+#else
 #define va_start(v,l)    __builtin_stdarg_start((v),l)
+#endif
 #define va_end        __builtin_va_end
 #define va_arg        __builtin_va_arg
 #define __va_copy(d,s)    __builtin_va_copy((d),(s))

Or download and install a newer dietlibc version, the latest one is 0.33 AFAICS, which should work.
diet libc - a libc optimized for small size

On Thu, 12 Sep 2013 17:46:03 +0000, wolfi323 wrote:

> But why are you using “switch” instead of a simple “if”?

I would concur with this - switch() is typically only used if there are
multiple options, not to test equality to one specific value.

ballsystemlord, it would be very important to learn to use the proper
structures in your coding - forming bad habits like misusing switch()
early on (and mixing up equality tests and variable assignment) is not
good.

Jim


Jim Henderson
openSUSE Forums Administrator
Forum Use Terms & Conditions at http://tinyurl.com/openSUSE-T-C

I never said my code was bug free I think it would at the very least be rather arrogant to do so.
I use switch statements instead of if statements because as far as I know it doesn’t matter which you use and I think it would be a good idea to practice using the switch statement least, when I actually need it, I forget the break or something stupid like that.

Thanks for pointing the argc problem out though, true, I fixed it before reading this forum, but thanks anyway.

I’ll install the latest version of diet and try it.

On Fri, 20 Sep 2013 13:46:03 +0000, ballsystemlord wrote:

> hendersj;2584453 Wrote:
>> On Thu, 12 Sep 2013 17:46:03 +0000, wolfi323 wrote:
>>
>> > But why are you using “switch” instead of a simple “if”?
>>
>> I would concur with this - switch() is typically only used if there are
>> multiple options, not to test equality to one specific value.
>>
>> ballsystemlord, it would be very important to learn to use the proper
>> structures in your coding - forming bad habits like misusing switch()
>> early on (and mixing up equality tests and variable assignment) is not
>> good.
>>
>> Jim
>>
>>
>>
> I never said my code was bug free I think it would at the very least be
> rather arrogant to do so.

And we never said you said that.

> I use switch statements instead of if statements because as far as I
> know it doesn’t matter which you use and I think it would be a good idea
> to practice using the switch statement least, when I actually need it, I
> forget the break or something stupid like that.

It’s not generally a good way to learn to use things improperly - that
reinforces “bad” behaviours.

You want to practice using things the right way - that reinforces “good”
behaviours.

Trust me on this - I’ve worked in technical education for over a decade.
I would never encourage a student to practice something that reinforced
poor practices. Doing so is bad for one’s ability to learn, because it
reinforces doing things in an improper way.

There is a difference in how switch() and conditional if…then code is
compiled, and there are performance implications for both.

There also are program readability implications for using the proper
structures in your coding. If you end up working on a project with
multiple other developers, you want code that they can understand (and
vice versa). Doing things in a non-standard way is going to (a) lose you
respect from the other developers, and (b) make your code more difficult
for them to maintain, because they’ll spend a fair amount of time looking
at the code, shaking their head, and asking “what on earth was he
thinking?”.

It’s always best to learn things and form good habits out the gate when
learning to code - and to avoid learning and reinforcing bad habits.

Jim

Jim Henderson
openSUSE Forums Administrator
Forum Use Terms & Conditions at http://tinyurl.com/openSUSE-T-C

Hi,
sorry to say, but I think that probably everyone in this thread is wrong.

Lets got back to:

In this - the 6th line of main() - there is the command:

switch(argv = 1)

This is a weird bug, possible only in plain C !
(I once had a tool running under MacOS that checked for that kinds of bugs!).

In the above line of code,

argv = 1

within the switch, is a valid C statement for an assignment of the value 1 to argv,
which usually is of type

void *argv];

So the valid address/pointer in the variable

void **argv

is replaced by the arbitrary value of 1,
even before the switch is carried out.

So this may result in any kind of arbitrary and strange errors,
because the address of 0x1 probably doesn’t point to something meaningful
(or will point to garbage, to use the words of Kernighan and Ritchie).

Anyway, it doesn’t make any sense to compare `argv’ to anything.

ballsystemlord, you probably meant to compare argc !

A reasonable peace of code may rather look like this:

while (argc > 1) .....

The same trap would be a C statement like

if (x = 8)

which would assign 8 to x before the comparison (the if statement)
instead of the C statement

if (x == 8)

which would indeed compare the value of x to 8, without assigning anything beforehand!

Good luck
Mike

???
That’s a bold statement.
Where was everybody wrong?

But that makes you wrong as well, because you effectively say the same thing that I already did. (with a better explanation though… :wink: )

Anyway, it doesn’t make any sense to compare `argv’ to anything.

ballsystemlord, you probably meant to compare argc !

A reasonable peace of code may rather look like this:

while (argc > 1) .....

Didn’t I already point this out?
And “while (argc > 1)” doesn’t really make sense either, since argc isn’t changed anywhere.

Sorry, didn’t get that !

Mike

Hi again,

That isn’t necessarily true, besides.

In C it isn’t unusual (I have samples of code for that) to decrement the value of argc while working on the arguments passed by the command line,
in order to spare (or to avoid introducing) an additional integer variable.

Best wishes
Mike


switch(argv = 1)
{
case true:
( SOPF( TFN ) != printf( TFN )) ? raise(SIGHUP): \
exit(EXIT_FAILURE);
break;
default
break;
}

On 2013-09-12, Jim Henderson <hendersj@no-mx.forums.opensuse.org> wrote:
> On Thu, 12 Sep 2013 17:46:03 +0000, wolfi323 wrote:
>
>> But why are you using “switch” instead of a simple “if”?
>
> I would concur with this - switch() is typically only used if there are
> multiple options, not to test equality to one specific value.
>
> ballsystemlord, it would be very important to learn to use the proper
> structures in your coding - forming bad habits like misusing switch()
> early on (and mixing up equality tests and variable assignment) is not
> good.
>
> Jim

Although Jim is of course right, there’s a execution optimisation justification for the use of if rather than switch in
the case. Let’s assume the expression inside the switch expression was (argv == 1), then the by-case comparison, when
translated to assembler, would result in unnecessary boolean calculation (i.e.: (argv == 1) == true). For this reason,
conditional branching based purely on the value of a single boolean variable should only ever by coded using an if–else
statement.