Undefined reference to 'function' error in C

48,367

Solution 1

I guess you are compiling only main.c. You should also include ofdm.c.

$ gcc -Wall main.c ofdm.c -o output

Solution 2

Since you get this error for all your functions, it can't be a typo. My best guess is that you are not linking the two files.

If using gcc, this is done in the following way:

gcc -o main.o -c main.c
gcc -o ofdm.o -c ofdm.c
gcc -o program main.o ofdm.o

Note that -c means it should compile, but not try to create an executable. This means that linking is not done.

Once both files are compiled, you would then link them together.

Solution 3

When you're learning new things, it helps to learn one new thing at a time. Put your source code into version control, then simplify it to get a clean compile.

main.c

#include "ofdm.h"

int main(int argc, char *argv[])
{
  return 0;
}

ofdm.c

#include "ofdm.h"

void leftshift(short *bin,short *erg,int shifts, int len)
{
  int i;


  for(i = 0;i < len - shifts;i++)
  {
    erg[i] = bin[i + shifts];
  }
  for(i = len - shifts;i < len;i++)
  {
   erg[i] = 0;
  }
}

ofdm.h

#ifndef OFDM_H_INCLUDED
#define OFDM_H_INCLUDED

void leftshift(short *bin,short *erg,int shifts, int len);

#endif

Then, to compile with gcc . . .

$ gcc -Wall -c ofdm.c
$ gcc -Wall -c main.c
$ gcc -Wall *.o

That should give you a program that does nothing, successfully. Now you can start to build it up again from your version-controlled source.

  • Add one function at a time.
  • Edit it to get a clean compile.
  • Edit it to pass sane tests.
Share:
48,367
Admin
Author by

Admin

Updated on July 09, 2022

