C: linker command failed with exit code 1

You have the following line of code:

int lookup (const struct entry dictionary[], const char search[], const int entries);

Inside the main function. There are 2 major problems with this.

  1. Function declarations cannot appear inside of another function. The line I quoted needs to appear outside of your main function as follows:int lookup(.....) //code here int main(...) { //more code here }
  2. Even though you declare the function “lookup”, you never define it. This is probably what is causing the linker error. The compiler compiles all the functions, and then the linker goes to link the functions together (so to speak) and finds that, although the function “lookup” is declared and then later called, it doesn’t really exist anywhere! (as far as I know, the function “lookup” doesn’t exist in stdlib.h or stdio.h). This prevents the linker from doing its job.

To recapitulate, your code should be reorganized as follows:

#include <stdio.h>
#include <stdlib.h>

int lookup (const struct entry dictionary[], const char search[], const int entries)
{
    //lots of code belongs in here, but that's for you to figure out :)
}

int main (int argc, char *argv[]) {
    struct entry {
        char word[15];
        char definition[100];
    };

    const struct entry dictionary[100] = 
    {{"aardvark", "a burrowing African mammal"},
    {"abyss", "a bottomless pit"},
    {"acumen", "mentally sharp; keen"},
    {"addle", "to become confused"},
    {"aerie", "a high nest"},
    {"affix", "to append; attach"},
    {"agar", "a jelly made from seaweed"},
    {"ahoy", "a nautical call of greeting"},
    {"aigrette", "an ornamental cluster of feathers"},
    {"ajar", "partially opened"}};

    int entries = 10;
    int entryNumber;
    //**REMOVE THIS LINE**  Move it up top....
    //int lookup (const struct entry dictionary[], const char search[], const int entries);

    if (argc != 2)
    {
        fprintf (stderr, "No word typed on the command line.\n");
        return EXIT_FAILURE;
    }

    entryNumber = lookup (dictionary, argv[1], entries);

    if (entryNumber != -1)
        printf("%s\n", dictionary[entryNumber].definition);
    else
        printf("Sorry, %s is not in my dictionary.\n", argv[1]);

    return EXIT_SUCCESS;
}

I hope this helps. If you do not understand what a “linker” does or why this is important, leave a comment and I will edit my answer accordingly. Understanding linkers and compilers is one of the many factors that separates mediocre C programmers from great C programmers!


I think it would be useful at this point to explain what a linker is. Before we get to that, though, it’s important to understand what your compiler does and what a compiled program really is.

Based on the code you posted in your question, I think it’s safe to assume that you have used a compiler more than once :). I’m going to say a few things you already know, but stick with me. The “.c” and “.h” files you have describe algorithms. These files are easy for humans to read and edit, however, your computer can have a difficult time extracting meaning from them. In order for your computer to “run” the program in these files, the algorithms need to be converted to a language that your computer understands. This language, called “machine language” is difficult for humans to write in, so we write in C or C++, and convert our C and C++ programs into “machine language” using a compiler.

Now, the function of the linker here is subtle but very important. It’s easy for a beginner to think that a linker is totally unnecessary: if the compiler converts the C to “machine language”, then the job is over, right? well… not quite.

You see, every little bit of “machine language” in your compiled program has a memory address. Consider the following toy example:

#include <stdio.h>

int addnums(int numbers[], int length)
{
    int total = 0;
    for(int i = 0; i < length; i++)
    {
        total += numbers[i];
    }
    
    return total;
}

int main(int argc, char** argv)
{
    int mynums[] = {1, 2, 3, 4, 5};
    int total = addnums(mynums, 5);
    printf("the total of the array is %i\n", total);
    return 0;
}

If we were to look at the machine code for this toy program, we would see that each function has a starting point and an ending point in your computer’s memory. This means that each function has an address where it starts. When your computer executes the line

int total = addnums(mynums, 5);

It needs to “jump” to a different part of the machine code. “int main()” might start at address 100, and “int addnums()” is at address 50. Your computer needs to execute the machine code at address 50 when it reaches this line.

The compiler does not concern itself with the addresses of the functions. It just compiles the code, and leaves it up to another program to put the right addresses into the machine code. If the linker says something like

symbol(s) not found

it means that the linker does not know the address for a certain function. This is usually because the function in question was never declared or defined. If the linker were to produce an executable from this code, your computer would reach the line

int total = addnums(mynums, 5);

and say “Huh??? where do I go??” Without an address to jump to for the “int addnums()” function, your cpu would be utterly lost.

and your program would mysteriously crash.

The linker saves you this heartache by dropping an error and stopping the compilation process. In my amateur days of programming embedded systems, I had this problem a few times, and it was a nightmare to debug.

Hope this helps. Tell me if my explanation is bad.

Leave a Comment