0

I am writing a program in C that contains two source files, one containing main() and one containing function definitions. I also have a header file declaring the functions and variables so I don't have to pass variables back and forth. Here is the content of the files.

main.c:

#include <stdio.h>
#include "defs.h"
#include "sorting.c"

int main(int argc, char **argv){

    listLength = 0;/*this is a load of barnacles*/
    EOFFlag = 1;

    input = fopen(argv[1], "r");

    if(input == NULL){
        printf("Could not open requested file.\n");
        return -1;
    }

    while(EOFFlag){
        sortNextWord();
    }

    if(FULLLISTCONSEQUENCES){
        for(genericIterator = 0; genericIterator < USHRT_MAX + 1; genericIterator++){
            printf("%d: %s; %d", genericIterator + 1, wordlist[genericIterator], wordcount[genericIterator]);
        }
    }else{
        for(genericIterator = 0; genericIterator < listLength; genericIterator++){
            printf("%d: %s; %d", genericIterator + 1, wordlist[genericIterator], wordcount[genericIterator]);
        }
    }

    return 1;


}

sorting.c

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include "defs.h"

int sortNextWord(){
    
    getNextWord();
    if(wordHolder[0] != '\0')/*checks to ensure that getNextWord didn't get an empty string*/
        listMatch();
    return 1;
}
int getNextWord(){
    char charStore;
    char returnFlag = 0;

    genericIterator = 0;

    while(genericIterator != USHRT_MAX){

        switch(charStore = getc(input)){

        case EOF:
            EOFFlag = 0;
            goto exitcond;/* checks for EOF or whitespace, exits loop if found*/
        case ' ':
        case '\n':
        case '\t':
            goto exitcond;
        default:
            wordHolder[genericIterator++] = charStore;/* otherwise it writes the character it read to the next available spot */
            break;


        }

    }
exitcond:
    wordHolder[genericIterator] = '\0';
    wordlen = genericIterator;
    return 1;

}

int listMatch(){/* runs through wordlist to find a matching word. If found, increments the respective wordcount entry, otherwise, creates new entry in wordlist */
    for(genericIterator = 0; genericIterator < listLength; genericIterator++){
        if(strcmp(wordHolder, wordlist[genericIterator])){
            ++wordcount[genericIterator];
            goto foundmatch;
        }
    }
    addToList();
foundmatch:
    return 1;
}