Comments

  • Admin
    Admin almost 2 years

    I created a header file called ofdm.h which includes all the function prototypes. Then I created a source file called ofdm.c, which includes the source code of all the functions declared in ofdm.h . After that I started coding in main.c, but when I run it I get the error: undefined reference to '(function name)'. I get this error for all my functions.

    Below you can find the source code of all my three files.

    ofdm.h

    #ifndef OFDM_H_INCLUDED
    #define OFDM_H_INCLUDED
    
    typedef struct {
        double real, img;
    } Complex;
    
    char** split(char *s, const char *delim);
    void parseComplex(Complex *c, char *line);
    
    void rbits(short* buf, int nbits);
    
    void printbinary(short* buf, int len);
    void printcomplex(Complex* buf, int len);
    
    long bin2dec(short *bin, int len);
    void dec2bin(long dec, short *bin, int len);
    void binaryadd(short *bin1, short *bin2, short *erg, int len);
    void leftshift(short *bin,short *erg,int shifts, int len);
    void binarymult(short *bin1, short *bin2, short *erg, int len);
    void binarypower(short *bin,short *erg,int power, int len);
    
    void scrambler(short *seed, short *input, short *output, int len, int seedlen);
    void encoder(short *input, short *output, int inputlen);
    
    void interleaver(short *input, short *output, int N_CBPS,int N_BPSC);
    void deinterleaver(short *input, short *output, int N_CBPS,int N_BPSC);
    
    void fixed_point(short* input, int nbits);
    void fixed_point_complex(Complex* input, int nbits);
    void defixed_point(short* input, int nbits);
    
    void BPSKmapping(short* input, short* output, int nbits);
    void BPSKdemapping(short* input, short* output, int nbits);
    void QPSKmapping(short* input, Complex* output, int nbits);
    void QPSKdemapping(Complex* input, short* output, int nbits);
    
    void IFFT_BPSK(short* input, Complex* output, Complex* twidder);
    void IFFT_QPSK(Complex* input, Complex* output, Complex* twidder);
    
    double uniform(double a, double b);
    double gauss(double mean, int SNRdb);
    
    void ChannelModel(Complex R[], Complex S[], int SNRdb);
    
    #endif
    

    ofdm.c

    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include <math.h>
    #include "ofdm.h"
    
    char** split(char* string, const char* delim)
    {
        char* p;
        int i = 0;
    
        char** array = malloc(strlen(string) * sizeof(char*));
        p = strtok(string, delim);
    
        while(p != NULL)
        {
            array[i] = malloc(sizeof(char));
            array[i++] = p;
            p = strtok(NULL, delim);
        }
    
        return array;
    }
    
    void parseComplex(Complex *cmplx, char *number)
    {
        char *copy = number;
    
        if(strchr(copy, ' ') != NULL)
        {
            char **result = split(copy, " ");
            cmplx->real = atof(*result++);
    
            char *sign = *result++;
            cmplx->img = atof(*result++);
    
            if(sign[0] == '-')
                cmplx->img = -(cmplx->img);
        }
        else if(strchr(copy, 'j') != NULL)
        {
            cmplx->real = 0;
            cmplx->img = atof(copy);
        }
        else
        {
            cmplx->real = atof(copy);
            cmplx->img = 0;
        }
    }
    
    void rbits(short* buf, int nbits)
    {
        int i;
    
        for(i = 0; i < nbits; i++)
            buf[i] = (rand() % 2);
    }
    
    void printbinary(short* buf, int len)
    {
      int i;
    
      for(i = 0; i < len; i++)
      {
        printf("%d\t", buf[i]);
      }
      printf("\n\n\n");
    }
    
    void printcomplex(Complex* buf, int len)
    {
        int i;
    
        for(i = 0; i < len; i++)
        {
            printf("%.0lf %.0lf\t", buf[i].real, buf[i].img);
        }
        printf("\n\n");
    }
    
    long bin2dec(short *bin, int len)
    {
      long dec = 0;
      int i;
    
      for(i = 0;i < len;i++)
      {
        dec += bin[i]*pow(2.0,(double) (len - i -1));
      }
      return dec;
    }
    
    void dec2bin(long dec, short *bin, int len)
    {
      long temp = dec;
      int i;
    
      for(i = 0;i<len;i++)
      {
        bin[len - 1 - i] = temp % 2;
        temp = temp/2;
      }
    }
    
    void binaryadd(short *bin1, short *bin2, short *erg, int len)
    {
      int i;
      short carry = 0;
      short oldcarry = 0;
      for(i = len - 1; i >= 0; i--)
      {
        if((bin1[i] + bin2[i] + oldcarry) > 1)
        {
          carry = 1;
        }
        else
        {
          carry = 0;
        }
        erg[i] = (bin1[i] + bin2[i] + oldcarry) % 2;
        oldcarry = carry;
      }
    }
    
    void leftshift(short *bin,short *erg,int shifts, int len)
    {
      int i;
    
    
      for(i = 0;i < len - shifts;i++)
      {
        erg[i] = bin[i + shifts];
      }
      for(i = len - shifts;i < len;i++)
      {
       erg[i] = 0;
      }
    }
    
    void binarymult(short *bin1, short *bin2, short *erg, int len)
    {
      int i;
      short temp[len - 1];
    
    
      for(i = 0;i < len;i++)
      {
       erg[i] = 0;
      }
    
      for(i = 0;i < len;i++)
      {
        if(bin2[i] == 1)
        {
          leftshift(bin1,temp,len - 1 - i,len);
          binaryadd(temp,erg,erg,len);
        }
      }
    
    }
    
    void binarypower(short *bin,short *erg,int power, int len)
    {
      int i;
      short temp[len - 1];
    
      for(i = 0;i < len;i++)
      {
       temp[i] = 0;
      }
      temp[len - 1] = 1;
    
      if(power > 1)
        binarypower(bin,temp,power - 1,len);
    
      binarymult(temp,bin,erg,len);
    }
    
    
    void scrambler(short *seed, short *input, short *output, int len, int seedlen)
    {
      int i;
      short carry;
      short sequence[len - 1];
      for(i = 0; i < len; i++)
      {
        sequence[i] = (seed[0] + seed[3]) % 2;
        carry = (seed[0] + seed[3]) % 2;
        leftshift(seed,seed,1,seedlen);
        seed[seedlen - 1] = carry;
        output[i] = (sequence[i] + input[i]) % 2;
      }
    }
    
    
    void encoder(short *input, short *output, int inputlen)
    {
      int i;
      short SR[7] = {0,0,0,0,0,0,0};
      short A;
      short B;
    
      for(i = 0; i < inputlen;i++)
      {
        leftshift(SR,SR,1,7);
        SR[6] = input[i];
        A = (SR[6] + SR[4] + SR[3] + SR[1] + SR[0]) % 2;
        B = (SR[6] + SR[5] + SR[4] + SR[3] + SR[0]) % 2;
        output[2*i] = A;
        output[2*i + 1] = B;
      }
    }
    
    /*
    void decoder(short *input, short *output, int inputlen)
    {
        int i;
        short SR[7] = {0}
        short A;
        short B;
        short C1;
        short C2;
    
        for(i = 0; i < intputlen; i++)
        {
            leftshift(SR, SR, 1, 7)
            SR[6] = input[i];
    
            C1 = (SR[6] + SR[4] + SR[3] + SR[1] + SR[0]) / 2;
            C2 = (SR[6] + SR[5] + SR[4] + SR[3] + SR[0]) / 2;
    
            A = (SR[6] + SR[4] + SR[3] + SR[1] + SR[0]) - (2 * C1);
            B = (SR[6] + SR[5] + SR[4] + SR[3] + SR[0]) - (2 * C2);
    
            output[2*i] = A;     // output[i/2] = A;
            output[2*i + 1] = B; // output[i/2 + 1] = B;
        }
    }
    */
    
    void interleaver(short *input, short *output, int N_CBPS,int N_BPSC)
    {
      int i;
      int t;
      int k;
      int s;
      short first_permutuation[N_CBPS - 1];
    
      for (k = 0; k < N_CBPS; k++)
      {
        i = (N_CBPS/16)*(k % 16) + (k/16);
        first_permutuation[i] = input[k];
      }
    
      s = fmax(N_BPSC/2,1);
    
      for(i = 0; i < N_CBPS;i++)
      {
        t = s*(i/s) + (i + N_CBPS - ((16*i)/N_CBPS)) % s;
        output[t] = first_permutuation[i];
      }
    }
    
    void fixed_point(short* input, int nbits)
    {
        int i;
    
        for(i = 0; i < nbits; i++)
        {
            if(input[i] < 0)
                input[i] *= 32768;
            else input[i] *= 32767;
        }
    }
    
    void fixed_point_complex(Complex* input, int nbits)
    {
        int i;
    
        for(i = 0; i < nbits; i++)
        {
            if(input[i].real == -1 || input[i].img == -1)
                input[i] *= 32768;
            else input[i] *= 32767;
        }
    }
    
    void defixed_point(short* input, int nbits)
    {
        int i;
    
        for(i = 0; i < nbits; i++)
        {
            if(input[i] < 0)
                input[i] /= 32768;
            else input[i] /= 32767;
        }
    }
    
    void IFFT_BPSK(short* input, Complex* output, Complex* twidder)
    {
        int i, k;
    
        for(i = 0; i < 64; i++)
        {
            for(k = 0; k < 64; k++)
            {
                output[i].real += (twidder[i][k].real * input[i]) / 64;
                output[i].img += (twidder[i][k].img * input[i]) / 64;
            }
        }
    }
    
    void IFFT_QPSK(Complex* input, Complex* output, Complex* twidder)
    {
        int i, k;
    
        for(i = 0; i < 64; i++)
        {
            for(k = 0; k < 64; k++)
            {
                output[i].real += (twidder[i][k].real * input[i].real) / 64;
                output[i].img += (twidder[i][k].img * input[i].img) / 64;
            }
        }
    }
    
    void IFFT_QPSK2(Complex* input, Complex* output, Complex* twidder, int nbits)
    {
        int a, b, c, d, e, f, g, h, blocks;
        int count1 = 7, count2 = 20, count3 = 28, count4 = 41;
        int next = 0;
        Complex ifft_qpsk_output[64];
    
        blocks = nbits / 48;
    
        for(a = 1; a <= blocks; a++)
        {
            // pilots
            output[7].real = 32767;
            output[21].real = 32767;
            output[42].real = 32767;
            output[56].real = -32768;
            // some data
            output[40].real = input[26 + (next * 48)].real;
            output[40].img = input[26 + (next * 48)].img;
            output[41].real = input[27 + (next * 48)].real;
            output[41].img = input[27 + (next * 48)].img;
    
            // zeroes
            for(b = 28; b <= 39; b++)
                output[b].real = 0;
    
            // other data
            for(c = 0; c <= 6; c++)
            {
                output[c].real = input[c + (next * 48)].real;
                output[c].img = input[c + (next * 48)].img;
            }
    
    
            for(d = 8; d <= 20; d++)
            {
                output[d].real = input[count1++ + (next * 48)].real;
                output[d].img = input[count1++ + (next * 48)].img;
            }
    
    
            for(e = 22; e <= 27; e++)
            {
                output[e].real = input[count2++ + (next * 48)].real;
                output[e].img = input[count2++ + (next * 48)].img;
            }
    
    
            for(f = 43; f <= 55; f++)
            {
                output[f].real = input[count3++ + (next * 48)].real;
                output[f].img = input[count3++ + (next * 48)].img;
            }
    
    
            for(h = 57; h <= 63; h++)
            {
                output[h].real = input[count4++ + (next * 48)].real;
                output[h].img = input[count4++ + (next * 48)].img;
            }
    
    
            // IFFT function goes here
            IFFT_QPSK(output, ifft_qpsk_output, twidder);
            printcomplex(ifft_qpsk_output, 64);
    
            next++;
    
        }
    }
    
    void IFFT_BPSK2(short* input, short* output, Complex* twidder, int nbits)
    {
        int a, b, c, d, e, f, g, h, blocks;
        int count1 = 7, count2 = 20, count3 = 28, count4 = 41;
        int next = 0;
        Complex ifft_bpsk_output[64];
    
        blocks = nbits / 48;
    
        for(a = 1; a <= blocks; a++)
        {
            // pilots
            output[7] = 32767;
            output[21] = 32767;
            output[42] = 32767;
            output[56] = -32768;
            // some data
            output[40] = input[26 + (next * 48)];
            output[41] = input[27 + (next * 48)];
    
            // zeroes
            for(b = 28; b <= 39; b++)
                output[b] = 0;
    
            // other data
            for(c = 0; c <= 6; c++)
                output[c] = input[c + (next * 48)];
    
            for(d = 8; d <= 20; d++)
                output[d] = input[count1++ + (next * 48)];
    
            for(e = 22; e <= 27; e++)
                output[e] = input[count2++ + (next * 48)];
    
            for(f = 43; f <= 55; f++)
                output[f] = input[count3++ + (next * 48)];
    
            for(h = 57; h <= 63; h++)
                output[h] = input[count4++ + (next * 48)];
    
            // IFFT function goes here
            IFFT_BPSK(output, ifft_bpsk_output, twidder);
            printcomplex(ifft_bpsk_output, 64);
    
            next++;
    
        }
    }
    
    void BPSKmapping(short* input, short* output, int nbits)
    {
        int i;
    
        for(i = 0; i < nbits; i++)
        {
            if(input[i] == 0)
                output[i] = -1;
            else output[i] = 1;
        }
    }
    
    void BPSKdemapping(short* input, short* output, int nbits)
    {
        int i;
    
        for(i = 0; i < nbits; i++)
        {
            if(input[i] == -1)
                output[i] == 0;
            else output[i] == 1;
        }
    }
    
    void QPSKmapping(short* input, Complex* output, int nbits)
    {
        int i;
    
        for(i = 0; i < nbits; i += 2)
        {
            if(input[i] == 0 && input[i+1] == 0)
            {
                output[i].real = -1;
                output[i+1].img = -1;
            }
            else if(input[i] == 0 && input[i+1] == 1)
            {
                output[i].real = -1;
                output[i+1].img = 1;
            }
            else if(input[i] == 1 && input[i+1] == 0)
            {
                output[i].real = 1;
                output[i+1].img = -1;
            }
            else
            {
                output[i].real = 1;
                output[i+1].img = 1;
            }
        }
    }
    
    void QPSKdemapping(Complex* input, short* output, int nbits)
    {
        int i;
    
        for(i = 0; i < nbits; i += 2)
        {
            if(input[i].real == -1 && input[i+1].img == -1)
            {
                output[i] = 0;
                output[i+1] = 0;
            }
            else if(input[i].real == -1 && input[i+1].img == 1)
            {
                output[i] = 0;
                output[i+1] = 1;
            }
            else if(input[i].real == 1 && input[i+1].img == -1)
            {
                output[i] = 1;
                output[i+1] = 0;
            }
            else
            {
                output[i] = 1;
                output[i+1] = 1;
            }
        }
    }
    
    //Channel Begin
    double uniform(double a, double b)
    {
     double c;
     double d;
     static int firstcall = 1;
     c = b - a;
     if(firstcall == 1)
     {
         srand((unsigned int)time(NULL));
         firstcall = 0;
     }
    
     d = a + (double)rand() / RAND_MAX * c;
     return d;
    }
    
    double gauss(double mean, int SNRdb)
    {
        double dGaussNum;
        double x = 0;
        int i;
        double sigma;
        sigma = 1 / pow(10, (double)SNRdb / 10);
    
        for(i = 0;i < 12; i ++)
        {
            x = x + uniform(0,1);
        }
        x = x - 6;
        dGaussNum = mean + sqrt(sigma) * x;
        return dGaussNum;
    }
    
    void ChannelModel(Complex R[], Complex S[], int SNRdb)
    {
        int i;
        for (i=0;i<N+L;i++)
        {
    
            R[i].real = S[i].real + gauss(0, SNRdb);
            R[i].img = S[i].img + gauss(0, SNRdb);
        }
    }
    //Channel End
    
    void deinterleaver(short *input, short *output, int N_CBPS,int N_BPSC)
    {
      int i;
      int t;
      int k;
      int s;
      short first_permutuation[N_CBPS - 1];
    
      s = fmax(N_BPSC/2,1);
    
      for (t = 0; t < N_CBPS; t++)
      {
        i = s*(t/s) + (t + ((16*t)/N_CBPS)) % s;
        first_permutuation[i] = input[t];
      }
    
    
      for(i = 0; i < N_CBPS;i++)
      {
        k = 16*i - (N_CBPS - 1)*((16*i)/N_CBPS);
        output[k] = first_permutuation[i];
      }
    }
    

    main.c

    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include <time.h>
    #include "ofdm.h"
    
    int main(int argc, char *argv[])
    {
    
      short seed[8];
      int bits, i, j, k;
      char mode[5], line[1024];
    /*  Complex twidder[64][64];
    
      FILE *file = fopen("twidder_factor.txt", "r");
    
      i = 0;
      while(fgets(line, sizeof(line), file ) != NULL)
      {
          k = j = 0;
          char **result = split(line, "\t");
    
          while(result[k] != NULL)
          {
              parseComplex(&twidder[i][j], result[k++]);
              j++;
          }
    
          i++;
      }
    */
    
      printf("How many bits do you want to transmit?: ");
      scanf("%d", &bits);
    
      short* start_input;
      short* scrambler_output;
      short* encoder_output;
      short* interleaver_output;
      short* bpsk_mapper_output;
      short* ifft_bpsk_input[64];
      Complex* qpsk_mapper_output;
      Complex ifft_qpsk_input[64];
    
      start_input = malloc(sizeof(short) * bits);
    
      scrambler_output = malloc(sizeof(short) * bits);
    
      encoder_output = malloc(sizeof(short) * (bits * 2));
    
      interleaver_output = malloc(sizeof(short) * (bits * 2));
    
      bpsk_mapper_output = malloc(sizeof(short) * (bits * 2));
    
      qpsk_mapper_output = malloc(sizeof(Complex) * (bits * 2));
    
      if(qpsk_mapper_output == NULL)
      {
          fprintf(stderr, "Couldn't allocate that much memory!\n");
          return 1;
      }
    
      srand(time(NULL));
      rbits(seed, 8);
      rbits(start_input, bits);
    
      printf("Which modulation type to you want to use? (type BPSK or QPSK): ");
      scanf("%s", mode);
    
      if((strcmp(mode, "BPSK") == 0) || (strcmp(mode, "bpsk") == 0))
      {
          printf("\nSelected modulation type: BPSK\n\n\n");
          printf("SCRAMBLER OUTPUT:\n\n");
          scrambler(seed, start_input, scrambler_output, bits, 8);
          printbinary(scrambler_output, bits);
    
          printf("ENCODER OUTPUT:\n\n");
          encoder(scrambler_output, encoder_output, bits);
          printbinary(encoder_output, bits*2);
    
          printf("INTERLEAVER OUTPUT:\n\n");
          interleaver(encoder_output, interleaver_output, bits, 1);
          printbinary(interleaver_output, bits*2);
    
          printf("MAPPER OUTPUT:\n\n");
          BPSKmapping(interleaver_output, bpsk_mapper_output, bits*2);
          printbinary(bpsk_mapper_output, bits*2);
    
          printf("FIXED-POINT OUTPUT:\n\n");
          fixed_point(bpsk_mapper_output, bits*2);
          printbinary(bpsk_mapper_output, bits*2);
    /*
          printf("IFFT OUTPUT:\n\n");
          IFFT_BPSK(bpsk_mapper_output, ifft_bpsk_input, twidder, bits*2)
    
          defixed_point(bpsk_mapper_output, bits*2);
          printbinary(bpsk_mapper_output, bits*2);
     */ }
      else if((strcmp(mode, "QPSK") == 0) || (strcmp(mode, "qpsk") == 0))
      {
          printf("\nSelected modulation type: QPSK\n\n\n");
          printf("SCRAMBLER OUTPUT:\n\n");
          scrambler(seed, start_input, scrambler_output, bits, 8);
          printbinary(scrambler_output, bits);
    
          printf("ENCODER OUTPUT:\n\n");
          encoder(scrambler_output, encoder_output, bits);
          printbinary(encoder_output, bits*2);
    
          printf("INTERLEAVER OUTPUT:\n\n");
          interleaver(encoder_output, interleaver_output, bits, 2);
          printbinary(interleaver_output, bits*2);
    
          printf("MAPPER OUTPUT:\n\n");
          QPSKmapping(interleaver_output, qpsk_mapper_output, bits*2);
          printcomplex(qpsk_mapper_output, bits*2);
    /*
          printf("FIXED-POINT OUTPUT:\n\n");
          fixed_point_complex(qpsk_mapper_output, bits*2);
          printcomplex(qpsk_mapper_output, bits*2);
    
          printf("IFFT OUTPUT:\n\n");
          IFFT_QPSK(qpsk_mapper_output, ifft_qpsk_input, twidder, bits*2)
    
          defixed_point(qpsk_mapper_output, bits*2);
          printbinary(qpsk_mapper_output, bits*2);
    */  }
      else
      {
          printf("That's an invalid modulation type!\n");
          free(start_input);
          free(scrambler_output);
          free(encoder_output);
          free(interleaver_output);
          free(bpsk_mapper_output);
          free(qpsk_mapper_output);
          return 0;
      }
    
    
      free(start_input);
      free(scrambler_output);
      free(encoder_output);
      free(interleaver_output);
      free(bpsk_mapper_output);
      free(qpsk_mapper_output);
    
      system("PAUSE");
    
      return 0;
    
    }
    

    If you could help me to solve this problem I would be glad. I think there is some kind of linking problem between my library and the main source file.

    Thanks in advance.

  • ruakh
    ruakh about 12 years
    +1. Alternatively: gcc -Wall main.c -c main.o plus gcc -Wall ofdm.c -c ofdm.o plus gcc main.o ofdm.o -o output, so that only main.c needs to be recompiled if ofdm.c hasn't changed.
  • P.P
    P.P about 12 years
    I agree. That's a little more efficient.