c - 如何链接C ansi中的所有文件?多重定义错误
问题描述
早上好
链接所有文件( main.c、myFunc.c、myFuncHeaders.h和MakeFile)对我来说是个大问题。当我不知道该怎么做时,问题是多重定义。我使用了全局变量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()
然后发送给函数。我的错误比我预期的要多。如果有人有相同问题的链接或来源,我会很高兴获得这些信息。
解决方案
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).
推荐阅读
- javascript - 如何替换所有出现的字符,除非它包含在使用正则表达式的单词中
- c# - 使用Action时的执行顺序问题
- sql - 运行查询时是否可以跳过列?
- memory - T 或 F:如果使用分页虚拟内存的机器具有 24 位逻辑地址和 32 位物理地址,则永远不会发生页面错误
- c - BFS 算法返回分段错误
- node.js - 在发送邮件之前等待文件创建
- jenkins-pipeline - Jenkins 脚本化管道
- r-markdown - render() 与 word_document 的 Knit GUI
- java-8 - CompletableFuture List 等待所有未来的问题
- javascript - 在传单 OSM 上的附近搜索