首页 > 解决方案 > 如何链接C ansi中的所有文件?多重定义错误

问题描述

早上好

链接所有文件( main.c、myFunc.c、myFuncHeaders.hMakeFile)对我来说是个大问题。当我不知道该怎么做时,问题是多重定义。我使用了全局变量char board[3][3]和. 我知道 global 将是不必要的和糟糕的设计程序,但我想尝试一些新的东西。简单的井字游戏char board_checked[3][3]int playersRound

在一个文件中(多合一),代码有效。这里:

#include<stdio.h>
#include <stdlib.h>

char board[3][3] = {{'_', '_', '_'},{'_', '_', '_'},{'_', '_', '_'} };
char board_checked[3][3] = {{'+', '+', '+'},{'+', '+', '+'},{'+', '+', '+'}};
int playersRound = 0;

// It shows board
void show_board(){
    char * space = "          ";
    puts("\tPlansza\n\t==================================");
    for(int i = 1; i < 4; i++)
    {
        printf("%s|%d|", space, i);
    }
        printf("\n");
    for(int i = 0; i < 3; i++){
        printf("\t|%d|",i+1);
        for(int j = 0; j < 3; j++)
        {
            printf("%c  %s", board[i][j], space);
        }
        printf("\n\n");
    }
    puts("\t==================================\n");
}


// This function add a player's mark - 'X' or 'O' - to board
void add_mark(int *p, int player){
    // If it isn't reserved by other mark
    if(board_checked[p[0]-1][p[1]-1] != '-'){
        // x (p[1]) and y (p[0]) vectors are (1, 2, 3)
        if(1 <= p[0] && p[0] <= 3 && 1 <= p[1] && p[1] <= 3)
        {
            if(player == 1)
            {
                // Add to board 'X'
                board[p[0]-1][p[1]-1] = 'O';
                // and unchecked at the same position 'board_checked'
                board_checked[p[0]-1][p[1]-1] = '-';

            }
            else
            {
                // Add to board 'X'
                board[p[0]-1][p[1]-1] = 'X';
                // and unchecked at the same position 'board_checked'
                board_checked[p[0]-1][p[1]-1] = '-';
            }
            // If Everything is Okey go to next playersRound
            playersRound++;
        }
    }
    else
        // On start variable is position[2] = {0,0}; it's mean that I made exception
        if(!(0 == p[0] && 0 == p[1]))
        {
            puts("Nie podales poprawnych parametrow");
            sleep(2);
        }
}


// This function check every position where any mark have been added
int structure_check(int player){
    //return winner
    for(int i = 0; i < 2; i++){
        // Check horizontal
        for(int level = 0; level < 3; level++)
            if(board[level][0] == board[level][1] && board[level][0] == board[level][2] && board[level][0] != '_')return player;
        // Check vertical
        for(int level = 0; level < 3; level++)
            if(board[0][level] == board[1][level] && board[0][level] == board[2][level] && board[0][level] != '_')return player;
        // Check diagonal left
        if(board[0][0] == board[1][1] && board[0][0] == board[2][2] && board[0][0] != '_')return player;
        // Check diagonal right
        if(board[2][0] == board[1][1] && board[2][0] == board[0][2] && board[0][2] != '_')return player;
    }
    // Draw - when no one of two players won
    return 0;
}



int main(char argc, char * argv[]){
    int player = 1;
    int position[2] = {0,0};
    int status = 0;



    show_board();


    while(playersRound < 10){
        // Short information
        if(player == 1) puts("Gracz 1:");
        else puts("Gracz 2:");
        // Get position
        printf("\tx:"); scanf("%d", &position[0]);
        printf("\ty:"); scanf("%d", &position[1]);
        // status game, win or draw
        status = structure_check(player);
        // Players movement in playersRounds
        if(playersRound%2 == 0) player = 1;
        else player = 2;
        // This add mark to board by player
        add_mark(position, player);
        // Clear console
        system("cls");
        // Show only board
        show_board();
        // To be sure it works
        status = structure_check(player);
        // It finish when someone won game
        if(status != 0) break;
    }

    if(player == 1)
        printf("Wygrywa gracz: 1 z  'O'");
    else
        printf("Wygrywa gracz: 2 z  'X'");
    puts("  ||| Gratulacje! |||");

    return 0;
}

