1

我编写了一个由几个文件组合而成的小型 C 程序。当我编译时,我收到“多个定义”的错误。

我的 main.c:

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

#define FOREVER for(;;)
#define INPUT_LEN 30

int main()
{
    char command[INPUT_LEN];
    char *func;
    int i;
    int t;

    FOREVER
    {
        if(scanf("%s", command) == 1)
        {
            func = strtok(command, " ");
            for(i=0;cmd[i].func != NULL;i++)
            {
                if(strcmp(func, cmd[i].name) == 0)
                {
                    (*((cmd[i].func)));
                    t = 1;
                }
            }
            if(t == 1)
            {
                printf("No such command");
            }
        }
    }   
    return 0;   
}

我的 mat.c 文件:

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

#define LENGTH 100
#define SIXTEEN 16
#define SIZE 4


void read_mat()
{
    int i = 0;
    int j = 0;
    int k = 0;
    char tmp_name[LENGTH];
    char num_buffer[LENGTH];
    char *token;
    double num_list[16];
    double tmp_num = 0;

    scanf("%[^,], %s", tmp_name, num_buffer);

    token = strtok(num_buffer, ",");

    while(token != NULL)
    {
        if(strcmp(token, "0") == 0)
        {
            num_list[i] = 0;
        }
        else
        {
            tmp_num = atof(token);
            if(tmp_num == 0)        
            {
                printf("Error in parameter: %d\n", (i-1));
                break;
            }
            else
            {
                num_list[i] = tmp_num;
            }
        }   
    i++;
    token = strtok(NULL, ",");
    }

    if(!strcmp(tmp_name, "MAT_A"))
    {
        for(i=0;i<SIZE;i++)
            for(j=0;j<SIZE;j++)
            {
                mats[0].mat[0][i][j] = num_list[k];
                k++;
            }

    }
    else if(!strcmp(tmp_name, "MAT_B"))
    {
        for(i=0;i<SIZE;i++)
            for(j=0;j<SIZE;j++)
            {
                mats[1].mat[0][i][j] = num_list[k];
                k++;
            }
    }
    else if(!strcmp(tmp_name, "MAT_C"))
    {
        for(i=0;i<SIZE;i++)
            for(j=0;j<SIZE;j++)
            {
                mats[2].mat[0][i][j] = num_list[k];
                k++;
            }
    }
    else if(!strcmp(tmp_name, "MAT_D"))
    {
        for(i=0;i<SIZE;i++)
            for(j=0;j<SIZE;j++)
            {
                mats[3].mat[0][i][j] = num_list[k];
                k++;
            }
    }
    else if(!strcmp(tmp_name, "MAT_E"))
    {
        for(i=0;i<SIZE;i++)
            for(j=0;j<SIZE;j++)
            {
                mats[4].mat[0][i][j] = num_list[k];
                k++;
            }
    }
    else if(!strcmp(tmp_name, "MAT_F"))
    {
        for(i=0;i<SIZE;i++)
             for(j=0;j<SIZE;j++)
             {
                mats[5].mat[0][i][j] = num_list[k];
                k++;
             }
    }
    else
    {
        printf("No such matrix name.");
    }
}

我的 general_structs.h 文件:

#define SIZE 4
#define SIZE_NAME 5
#define SIZE_FUNC 10

typedef double matrix[SIZE][SIZE];

matrix MAT_A, MAT_B, MAT_C, MAT_D, MAT_E, MAT_F;

void read_mat(void);

struct 
{
    char name[SIZE_NAME];
    matrix *mat;
} mats[] = {
        {"MAT_A", &MAT_A},
        {"MAT_B", &MAT_B},
        {"MAT_C", &MAT_C},
        {"MAT_D", &MAT_D},
        {"MAT_E", &MAT_E},
        {"MAT_F", &MAT_F},
        {"non", NULL}
      };

struct
{
    char name[SIZE_FUNC];
    void (*func)(void);
} cmd[] = {
        {"read_mat", read_mat},
        {"not_valid", NULL}
      };

我的制作文件:

int_loop: my_math.o int_loop.o
    gcc -g -ansi -Wall -pedantic my_math.o int_loop.o -o int_loop

int_loop.o : int_loop.c
    gcc -c -ansi -Wall -pedantic int_loop.c -o int_loop.o

my_math.o : my_math.c
    gcc -c -ansi -Wall -pedantic my_math.c -o my_math.o

我一直在尝试用各种技术解决这个问题,但没有成功。

我收到的错误是:

gcc -g -Wall -ansi -pedantic main.o mat.o -o mamantest
mat.o:(.data+0x0): multiple definition of `mats'
main.o:(.data+0x0): first defined here
mat.o:(.data+0x70): multiple definition of `cmd'
main.o:(.data+0x70): first defined here
collect2: ld returned 1 exit status
make: *** [mamantest] Error 1

为什么会出现这个错误?我该如何解决这个问题?

谢谢

4

1 回答 1

3

In the header file you define the variables mats and cmd, meaning both translation units (both source files that includes the header file) will have those defined.

The variables should be defined only in a single place, in a single source file, like

struct mat mats[7] = { ... };

The above defines the array mats, and like I said should be done in only one place.

For the other source file you declare the variables, which can be done in the header file like e.g.

extern struct mat
{
    ...
} mats[7];

The above declare the variable mats as an array of seven mat structures. It also define the structure so it can be used to e.g. define the array.


After modifications suggested above, the complete header file should look something like

// First header include guards (see https://en.wikipedia.org/wiki/Include_guard)
#ifndef GENERIC_STRUCTS_H
#define GENERIC_STRUCTS_H

#define SIZE 4
#define SIZE_NAME 5
#define SIZE_FUNC 10

typedef double matrix[SIZE][SIZE];

// Declare the variables (note the added use of the extern keyword)
extern matrix MAT_A, MAT_B, MAT_C, MAT_D, MAT_E, MAT_F;

void read_mat(void);

// Define a structure named mat (note added structure tag name)
struct mat
{
    char name[SIZE_NAME];
    matrix *mat;
};

// Define a structure named command (note added structure tag name)
struct command
{
    char name[SIZE_FUNC];
    void (*func)(void);
};

// Now declare variables of the previous structures
extern struct mat mats[7];
extern struct command cmd[2];

// End of header include guard
#endif

That header file only declares variables, and can be included in all your source files.

Then in a single source file (for example your main.c file) you do the actual variable definitions:

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

matrix MAT_A, MAT_B, MAT_C, MAT_D, MAT_E, MAT_F;

struct mat mats[7] = {
    {"MAT_A", &MAT_A},
    {"MAT_B", &MAT_B},
    {"MAT_C", &MAT_C},
    {"MAT_D", &MAT_D},
    {"MAT_E", &MAT_E},
    {"MAT_F", &MAT_F},
    {"non", NULL}
};

struct command cmd[2] = {
    {"read_mat", read_mat},
    {"not_valid", NULL}
};

#define FOREVER for(;;)
#define INPUT_LEN 30

int main()
{
    ...
}

The important thing you need to learn here is that there is a difference between declaring and defining something.

A declaration is basically telling the compiler that "this thing exists somewhere", and a definition is telling the compiler "this is the thing".

The problem is that unless a thing has already been declared, a definition is also a declaration, and many simply call these combined definitions/declarations just declaration, which muddles the whole concept up a bit.

于 2016-05-23T18:06:41.203 回答