Thread: undefined reference to ...

  1. #1
    DeletedUserAccount
    Guest

    undefined reference to ...

    Hey, I am new to both these forums and C in general, so I might be overlooking something simple. If that's the case, sorry, but Google searches got me nothing. Here's the problem:

    I am going to Project Euler's problems, and am hitting a wall with both Project 7 and Project 3. Both of those involve deciding whether a number is a prime, which I have implemented with an additional function that looks like this:

    Code:
    /*		Prime Number Checker
     * Takes an integer as an argument
     * Returns 1 if the integer is prime
     * Returns 0 if the integer is composite
     */
    
    int is_prime(int n)
    {
    	int i;
    	for (i = 2; i < sqrt(n); i++)
    	{
    		if ( n%i == 0 && n > 3)
    		{
    			return 0;
    		}
    	}
    	return 1;
    }
    There may be a more efficient way to implement this, but I think this should work. I have #included <math.h> as well. Here is how the rest of my ideas fit into this:

    I have a 003.c (007.c too, but that's irrelevant for now) file in my .../003 folder, as well as a soft link functions.h to .../Functions/functions.h, where my is_prime function is. I've included <math.h> and "functions.h in the 003.c. Somehow functions.h compiles with no problems, but 003.c gives me the
    Code:
    undefined reference to 'sqrt'
    There is a little more text to the warning, but I don't see how it could be helpful or relevant. I'll paste it if needed.

    Any thoughts?

  2. #2
    and the Hat of Guessing tabstop's Avatar
    Join Date
    Nov 2007
    Posts
    14,336
    1) If you're compiling functions.h, that's ... interesting.

    2) Many systems require you to link in the math library separately, so you would do that in the same way you link any library (i.e. for cc or gcc, you need -lm).

  3. #3
    Registered User
    Join Date
    May 2010
    Location
    Naypyidaw
    Posts
    1,314
    If it's compiler error, you should tell us what compiler you are using.
    You probably need to link with math library,
    for gcc, gcc -lm foo.c

  4. #4
    Registered User \007's Avatar
    Join Date
    Dec 2010
    Posts
    179
    Yea, most likely forgot to link it. I always forget to link stuff like pthreads and math.

  5. #5
    DeletedUserAccount
    Guest
    Ah, I didn't know I had to link anything =\

    But yes, I am using gcc. functions.h was not compiling for a while too, but it turns out I had just forgotten to include the headers.

    003.c compiles now, it gives me an output, I just need to fix my logic

  6. #6
    Registered User
    Join Date
    Nov 2010
    Location
    Long Beach, CA
    Posts
    5,909
    Glad to see you're reusing your code, but you're heading down the wrong track with by putting code in .h files. As tabstop hinted, compiling a .h file is not a good idea. When you're going to reuse code, and you go including header files in multiple .c files for one project/executable, you will run into problems with redefined symbols. Header files shouldn't contain any function or variable definitions (actual code or allocated space). They should pretty much only contain function and variable declarations (using the extern keyword), typedefs, enums and preprocessor directives. All these should be inside an include guard to avoid problems with multiple inclusion of header files. Example:
    Code:
    /* prime.h */
    #ifndef __prime_h__
    #define __prime_h__  // this prevents multiple inclusions of foo.h
    
    // this tells the compiler about the function, and says the definition will be found in another file/translation unit
    extern int is_prime(int n);
    
    #endif
    
    
    
    /* prime.c */
    int is_prime(int n)
    {
    	int i;
    	for (i = 2; i < sqrt(n); i++)
    	{
    		if ( n%i == 0 && n > 3)
    		{
    			return 0;
    		}
    	}
    	return 1;
    }
    This approach will make it easier to move these functions into a library you can use with all your programs at a later time.

  7. #7
    Registered User
    Join Date
    Sep 2007
    Posts
    1,012
    Code:
    #ifndef __prime_h__
    #define __prime_h__
    User code should not create identifiers that begin with two underscores, as these are reserved for the implementation. For include guards, I'd recommend using some sort of prefix as a "namespace":
    Code:
    #ifndef MYPROJECT_HEADERNAME_H
    ...
    In fact, you should avoid leading underscores in general. There are some cases where they're OK, but it's easier to just not use them instead of remembering when it's OK.

    The reason you cannot (or should not: it's undefined behavior) use a leading underscore is because the implementation (that is, your compiler/library) has to be able to create some of its own identifiers (variable/function/macro names, essentially). For example, tolower() is often implemented as a macro that uses a lookup table; that lookup table, however, should not use a name that your program might use. The implementation is not allowed to step on your toes. So it's done something like this:
    Code:
    static int _lower_table[257] = { ... };
    #define tolower(c) _lower_table[(c) + 1];
    The implementation promises not to use names that you're allowed to use, and you're supposed to do the same thing. That way neither side clashes with the other.

  8. #8
    Registered User
    Join Date
    Nov 2010
    Location
    Long Beach, CA
    Posts
    5,909
    You're right. I learned the wrong way years ago...old habits are hard to break.

  9. #9
    DeletedUserAccount
    Guest
    I am not sure I understood you completely, anduril. Speaking in my terms, I would have functions.h include only declarations for all those things you mentioned, but the actual implementation for each one of them (e.g. is_prime()) would be somewhere else? If so, would I implement every single one of my functions in a separate file (e.g. prime.c), or...?

    Also, considering that I am just now making my baby steps into C, I'll need some time to get familiar enough with this process to feel comfortable with it. I appreciate the advice though

  10. #10
    -bleh-
    Join Date
    Aug 2010
    Location
    somewhere in this universe
    Posts
    463
    Quote Originally Posted by ArgentSun View Post

    Code:
    /*		Prime Number Checker
     * Takes an integer as an argument
     * Returns 1 if the integer is prime
     * Returns 0 if the integer is composite
     */
    
    int is_prime(int n)
    {
    	int i;
    	for (i = 2; i < sqrt(n); i++)
    	{
    		if ( n%i == 0 && n > 3)
    		{
    			return 0;
    		}
    	}
    	return 1;
    }
    This way is very slow when you go into large prime problem like problem #10, because you are iterating over the multiples of primes as well, which doesn't need to be checked at all. You can look at the the Sieve of Eratosthenes to generate primes quick.
    Last edited by nimitzhunter; 01-28-2011 at 01:10 PM.
    "All that we see or seem
    Is but a dream within a dream." - Poe

  11. #11
    Registered User
    Join Date
    Nov 2010
    Location
    Long Beach, CA
    Posts
    5,909
    Quote Originally Posted by ArgentSun View Post
    I am not sure I understood you completely, anduril. Speaking in my terms, I would have functions.h include only declarations for all those things you mentioned, but the actual implementation for each one of them (e.g. is_prime()) would be somewhere else? If so, would I implement every single one of my functions in a separate file (e.g. prime.c), or...?

    Also, considering that I am just now making my baby steps into C, I'll need some time to get familiar enough with this process to feel comfortable with it. I appreciate the advice though
    Yes, that's the idea. The actual code goes in the .c files. You can put more than one function in a .c file, but they should be fairly related if you do, e.g. helper functions or a family of functions, like sin(), cos() and tan(). The .h files are there to provide information about the functions and variables to other programs, but should contain no actual code.

  12. #12
    DeletedUserAccount
    Guest
    @nimitzhunter, I am afraid that while I know this algorithm, I haven't the slightest idea how to begin implementing it - other than using a stupidly large array to store all of the candidate divisors. Which doesn't sound't terribly efficient.

    I hit a different problem though. Apparently the number provided by Project Euler for this problem (n = 600,851,475,143) is too... weird... to be properly handled by C. Assigning it to a double, and printing it immediately after gives me 600,851,480,576 - which doesn't look like a rounding issue, but I may be wrong. So when I start looking for its prime divisors, the very first one my program returns is 2 - which is obviously wrong, seeing that my number ends with an odd digit.

    @anduril462, where would those .c files be located? Wherever I want them, or in some special folder C recognizes by default?

  13. #13
    -bleh-
    Join Date
    Aug 2010
    Location
    somewhere in this universe
    Posts
    463
    Quote Originally Posted by ArgentSun View Post
    @nimitzhunter, I am afraid that while I know this algorithm, I haven't the slightest idea how to begin implementing it - other than using a stupidly large array to store all of the candidate divisors. Which doesn't sound't terribly efficient.
    Yes, the array will be large. But not that large. Say, if you want to get all primes below "n", you can declare the seive vector of "n" bits and set all the bit to 1. This way you are trading space for time. I did this problem before, checking each number in the range [2,n] is not pretty when n is large.
    I hit a different problem though. Apparently the number provided by Project Euler for this problem (n = 600,851,475,143) is too... weird... to be properly handled by C. Assigning it to a double, and printing it immediately after gives me 600,851,480,576 - which doesn't look like a rounding issue, but I may be wrong. So when I start looking for its prime divisors, the very first one my program returns is 2 - which is obviously wrong, seeing that my number ends with an odd digit.

    Are you sure that's the correct return number? You want it to return 600,851,475,143, but you got 600,851,480,576 instead? For the second number, 2 is the correct factor.

    you can use unsigned long longj, or int64_t to store that number.
    Code:
    unsigned long long weird_num = 600851475143ULL;
    Last edited by nimitzhunter; 01-28-2011 at 01:26 PM.
    "All that we see or seem
    Is but a dream within a dream." - Poe

  14. #14
    and the Hat of Guessing tabstop's Avatar
    Join Date
    Nov 2007
    Posts
    14,336
    You will need to use either long long (if your system supports long long that is long enough) or some other multiple-precision setup to deal with numbers on the order of 10^12. (The given number would take 40 bits to express in binary, so if you've got a 64-bit integer type you're good, at least for now.)

  15. #15
    DeletedUserAccount
    Guest
    long long resolved the issue. The entire thing is finally complete, and I got the correct answer

    Thanks for the help, and expect to see more threads by me :P

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Getting an error with OpenGL: collect2: ld returned 1 exit status
    By Lorgon Jortle in forum C++ Programming
    Replies: 6
    Last Post: 05-08-2009, 08:18 PM
  2. Undefined Reference Compiling Error
    By AlakaAlaki in forum C++ Programming
    Replies: 1
    Last Post: 06-27-2008, 11:45 AM
  3. Screwy Linker Error - VC2005
    By Tonto in forum C++ Programming
    Replies: 5
    Last Post: 06-19-2007, 02:39 PM
  4. C OpenGL Compiler Error?
    By Matt3000 in forum C Programming
    Replies: 12
    Last Post: 07-07-2006, 04:42 PM
  5. c++ linking problem for x11
    By kron in forum Linux Programming
    Replies: 1
    Last Post: 11-19-2004, 10:18 AM