Search code examples
headermacrosconstantsdefinition

const definition in a header file, using macro constants causes linker multiple definition errors


G'day! While I have previously found solutions to my programming issues here by Googling, this is the first time I've asked a question, since I couldn't find an answer by Googling.

I'm a professional electronics engineer, but not a software engineer. My (limited) software skills are self-taught, and I particularly struggle with C programming, from lack of understanding. So please treat me as an absolute novice, and explain in simple terms what I've done wrong, and suggestions on how to fix it , if possible.

I'm compiling/linking a program for an old DOS-based PC using the Phar Lap compiler/linker suite. Several of my C modules have #include "codes.c", and I've included an extract from that header file below. Just the relevant lines in sequential order, with intermediate irrelevant lines omitted. (Incidentally, the value 'LAST_IRTYPE' is defined earlier in the file, with a value of 9.)

#ifndef CODES_H
    #define CODES_H

#include "AStypes.h"                        // Typedefs for common types

#define IRtime(x)   ((x/IRtimeClkPer_us) + 0.5)


const uShort_16 cusarIRtimes[LAST_IRTYPE + 1][6] =  /* carrier pulse-times expressed in timer counts.
                                                    NB: IRtimeClkPer_us MUST be #defined (not in
                                                    this file!) for every project using this file!
                                                    (comment times are in ms:
                                                    start-pulse, start-gap, '0', '1', bit-gap, inter-command gap) */
{
    {IRtime(250), IRtime(2474), IRtime(2474), IRtime(3582), IRtime(250), IRtime(7000)},     // 0 = dbx 4BX (0.25, 2.474, 2.474, 3.582, 0.25, 7)
    {IRtime(2348), IRtime(580), IRtime(580), IRtime(1168), IRtime(580), IRtime(25000)},     // 1 = Sony 12-bit (2.348, 0.58, 0.58, 1.168, 0.58, 25)
    {IRtime(2348), IRtime(580), IRtime(580), IRtime(1168), IRtime(580), IRtime(25000)},     // 2 = Sony 16-bit (2.348, 0.58, 0.58, 1.168, 0.58, 25)
    {IRtime(8424), IRtime(4192), IRtime(520), IRtime(1576), IRtime(520), IRtime(20000)},    // 3 = JVC (8.424, 4.192, 0.52, 1.576, 0.52, 20)
    {IRtime(9040), IRtime(4560), IRtime(552), IRtime(1672), IRtime(552), IRtime(40000)},    // 4 = Squeezebox 3 (9.04, 4.56, 0.552, 1.672, 0.552, 40)
    {IRtime(9000), IRtime(4560), IRtime(552), IRtime(1672), IRtime(552), IRtime(40000)},    // 5 = Medion, 5BX, Oppo, Toppy (9, 4.56, 0.552, 1.672, 0.552, 40)
    {IRtime(4500), IRtime(4500), IRtime(560), IRtime(1680), IRtime(470), IRtime(45000)},    // 6 = LG BD, Samsung (4.55, 4.55, 0.560, 1.68, 0.515, 45)
    {IRtime(8512), IRtime(4272), IRtime(536), IRtime(1592), IRtime(536), IRtime(40000)},    // 7 = Pioneer GR-777 (8.512, 4.272, 0.536, 1.592, 0.536, 40)
    {IRtime(8512), IRtime(4272), IRtime(536), IRtime(1592), IRtime(536), IRtime(26000)}     // 8 = Pioneer DVD (8.512, 4.272, 0.536, 1.592, 0.536, 26)
};

    // Bits per code for 4BX, Sony1, Sony2, JVC, SB3, DTV, LGBD, STV, Pioneer1, Pioneer2:
const uChar_8 cucarBitsPerCode[LAST_IRTYPE + 1] = {6, 12, 15, 16, 32, 32, 32, 32, 32};

    /* Whether bits are sent as 'high' (IR on +) or 'low' (IR off -) for
        4BX, Sony1, Sony2, JVC, SB3, DTV, LGBD, STV, Pioneer1, Pioneer2: */
const Bool_8 bIRbitsHigh[LAST_IRTYPE + 1] = {bFALSE, bTRUE, bTRUE, bFALSE, bFALSE, bFALSE, bFALSE, bFALSE, bFALSE};

#endif

My understanding of using #ifndef CODES_H / #define CODES_H is that the compiler will only parse/compile the file's contents the first time it's encountered, so any variables defined within will only be defined once, but this doesn't seem to be happening.

When I compile/link my program, I get a series of linker errors like the following, repeated for all but one of the C files that #include codes.h


386|LINK: 8.02 -- Copyright (C) 1986-96 Phar Lap Software, Inc.
Error LINK.3070: Duplicate definition of the symbol "cusarIRtimes" in module "funcs.c".
Error LINK.3070: Duplicate definition of the symbol "cucarBitsPerCode" in module "funcs.c".
Error LINK.3070: Duplicate definition of the symbol "bIRbitsHigh" in module "funcs.c".

Using Notepad++ with all .C and .H files loaded, and doing a search across all open files for cusarIRtimes, it is only in that one place, as above.

Can anyone please explain why the linker finds duplicate definitions, and how I might correct this? Thank you.

Daniel


Solution

  • My understanding of using #ifndef CODES_H / #define CODES_H is that the compiler will only parse/compile the file's contents the first time it's encountered, so any variables defined within will only be defined once, but this doesn't seem to be happening.

    It is happening, but it's once per translation unit (C module), which are compiled independently from each other. You can correct this by moving the definitions of cusarIRtimes, cucarBitsPerCode and bIRbitsHigh into one of your C modules, and in the include file replacing them by declarations:

    extern const uShort_16 cusarIRtimes[LAST_IRTYPE + 1][6];
    extern const uChar_8 cucarBitsPerCode[LAST_IRTYPE + 1];
    extern const Bool_8 bIRbitsHigh[LAST_IRTYPE + 1];