0

The code is as follows:

global.h

#ifndef GLOBAL_H
#define GLOBAL_H
#include <stdio.h>
int test;

void test_fun(void);
#endif

global.c

#include "global.h"

void test_fun()
{
    printf("%d\n", test);
}

main.c

#include "global.h"

int main(void)
{
    test_fun();
    test = 1;
    printf("%d\n", test);
}

Makefile using gcc compiler

main: main.o global.o
    gcc -o main main.o global.o

main.o: main.c global.h
    gcc -c main.c
global.o: global.c global.h
    gcc -c global.c

clean:
    rm -f global.o main.o main

This works well.

However, when I change my code to C++, as follows:

global.h

#ifndef GLOBAL_H
#define GLOBAL_H
#include <iostream>
int test;

void test_fun(void);
#endif

global.cpp

#include "global.h"

void test_fun()
{
    cout << test
}

main.cpp

#include "global.h"

int main(void)
{
    test_fun();
    test = 1;
    std::cout << test;
}

Makefile using g++ compiler

main: main.o global.o
    g++ -o main main.o global.o

main.o: main.cpp global.h
    g++ main.cpp
global.o: global.cpp global.h
    g++ global.cpp

clean:
    rm -f global.o main.o main

The code above throws the output:

global.o:(.bss+0x0): multiple definition of `test'

What makes the different here?

Charles0429
  • 1,406
  • 5
  • 15
  • 31
  • possible duplicate of [Redefinition allowed in C but not in C++?](http://stackoverflow.com/questions/5337370/redefinition-allowed-in-c-but-not-in-c) – legends2k Mar 03 '14 at 11:57

2 Answers2

1

... You are using a different programming language

Ed Heal
  • 59,252
  • 17
  • 87
  • 127
  • I think this doesn't matter whether I use `.c` files or `.cpp` files. I confirmed just now when I replace all `.c` files with `.cpp` files, the result is still the same. – Charles0429 Mar 03 '14 at 11:16
  • @Charles0429 - g++ speaks C++, gcc speaks C. Like getting a French man to understand Greek. – Ed Heal Mar 03 '14 at 11:18
  • Ed Heal is right. Getting errors with C++ in gcc and vice-versa is easy. – deviantfan Mar 03 '14 at 11:20
  • @Charles0429 - Why not have a go with a Fortran compiler? – Ed Heal Mar 03 '14 at 11:22
  • When I renamed the code file to `.cpp`, aren't they using `C++`? – Charles0429 Mar 03 '14 at 11:22
  • @Charles0429 - You can rename them to whatever you want. The code is C hence use a C compiler. So why not write a file as hello.french and rename it to hello.german. The computer does not automatically translate bonjour for you. – Ed Heal Mar 03 '14 at 11:26
  • Then, what can be called a `C++` program (please show me an example), isn't `C` included `C++`? – Charles0429 Mar 03 '14 at 11:30
  • please see my update, I think I have rewritten the code in `C++` now, but the result is still the same. – Charles0429 Mar 03 '14 at 11:46
  • 1
    I think you should interpret OPs question as: "Why does this code compile as C but produces this error when compiled as C++? It looks to me like it uses the supported C subset of C++." – pmr Mar 03 '14 at 11:53
  • 1
    C++ supports C, but can behave differently. That's why we have `extern "C"`. – zoska Mar 03 '14 at 13:13
1

You've int test; in a header which is included in 2 TUs, hence the error. Both the translation units main.c (or .cpp depending upon the compiler used) and global.c have global.h included, which leads to two definitions of the same variable in two object files, thus the linker error.

Pass test as an arguement to test_fun, thereby avoiding the usage of a global.

If you absolutely have to share the variable between the TUs, then remove int test; from global.h and in main.cpp do

int test;

and in global.cpp do

extern int test;

As an aside, since it's a global variable, test would be initialized to 0 and hence in main when you test_fun();, it should print 0 and then after setting it to 1, it'll print 1.

It's illegal in both C and C++ from a language standpoint, but as for why it works with a C compilers (like GCC) is because they implement a common extension, a legacy cruft.

Community
  • 1
  • 1
legends2k
  • 31,634
  • 25
  • 118
  • 222