问题在这里:

主程序

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include "myFunc.c"
#include "myFuncHeaders.h"



int main(char argc, char * argv[]){
    int player = 1;
    int position[2] = {0,0};
    int status = 0;
    
    

    show_board();
    

    while(playersRound < 10){
        // Short information
        if(player == 1) puts("Gracz 1:");
        else puts("Gracz 2:");
        // Get position
        printf("\tx:"); scanf("%d", &position[0]);
        printf("\ty:"); scanf("%d", &position[1]);
        // status game, win or draw
        status = structure_check(player);
        // Players movement in playersRounds
        if(playersRound%2 == 0) player = 1;
        else player = 2;
        // This add mark to board by player
        add_mark(position, player);
        // Clear console
        system("clear");
        // Show only board
        show_board();
        // To be sure it works
        status = structure_check(player);
        // It finish when someone won game
        if(status != 0) break;
    }

    if(player == 1)
        printf("Wygrywa gracz: 1 z  'O'");
    else
        printf("Wygrywa gracz: 2 z  'X'");
    puts("  ||| Gratulacje! |||");

    return 0;
}

我的函数

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h> // sleep() 
#include "myFuncHeaders.h"

char board[3][3] = {{'_', '_', '_'},{'_', '_', '_'},{'_', '_', '_'} };
char board_checked[3][3] = {{'+', '+', '+'},{'+', '+', '+'},{'+', '+', '+'}};
int playersRound = 0;

// It shows board 
void show_board(){
    char * space = "          ";
    puts("\tPlansza\n\t==================================");
    for(int i = 1; i < 4; i++)
    {
        printf("%s|%d|", space, i);
    }
        printf("\n");
    for(int i = 0; i < 3; i++){
        printf("\t|%d|",i+1);
        for(int j = 0; j < 3; j++)
        {
            printf("%c  %s", board[i][j], space);
        }
        printf("\n\n");
    }
    puts("\t==================================\n");
}


// This function add a player's mark - 'X' or 'O' - to board
void add_mark(int *p, int player){
    // If it isn't reserved by other mark
    if(board_checked[p[0]-1][p[1]-1] != '-'){
        // x (p[1]) and y (p[0]) vectors are (1, 2, 3)
        if(1 <= p[0] && p[0] <= 3 && 1 <= p[1] && p[1] <= 3)
        {
            if(player == 1)
            {
                // Add to board 'X'
                board[p[0]-1][p[1]-1] = 'O';
                // and unchecked at the same position 'board_checked'
                board_checked[p[0]-1][p[1]-1] = '-';

            }
            else
            {
                // Add to board 'X'
                board[p[0]-1][p[1]-1] = 'X';
                // and unchecked at the same position 'board_checked'
                board_checked[p[0]-1][p[1]-1] = '-';
            }
            // If Everything is Okey go to next playersRound
            playersRound++;
        }
    }
    else
        // On start variable is position[2] = {0,0}; it's mean that I made exception
        if(!(0 == p[0] && 0 == p[1]))
        {
            puts("Nie podales poprawnych parametrow");
            sleep(2);
        }
}


// This function check every position where any mark have been added
int structure_check(int player){
    //return winner
    for(int i = 0; i < 2; i++){
        // Check horizontal
        for(int level = 0; level < 3; level++)
            if(board[level][0] == board[level][1] && board[level][0] == board[level][2] && board[level][0] != '_')return player;
        // Check vertical
        for(int level = 0; level < 3; level++)
            if(board[0][level] == board[1][level] && board[0][level] == board[2][level] && board[0][level] != '_')return player;
        // Check diagonal left
        if(board[0][0] == board[1][1] && board[0][0] == board[2][2] && board[0][0] != '_')return player;
        // Check diagonal right
        if(board[2][0] == board[1][1] && board[2][0] == board[0][2] && board[0][2] != '_')return player;
    }
    // Draw - when no one of two players won
    return 0;
}

