我刚刚开始尝试使用 C,但在使用 Make(在 Ubuntu 14.04.2 上)从命令行编译一个简单的单文件应用程序时遇到了问题。我已经包括了 math.h,但是像 ceil
和 sqrt
这样的方法在使用 Make 时是“未定义的”。似乎 Make 无法链接 math.h 库,但 GCC/G++ 似乎做得很好。这是怎么回事?
C 代码在 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;
}
这是尝试使用 Make 编译 sample_fail.c,然后使用 GCC/G++ 的终端输出(我只是复制了我看到 Code::Blocks 构建器为 GCC/G++ 命令执行的步骤):
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$
在此先感谢您对这位 C 语言新手的帮助。
解决方案(由 user3629249 和 Useless 提供):
将我的 Makefile 更新为:
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 现在可以在终端上运行。
最佳答案
编译/链接序列的链接步骤需要被告知'-lm'(小写'L')时
#include <math.h>
在源代码中。
注意 ceil() 和 sqrt() 原型(prototype)是在 math.h 中定义的,因此不应在源代码中覆盖这些原型(prototype)。
关于Make 中的 C 编译错误,但不是 GCC/G++,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30074834/