简体   繁体   中英

C Compilation error in Make but not GCC/G++

I've just started experimenting with C, but am having issues compiling a simple, single file application from the command line with Make (on Ubuntu 14.04.2). I've included math.h, but methods like ceil and sqrt are 'undefined' when using Make. It seems Make can't link the math.h library, but GCC/G++ seems to do just fine. What's going on here?

The C code is in a sample-fail.c:

#include <stdio.h>
#include <math.h>
#include <limits.h>

double sqrt(double x);
double ceil(double x);

//Checks if an array contains any values that evenly divide 'val'
int array_contains_divisor(int arr[], int len, int val)
{
    int i;

    for(i = 0; i < len; i++)
    {
        if(val % arr[i] == 0)
        {
            return 1;
        }
    }

    return 0;
}

//Finds the largest prime factor of 'value'. Returns -1 if the number is
//prime, 0 if invalid
int largest_prime_factor(long value)
{
    //1 and 0 are not prime, this function does not expect negatives
    //so anything less than 1 is an invalid value
    if( value <= 1L )
    {
        return 0;
    }

    double val = (double)value;

    double d_max = ceil( sqrt( val ) );

    if( d_max > INT_MAX )
    {
        //value is invalid because its square root exceeds the maximum 
        //capacity of an int (defined in limits.h)
        return 0;
    }

    int max = (int)d_max;

    int prime_len = (int)( d_max / 2 ) + 1;

    int primes[prime_len];

    int primes_curr_pos = 0;

    int i;

    for(i = 9; i < max; i+=2)
    {
        //check if it's a factor
        if( value % i != 0 )
        {
            continue;
        }

        //basic prime check - should be no need to check 2 because we
        //are skipping all the even numbers
        if( i % 3 == 0 || i % 5 == 0 || i % 7 == 0 )
        {
            continue;
        }

        //complete prime check (not including 2, 3, 5 and 7)
        if( array_contains_divisor( primes, primes_curr_pos, i ) )
        {
            continue;
        }

        primes[primes_curr_pos++] = i;
    }

    //if we've found no prime divisors, check the remaining primes
    //we skipped earlier.
    if( primes_curr_pos <= 0 )
    {
        if( value % 7 == 0)
        {
            primes[primes_curr_pos++] = 7;
        }
        else if( value % 5 == 0 )
        {
            primes[primes_curr_pos++] = 5;
        }
        else if( value % 3 == 0 )
        {
            primes[primes_curr_pos++] = 3;
        }
        else if( value % 2 == 0 )
        {
            primes[primes_curr_pos++] = 3;
        }
    }

    if( primes_curr_pos <= 0 )
    {
        //the value is prime, return -1;
        return -1;
    }
    else
    {
        return primes[primes_curr_pos - 1];
    }
}

int main(int argc, char *argv[])
{
    printf("The largest prime factor of 600851475143 is %d\n", 
        largest_prime_factor(600851475143));

    return 0;
}

Here is the Terminal output from trying to compile sample_fail.c with Make, and then with GCC/G++ (I just copied the steps I saw the Code::Blocks builder take for the GCC/G++ commands):

x@x-desktop:~/Documents/Random Scripts$ ./sample_fail
bash: ./sample_fail: No such file or directory
x@x-desktop:~/Documents/Random Scripts$ make sample_fail
cc     sample_fail.c   -o sample_fail
/tmp/ccGCCT0E.o: In function `largest_prime_factor':
sample_fail.c:(.text+0x98): undefined reference to `sqrt'
sample_fail.c:(.text+0xaf): undefined reference to `ceil'
collect2: error: ld returned 1 exit status
make: *** [sample_fail] Error 1
x@x-desktop:~/Documents/Random Scripts$ gcc -Wall -c sample_fail.c
x@x-desktop:~/Documents/Random Scripts$ g++ -o ./sample_fail ./sample_fail.o
x@x-desktop:~/Documents/Random Scripts$ ./sample_fail
The largest prime factor of 600851475143 is 6857
x@x-desktop:~/Documents/Random Scripts$ 

Thanks in advance for any help for this C newbie.

Solution (courtesy of user3629249 and Useless):

Updated my Makefile to read:

CFLAGS=-Wall -g
CC=gcc

sample_fail: sample_fail.c
    gcc -o sample_fail sample_fail.c -lm

clean:
    rm -f sample_fail

make sample_fail now works on the Terminal.

the link step of the compile/link sequence needs to be told '-lm' (lower case 'L') when

#include <math.h> 

is in the source code.

note ceil() and sqrt() prototypes are defined in math.h so should not have those prototypes overridden in the source code.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM