如何link C ansi中的所有文件?多重定义错误

How to link all files in C ansi? Error with multiple definition

早上好

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

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

#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;
}

问题在这里:

main.c

#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;
}

myFunc.c

#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);

MakeFile

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(),然后发送给函数。我遇到的错误比我预期的要多。如果有人 link 或有相同问题的来源,我将很高兴获得此信息。

问题是您 #include "myFunc.c"main.c 中,所以您在编译的 main.o 中包含函数 show_boardadd_mark 等的实现对象,这些函数也包含在 myFunc.o 编译对象中,直接编译相同源文件的结果。链接器看到这一点后会抱怨,因为它不知道要使用哪个函数,以及您何时调用例如add_markmain中不知道调用哪个

解决你的问题,你只需要摘下线

#include "myFunc.c"

并在文件 myFunc.h 中也包含 myFuncHeaders.h,因此您可以检查头文件中给出的定义是否与您在文件 myFunc.c 中提供的实现兼容。

还有一个来自 make 的错误告诉你包含了一个规则表明 myFunc.o 文件依赖于 myFunc.o 这是一个循环依赖,这是一个错误 (不能为 make 提供带循环的依赖规则,因为如果它必须允许它们,它就永远不会结束)你需要改变

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

进入

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

并为main.o写一个类似的(默认使用内部make的版本,你会看到make调用了cc编译器,编译main.c而不是 gcc)

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

规则是认为,如果您触摸(编辑)任何文件 main.cmyFuncHeaders.h(这是最后一个,因为您已经修改了 [=24= 中定义的函数的接口],那么你需要重新编译main.cmain.o,否则最终的可执行文件会不一致(你的程序会崩溃)。