0

C noob here. I have a global header, opennec.h which has a bunch of includes for <math.h> and so forth. It also has a couple of basic definitions:

#define NUM_COMNTS  5
char *comment_codes[NUM_COMNTS] =
{
  "CM", "CE", "!", "'", "#"
};

These caused complaints because of multiple definitions (of course) so I did what I forgot to do the first time and added guards:

#ifndef COMNT_CODES_DEF
#define COMNT_CODES_DEF
#define NUM_COMNTS  5
char *comment_codes[NUM_COMNTS] =
{
  "CM", "CE", "!", "'", "#"
};
#endif

And yet...

duplicate symbol _comment_codes in:
    calculations.o
    somnec.o

Ok, what did I do wrong?

Maury Markowitz
  • 9,082
  • 11
  • 46
  • 98
  • 1
    http://c-faq.com/decl/decldef.html – melpomene Mar 03 '18 at 17:14
  • Related: https://stackoverflow.com/questions/1164167/variable-declaration-in-a-header-file, https://stackoverflow.com/questions/1433204/how-do-i-use-extern-to-share-variables-between-source-files – melpomene Mar 03 '18 at 17:17

1 Answers1

4

Your comment_codes symbol is going to need a declaration in a header file,

#ifndef COMNT_CODES_DEF
#define COMNT_CODES_DEF
#define NUM_COMNTS  5
extern char *comment_codes[NUM_COMNTS];
#endif

and a definition in one (and only one) c file.

#include "comnt_codes.h"

char *comment_codes[NUM_COMNTS] = {
  "CM", "CE", "!", "'", "#"
};

Otherwise every c file that includes your comment-codes header will provide conflicting definitions of comment_codes.

melpomene
  • 84,125
  • 8
  • 85
  • 148
dtolnay
  • 9,621
  • 5
  • 41
  • 62
  • 1
    Ah HA. I thought you only needed that with function definitions, as pretty much everything I've ever read implies, but in retrospect it's obvious. – Maury Markowitz Mar 03 '18 at 17:15
  • Just for the next person that comes here, for my own needs I placed the declarations in my main header and the implementation in main.c, as that was ultimately going to be the only consumer. – Maury Markowitz Mar 03 '18 at 17:24
  • 1
    @MauryMarkowitz If you only have one consumer, you can remove the declaration from the header and put a `static` definition in the c file, giving you a "module local" variable. – melpomene Mar 03 '18 at 17:32
  • You don't need any headers until you have more than one source file for a program that will share some code. As soon as you have more than one source file, you need a header, because you won't use two source files if there isn't something shared between the two, even if it is only a simple function call. Headers declare what's shared. Source files define what the headers declare. Make everything static at file scope except `main()` and any entry point functions — or global variables. Make sure that everything that uses the functions or variables includes the header; it provides cross-checks. – Jonathan Leffler Mar 03 '18 at 18:15
  • Currently the code shares these values, although they are *actively* used in only one file. I'll either remove them from the header or factor out the code in question from main at some point. – Maury Markowitz Mar 04 '18 at 13:53