1

I am taking an Arduino course on Coursera and was required to write a program to list the first 6 Fibonocci number. Rather a trivial assignment so I decided to go a different route and calculate the numbers using the Golden Mean. However I cannot get the program to build using the Geany IDE on Linux Mint. The code compiles without error but won't build. It compiles without error on the Arduino also. But if I can't build it I can't submit it or test it.

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

double GoldenMeanA;
double GoldenMeanB;
int i;
double x;


int main()
{
    printf ("the Fibonocci numbers are   ");
    for ( i = 1; i < 7 ; i++ )
    {   GoldenMeanA = pow(1.61, i);
        GoldenMeanB = pow(-.61, i);
        x = (GoldenMeanA) - (GoldenMeanB) / (sqrt (5));
        printf("%f", x);
    }
    return 0;
}

I am a complete novice at C programming. These are the errors from Geany:

gcc -Wall -o "fibass2" "fibass2.c" (in directory: /home/q/Desktop/Learn C)
/tmp/ccXlfYCE.o: In function `main':
fibass2.c:(.text+0x45): undefined reference to `pow'
fibass2.c:(.text+0x95): undefined reference to `pow'
collect2: error: ld returned 1 exit status
Compilation failed.

I don't know what any of that means but I thought math.h was a built-in library. Shouldn't Geany know what in the heck "pow" is?

Jonathan Leffler
  • 730,956
  • 141
  • 904
  • 1,278
Mikech
  • 27
  • 8
  • Format your code properly. That is unreadable. – too honest for this site Jan 09 '16 at 20:28
  • Sorry about the poor formatting but the course I am taking doesn't teach us anything about formatting and neither does my text book. I did the best I could to make it readable. I do know Python formating. I will use that next time since there is no formating standard in C that I know of.. Sorry! I am new to stack overflow. – Mikech Jan 10 '16 at 22:00
  • There are various indentation standards in C. Just try this. None is like Python - for good reasons. Do not try to format C Python-style! There is something called search providers which allow to search for phrases like "C indentation style". – too honest for this site Jan 10 '16 at 22:27
  • 1
    OK will do. The reason I didn't do something as obvious as Google it is because I was told that C had no formating style. – Mikech Jan 10 '16 at 22:46
  • True that it does not have one as prescriptive as Python, but in fact that is a plus point! It means that you can use an *unlimited* amount of spaces and returns to format your code, to be as human-readable as possible. – Jongware Jan 10 '16 at 23:16
  • @Jongware: Depends. When I started with Python, I also hated being bound to a specific style. But the more I learned, the more I appreciated to be forced to properly indent. See C code here: Wouldn't forced proper indentation be often enough welcome? Problem is that C's grammer leaves more room for different styles. – too honest for this site Jan 10 '16 at 23:20
  • @Olaf: also true. But my C editors of choice both have a 'match braces' hotkey, so my personal style of indentation is just a matter of taste. Only *very* rarely I get caught by a non-matching braces typo. – Jongware Jan 10 '16 at 23:23
  • @Jongware: Python does not need braces or similar. For other language like Modula, there is also little discussion about correct indentation style. Although - like C - it does not use indentation as part of the grammar. And Python still leaves the number of spaces (or tabs) to the programmer - if it is consistent. – too honest for this site Jan 10 '16 at 23:28
  • Note that you should avoid global variables. All the variables in your program should be local to `main()`. Yes, they work outside. But there isn't another function that references them, much less another source file, so the variables should be local to the function that uses them. Use global variables when necessary, but only when necessary. Avoid them whenever possible – which is most of the time (but it would be a nuisance if `stdout` and `stderr` were not global variables, for example). – Jonathan Leffler Jan 10 '16 at 23:34
  • Thanks for the advice. I forgot that defining variables outside main makes them global. Good lesson for the future. I hope this doesn't break any rules, but since we are talking about formatting; does the compiler strip all the white space? Or does the formatting take up more memory? The Arduino has very little memory. – Mikech Jan 10 '16 at 23:44
  • There is no direct link between the size of your C program and the executable size. – Jongware Jan 11 '16 at 09:32

3 Answers3

2

You haven't linked the math library. The math library is not part of the standard library, which gcc links by default. So you need to link it yourself with -lm.

gcc -Wall -o fibass2 fibass2.c -lm 

The error you see are given by linker that it couldn't find the definition for pow() function. Including math.h only provides the necessary prototypes/declarations. It doesn't provide the actual library.

P.P
  • 117,907
  • 20
  • 175
  • 238
  • Thank you!! I appreciate you taking the time to help me. I will comment again if that solves the problem. – Mikech Jan 10 '16 at 22:02
  • That worked but has to be done in Geany for it to work in Geany – Mikech Jan 10 '16 at 22:44
  • The mathematical library very well is part of the C standard library! It is an implementation detail, however it is not automatically linked. How to properly link the standard libraries is just not part of the C standard. – too honest for this site Jan 10 '16 at 23:25
  • 1
    Note that some systems — for example, Mac OS X, and also it seems Arduino — include the functions from `` in the main C library, and the `-lm` is unnecessary. (It works; it's a dummy library that is effectively ignored.) Once upon a long time ago, in the days of optional floating-point hardware and different software libraries for math, it made sense to keep the maths library separate from the rest of the standard library. This was valid when Linux was first created, for example. One year, Linux (glibc) will recognize that the separate `-lm` is really a relic of a bygone era. – Jonathan Leffler Jan 10 '16 at 23:32
  • @JonathanLeffler: Arduino is not C. And an FPU still is not standard for most CPUs. Even if, it is not guaranteed to have full type-support (see ARM Cortex-M4F). So it still is a good idea only to link it only if needed. And that is a gcc/GNU libc issue, not Linux. – too honest for this site Jan 10 '16 at 23:33
  • @Olaf It's certainly desirable to have the commonly used libraries such as math, pthreads to be linked by default gcc or to a have as single lib in glibc. I suppose it's not important enough for anybody make the necessary changes (in glibc). And no, it's *not* good to have to link them separately and the way it is is mainly historical. I agree with what Jonathan said here. It only takes less than 2ms for the linking the math library on my system. – P.P Jan 11 '16 at 00:02
  • Actually. gcc only is a freestanding implementation, as it does not provide the full C standard library (that comes with `newlib`, glibc, etc). Thus, it is required only to provide few headers which do not require additional object files. Also the math library does not depenmd on the runtime-environment, but on the CPU. For instance, an FPUs might (some actually do) implement some of the functions in hardware, so the compiler can emit special instructions instead of function calls. Both reasons make it a good idea not to include it in the system-dependent library. – too honest for this site Jan 11 '16 at 08:48
1

I don't know what any of that means but I thought math.h was a built-in library. Shouldn't Geany know what in the heck "pow" is?

math.h is not a library; it is a header file. Very informally, a header file lets the compiler know what the declarations of function and constants are. Kind of like saying "yo, compiler, pow is a function that takes a two arguments of type double and returns a double".

The compiler, actually the parser, needs this information to check the semantic correctness of a statement...in particular checking that the appropriate number of arguments have been provided, and that the types are correct.

Now, the compiler, actually the linker, needs to find the definition of whatever you declare and use. Since you didn't provide a definition (i.e. the implementation of the function), the linker throws an error.

Hint: any time you see an error like "undefined reference" you have forgotten to implement a function you use, or forgotten to link the appropriate library (as l3x suggests).

N.B. I kept saying stuff like "the compiler, actually the linker" because most people refer to gcc as a compiler, but it is in fact a collection of programs that work together to transform source code to an executable (or library). At a minimum the following programs get involved:

  1. preprocessor (on a Linux system, this is normally cpp). This part deals with the preprocessor instructions like #include or #define. You can look at the output of the preprocessor by using the -E argument with gcc.

  2. parser (on a Linux system this is normally cc1 generally) This part deals with checking the semantics of the program, and producing an assembly language output. You can look at the output of this phase by using the -S argument with gcc.

  3. assembler (on a Linux system this is normally gas). This take the output from the parser can converts it into object code. You can look at the output of this phase using the -c argument with gcc (this is the first output that is not a straight text file).

  4. linker (on a Linux system this is normally ld). This takes multiple object files and links them together into a single executable. It also deals with dynamic linkage and sets the executable up so that libraries can be linked at run time.

Understanding what each of these programs do, and the types of error (and reasons) will make you life much easier when troubleshooting a build.

Jonathan Leffler
  • 730,956
  • 141
  • 904
  • 1,278
thurizas
  • 2,473
  • 1
  • 14
  • 15
  • WOW! You guys here at Stack Overflow are GREAT! Thank you so much!! They didn't teach us any of this in the course. It seems to me that this is what they should start with so you don't waste hours trying get something to work. Can you recommend a textbook that has this sort of information? My current textbook is meant for beginners and doesn't have this level of detail. – Mikech Jan 10 '16 at 22:03
0

The command line that I3x provided was correct. When I entered that I did not receive an error on the command line. However Geany would still not build the code and gave the same errors.

But I remembered seeing a place farther down the menu list in Geany under "Build" called "Set Build Commands." So I selected that. I have no idea what most of the options are but the second box was labeled "build" so I pasted the command from I3x into that box and saved it. WALLA. The program compiled and built without further issues. Once I could build and test it I found the program had logic issues which I fixed. Below is the final working code hopefully formated in a manner that Olaf will approve:

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

int main()
{
    double GoldenMeanA;
    double GoldenMeanB;
    int i;
    int F;
    float x;

    printf ("The Fibonocci numbers are   ");
    for ( i = 1; i < 7 ; i++ )
    {  
        GoldenMeanA = pow(1.6180339887, i);
        GoldenMeanB = pow(-.6180339887, i);
        x = ((GoldenMeanA) - (GoldenMeanB)) / (sqrt (5));
        F=(int)(x+0.1);
        printf("%d  ", F); 
    }
    return 0;
}

Also I apologize for thanking my mentors. I just read in the instructions for answers that I am not supposed to do that.

Mikech
  • 27
  • 8