int addToList(){ /*adds word to next available spot in wordlist*/

    char *string;
    if(FULLLISTCONSEQUENCES) /*doesnt do anything if wordlist is full */
        return 0; /* John Freeman, who was Go */
    if(listLength == USHRT_MAX)
        FULLLISTCONSEQUENCES = 1;

    string = malloc((wordlen + 1) * sizeof(char));
    string[0] = '\0';

    strncat(string, wordHolder, USHRT_MAX + 1);

    wordcount[listLength] = 1;
    wordlist[listLength++] = string;

    return 1;`
        
}

defs.h (ignore the stuff about heapsort. I'm going to implement that to sort the wordlist, but i need to make sure this works first.

#ifndef DEFS_H
#define DEFS_H
#include <limits.h>
#include <stdio.h>


char *wordlist[USHRT_MAX + 1];
int wordcount [USHRT_MAX + 1];
unsigned short listLength;
unsigned short genericIterator;
FILE *input;

/*heapsort goes here */

char wordHolder[USHRT_MAX +  1];
unsigned short wordlen;
char EOFFlag;
char FULLLISTCONSEQUENCES;

int heapsort();
int buildMaxHeap();
int restoreMaxHeap();
int swap(unsigned short, unsigned short);
unsigned short getParent(unsigned short);
unsigned short getRightChild(unsigned short);
unsigned short getLeftChild(unsigned short);

int sortNextWord(); 
int getNextWord(); 
int listMatch();
int addToList();


#endif`

When I run those through gcc with the command

gcc -o wordsort main.c sorting.c

I get the following error:

/usr/bin/ld: /tmp/cc8X0W8R.o:(.bss+0x0): multiple definition of `wordlist'; /tmp/cc3dFw3Q.o:(.bss+0x0): first defined here
/usr/bin/ld: /tmp/cc8X0W8R.o:(.bss+0x80000): multiple definition of `wordcount'; /tmp/cc3dFw3Q.o:(.bss+0x80000): first defined here
/usr/bin/ld: /tmp/cc8X0W8R.o:(.bss+0xc0000): multiple definition of `listLength'; /tmp/cc3dFw3Q.o:(.bss+0xc0000): first defined here
/usr/bin/ld: /tmp/cc8X0W8R.o:(.bss+0xc0002): multiple definition of `genericIterator'; /tmp/cc3dFw3Q.o:(.bss+0xc0002): first defined here
/usr/bin/ld: /tmp/cc8X0W8R.o:(.bss+0xc0008): multiple definition of `input'; /tmp/cc3dFw3Q.o:(.bss+0xc0008): first defined here
/usr/bin/ld: /tmp/cc8X0W8R.o:(.bss+0xc0020): multiple definition of `wordHolder'; /tmp/cc3dFw3Q.o:(.bss+0xc0020): first defined here
/usr/bin/ld: /tmp/cc8X0W8R.o:(.bss+0xd0020): multiple definition of `wordlen'; /tmp/cc3dFw3Q.o:(.bss+0xd0020): first defined here
/usr/bin/ld: /tmp/cc8X0W8R.o:(.bss+0xd0022): multiple definition of `EOFFlag'; /tmp/cc3dFw3Q.o:(.bss+0xd0022): first defined here
/usr/bin/ld: /tmp/cc8X0W8R.o:(.bss+0xd0023): multiple definition of `FULLLISTCONSEQUENCES'; /tmp/cc3dFw3Q.o:(.bss+0xd0023): first defined here
/usr/bin/ld: /tmp/cc8X0W8R.o: in function `sortNextWord':
main.c:(.text+0x0): multiple definition of `sortNextWord'; /tmp/cc3dFw3Q.o:sorting.c:(.text+0x0): first defined here
/usr/bin/ld: /tmp/cc8X0W8R.o: in function `getNextWord':
main.c:(.text+0x2a): multiple definition of `getNextWord'; /tmp/cc3dFw3Q.o:sorting.c:(.text+0x2a): first defined here
/usr/bin/ld: /tmp/cc8X0W8R.o: in function `listMatch':
main.c:(.text+0xdf): multiple definition of `listMatch'; /tmp/cc3dFw3Q.o:sorting.c:(.text+0xdf): first defined here
/usr/bin/ld: /tmp/cc8X0W8R.o: in function `addToList':
main.c:(.text+0x191): multiple definition of `addToList'; /tmp/cc3dFw3Q.o:sorting.c:(.text+0x191): first defined here
collect2: error: ld returned 1 exit status

What is happening? I've only defined these functions once in sorting.c. Where did this error come from?

I've tried removing some of the #include headers, and I added the #ifndef statement to defs.h. Neither made any difference. I've also tried compiling and then linking as suggested in https://stackoverflow.com/questions/18777326/compiling-multiple-c-files-with-gcc`your text`

  • 3
    Don't `#include` .c files. – user3386109 Nov 28 '22 at 22:03
  • 1
    [As user3386109 said]: don't `#include` .c files. As to the definitions in your `.h` files, the TL;DR: Try compiling with `-fcommon`. Prior to gcc 12.0.0, this was the default. The default now is `-fno-common` :-( See my answer: [Global variables and the .data section](https://stackoverflow.com/a/64627070/5382650) for more details. – Craig Estey Nov 28 '22 at 22:16
  • @CraigEstey: Rather than compiling with `-fcommon` and relying on a C extension that is no longer a default in GCC, they should use `extern char *wordlist[USHRT_MAX + 1];` in the header and `char *wordlist[USHRT_MAX + 1];` in one source file, which will give them a program that will, in that respect, work in all C implementations. – Eric Postpischil Nov 28 '22 at 22:27

0 Answers0