我正在玩耍,在C中制作一个小棋子,因为我多年来都没有碰过C。
我的主要测试是一个非常简单的测试:
#include "ChessGame.h"
int main()
{
initializeNewGame();
onLift('a', '2');
onSet('a', '3');
}
InitializeNewGame()
将清除一些缓冲区,并初始化板。板是一个简单的结构,定义为:
CHESSBOARDSTRUCTURE.H:
struct chessboard
{
char board[8][8];
};
struct chessboard* board;
调用初始化时,它会使用一个称为Chessboard.h的标头。该标头有责任检查用户是否遵守规则。它也知道如何使董事会归化。
Chessboard.c
#include "chessBoardStructure.h"
extern struct chessboard * board;
void initializeBoard()
{
board = malloc(sizeof(struct chessboard));
/* Sets the array to the right chars */
}
现在,从我的理解中,我现在应该定义全局变量,板。为了验证我从InitializeNewGame()
调用InitializeBoard()
之后打印出板。一切都很好。
现在InitializeGame()
返回到MAIN,onLift()
被调用。这应该验证一些规则。问题是,当onLift()
在Chessgame.c中称为:
ChessGame.C 外部结构棋盘*板;
void onLift(char col, char row)
{
short err = getValidMoves(liftedCol, liftedRow, &validEndPoints, &validRoads, board);
if (err == -1)
handleBadPiece();
/* Do stuff */
}
董事会刚好为-51。当我在标头的板上设置手表时,我会看到它是初始化的,然后当InitializeGame()
退出范围时,它变成了良好的OL' -51。
我在这里做错了什么?
我想念C 。: - (
谢谢!
编辑小示例我试图按建议改变周围的外部,但也发生了同样的事情。请参见下面的示例。
main.c
#include "a.h"
int main()
{
masterInitialize();
printData();
return 0;
}
(仅由于声明而未显示标题(
A.C
#include "a.h"
#include "b.h"
#include "struct.h"
#include <stdio.h>
struct mystruct* datastruct;
void masterInitialize()
{
initializeDataStruct();
}
void printData()
{
for (int i = 0; i < 10; i++)
printf("Data: %cn", datastruct->data[i]);
}
b.c
#include "b.h"
#include "struct.h"
#include <stdlib.h>
struct mystruct* datastruct;
void initializeDataStruct()
{
datastruct = malloc(sizeof(struct mystruct));
for (int i = 0; i < 10; i++)
datastruct->data[i] = 1;
}
struct.h
struct mystruct
{
char data[10];
};
extern struct mystruct* datastruct;
你有错误的方式。
这应该在" Chessboard.c"中。
struct chessboard* board;
这应该在您的标题中
extern struct chessboard * board;
因为这将告诉所有您包含在哪里的文件,该文件存在在某个地方声明的变量board
,在链接时间,它将使用您在" Chessboard.c"中声明的一个文件。
使用您当前的方式,包括标头的每个C文件都有其自己的唯一版本的board
extern struct chessboard * board;
dewine nothing;它只是声明了标识符board
,并且它是类型的指针到某处的struct chessboard
。
struct chessboard* board;
是(暂定(定义。它定义了一个具有外部链接和静态存储持续时间的单个变量。但是,您已将其放入随附的源文件中,该文件包含在几个地方。因此,在#include
s的每个地方,此文件都会对board
进行冲突的定义。
GCC将在单独的翻译单元中合并多个定义,但C标准不指出。相反,它说(C11 6.9:
5 [...]如果在表达式中使用了带有外部链接的标识符(作为sizeof或_alignof运算符的操作数的一部分,其结果是整数常数(,则在整个程序中的某个地方应完全是标识符的一个外部定义;否则,不得超过一个。
在您的代码中,同一标识符有多个定义,这会导致您的程序具有不确定的行为,因为C11 4P2:
如果A ''warm''或" warge nonge"要求出现在约束或运行时 - 约束之外的要求,行为是未定义的。> [...]
但是(我想是(Posix规定了通用扩展J.5.11:
J.5.11多个外部定义
,对于对象的标识符,可能有一个以上的外部定义,无论是否明确使用关键字
extern
;如果定义不同意,或者是一个以上的初始化,则该行为是不确定的(6.9.2(。