myFuncHeaders.h

void show_board();
// This function add a player's mark - 'X' or 'O' - to board
void add_mark(int *p, int player);
// This function check every position where any mark have been added
int structure_check(int player);

生成文件

main:               main.o myFunc.o
                    gcc -o main main.o myFunc.o

myFunc.o:           myFunc.c myFunc.o
                    gcc -c -o myFunc.o myFunc.c

输出:

*my foleder*
~/zadania_domowe/kolko_krzyzyk $ make
cc    -c -o main.o main.c
make: circular version myFunc.o <- myFunc.o lost.
gcc -c -o myFunc.o myFunc.c
gcc -o main main.o myFunc.o
/usr/lib/gcc/x86_64-pc-linux-gnu/10.2.0/../../../../x86_64-pc-linux-gnu/bin/ld: myFunc.o:(.data+0x0): multiple definition of `board'; main.o:(.data+0x0): first defined here
/usr/lib/gcc/x86_64-pc-linux-gnu/10.2.0/../../../../x86_64-pc-linux-gnu/bin/ld: myFunc.o:(.data+0x10): multiple definition of `board_checked'; main.o:(.data+0x10): first defined here
/usr/lib/gcc/x86_64-pc-linux-gnu/10.2.0/../../../../x86_64-pc-linux-gnu/bin/ld: myFunc.o:(.bss+0x0): multiple definition of `playersRound'; main.o:(.bss+0x0): first defined here
/usr/lib/gcc/x86_64-pc-linux-gnu/10.2.0/../../../../x86_64-pc-linux-gnu/bin/ld: myFunc.o: in function `show_board':
myFunc.c:(.text+0x0): multiple definition of `show_board'; main.o:main.c:(.text+0x0): first defined here
/usr/lib/gcc/x86_64-pc-linux-gnu/10.2.0/../../../../x86_64-pc-linux-gnu/bin/ld: myFunc.o: in function `add_mark':
myFunc.c:(.text+0xf5): multiple definition of `add_mark'; main.o:main.c:(.text+0xf5): first defined here
/usr/lib/gcc/x86_64-pc-linux-gnu/10.2.0/../../../../x86_64-pc-linux-gnu/bin/ld: myFunc.o: in function `structure_check':
myFunc.c:(.text+0x2a6): multiple definition of `structure_check'; main.o:main.c:(.text+0x2a6): first defined here
collect2: error: ld returned 1 exit status
make: *** [makefile:2: main] Error 1

我尝试使用extern全局,将这个全局变量放入main()然后发送给函数。我的错误比我预期的要多。如果有人有相同问题的链接或来源,我会很高兴获得这些信息。

标签: clinuxgccmakefilemultiple-definition-error

解决方案


The problem is that you #include "myFunc.c" in main.c so you include the implementations of functions show_board, add_mark, etc. in the main.o compiled object, and those functions are also included in the myFunc.o compiled object, result of compiling the same source file directly. The linker, on seeing this, complaints, as it cannot know which function to use, and when you make a call to e.g. add_mark in main it doesn't know which one is to be called.

To solve your problem, you just need to take off the line

#include "myFunc.c"

and include also myFuncHeaders.h in the file myFunc.h, so you can check that the definitions given in the header file are compatible with the implementations you provide in the file myFunc.c.

There is also an error from make telling that you have included a rule indicating that myFunc.o file depends on myFunc.o which is a circular dependence, and it is an error (make cannot be given dependency rules with loops, as it would never end if it had to allow them) you need to change

myFunc.o: myFunc.c myFunc.o
    gcc -c -o myFunc.o myFunc.c

into

myFunc.o: myFunc.c myFuncHeaders.h
    gcc -c -o myFunc.o myFunc.c

and write a similar one for main.o (which has been taken by default with the internal make's version, you will see that make has called cc compiler, to compile main.c instead of gcc)

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

The rule is to think that if you touch (edit) any of the files main.c or myFuncHeaders.h (this last because you have modified the interface to the functions defined in myFunc.c, then you need to create a new compilation of main.c to main.o, or the final executable will be inconsistent (and your program will crash).


推荐阅读