4

I have a .h file which I was intending to use only for storing all the information string that will be displayed in my program. In my info.h:

#ifndef __INFO_H
#define __INFO_H

char *info_msg = "This is version 1.0 of NMS.";

//all other strings used by view.c and controller.c

#endif

Then in my view.h I have as follows:

//view.h
#ifndef __VIEW_H
#define __VIEW_H   

#include "info.h"
//other stuff like method declaration etc.
#endif

My controller.h is using view.h:

//controller.h
#ifndef __CONTROLLER_H
#define __CONTROLLER_H   

#include "view.h"
#include "model.h"
//other stuff line method declaration etc.
#endif

main.c:

 #include "controller.h"
 int main()
 {
    //stuff
 }

view.c:

#include "view.h"

char esc,up,down,right,left;   
void change_character_setting(char pesc, char pup, char pdown, char pright, char pleft)
{      
  esc = pesc;
  up = pup;
  down = pdown;
  right = pright;
  left = pleft;
}


void print_warning()
{
 printf("%s \n",info_msg);
} 

When I attempt to create the executable the linker complains:

/tmp/ccqylylw.o:(.data+0x0): multiple definition of `info_msg'
/tmp/cc6lIYhS.o:(.data+0x0): first defined here

I am not sure why it would see two definitions since I am using the protection block. I tried to google here but nothing specific showed up. Can someone explain how it is seeing multiple definitions? How do I achieve something as simple in Java to use one single file for all text manipulation in C?

as3rdaccount
  • 3,711
  • 12
  • 42
  • 62
  • NEVER assign variables in a header file. Declare them as extern in the header and define them in a source file. The compiler creates one instance for each include (e.g. in each compilation unit/source file). This creates errors at link time. – bash0r Aug 25 '13 at 18:17
  • Thanks. Now I am getting the following error:/tmp/ccFMbvlv.o: In function `print_warning': view.c:(.text+0x44b): undefined reference to `info_msg' – as3rdaccount Aug 25 '13 at 18:23
  • Can you edit your answer and post view.c? – bash0r Aug 25 '13 at 18:24
  • And the same error for all other strings in the file even after just externed all of them in the header and created a separate source file. – as3rdaccount Aug 25 '13 at 18:24
  • I think you aren't showing everything that is relevant, because this should work. bash0r is right about using externs. .h files should be about defining stuff, not instantiating stuff. – Jiminion Aug 25 '13 at 18:25
  • Updated the post. Still getting the same error after removing __ as suggested in the other answer. – as3rdaccount Aug 25 '13 at 18:35
  • @ArunavDev Did you read the *entire* answer? The mere mentioning of underscore usage as violating the standard was a footnote, and I'll gladly remove it if it helps you read the meat of the solution to your problem, which you will find by reading the answer from the top-down rather than the bottom-up. – WhozCraig Aug 26 '13 at 07:09

1 Answers1

5

You're compiling a global variable called info_msg into each source file that includes info.h either directly or pulled in from some other header. At link-time, the linker finds all these info_msg identifiers (one in each object file compiled) and doesn't know which one to use.

Change you're header to be:

#ifndef PROJ_INFO_H
#define PROJ_INFO_H

extern const char *info_msg;  // defined in info.cpp

#endif

And assuming you have an info.cpp (if not you can place this in any .cpp file, but that one would be the most natural location to maintain it):

// info.cpp
#include "info.h"

const char *info_msg = "This is version 1.0 of NMS.";

Note: Be careful when declaring preprocessor symbols and identifiers as to your placement of underscores. According to the C99 standard:

C99 §7.1.3/1

  • All identifiers that begin with an underscore and either an uppercase letter or another underscore are always reserved for any use.
  • All identifiers that begin with an underscore are always reserved for use as identifiers with file scope in both the ordinary and tag name spaces.
WhozCraig
  • 65,258
  • 11
  • 75
  • 141
  • 2
    Anything *containing* `__` is reserved. – chris Aug 25 '13 at 18:27
  • @chris whoa. reference please. (I don't doubt you, I just wanna read it). thanks. – WhozCraig Aug 25 '13 at 18:28
  • [reserved identifier](http://stackoverflow.com/questions/228783/what-are-the-rules-about-using-an-underscore-in-a-c-identifier) – chris Aug 25 '13 at 18:28
  • @chris you are *the* man. sir. thanks. (and updating answer, danka for the link). – WhozCraig Aug 25 '13 at 18:29
  • The 'containing double underscore' thing is a C++ only point though, no? This is a C question... – Crowman Sep 17 '13 at 21:46
  • @PaulGriffiths i'll double check the standard, you are likely quite right. I rarely dive into C except this board. I'll surely take a look. – WhozCraig Sep 17 '13 at 21:48
  • 1
    @PaulGriffiths sure enough you're correct, and I'll be updating the text accordingly. Double-`_` is more lenient in C than C++. – WhozCraig Sep 17 '13 at 22:01