简体   繁体   English

C语言中的Extern-我在做什么错?

[英]Extern in C - what am I doing wrong?

I'm playing around, making a small chessgame in C, cause I haven't touched C for years. 我正在玩,用C进行小型棋牌游戏,因为我好几年没碰C了。

My main is a pretty simple test: 我的主要任务是一个非常简单的测试:

#include "ChessGame.h"

int main()
{
    initializeNewGame();
    onLift('a', '2');
    onSet('a', '3');
}

InitializeNewGame() is going to clear some buffers, and initialize the board. InitializeNewGame()将清除一些缓冲区,并初始化开发板。 The board is a simple struct, defined in: 电路板是一个简单的结构,定义如下:

chessBoardStructure.h: ChessBoardStructure.h:

struct chessboard
{
    char board[8][8];
};

struct chessboard* board;

When initialize is called, it utilizes a header called Chessboard.h. 调用initialize时,它利用名为Chessboard.h的标头。 This header has the responsibility of checking that the user is following the rules. 该标题负责检查用户是否遵守规则。 It also knows how to initalize the board. 它还知道如何启动董事会。

chessBoard.c 国际象棋棋盘

#include "chessBoardStructure.h"

extern struct chessboard * board;

void initializeBoard()
{
    board = malloc(sizeof(struct chessboard));
    /* Sets the array to the right chars */
 }

Now, from my understanding, I should now have defined the global variable, board. 现在,据我所知,我现在应该定义了全局变量board。 And to verify I print out the board after InitializeBoard() has been called from InitializeNewGame() . 并验证我打印出来后板InitializeBoard()已经从所谓的InitializeNewGame() All seems fine. 一切似乎都很好。

Now the InitializeGame() returns to main, and onLift() is called. 现在, InitializeGame()返回main,并onLift() This should verify some rules. 这应该验证一些规则。 The problem is, when onLift() is called in ChessGame.c as: 问题是,在ChessGame.c onLift()调用为:

ChessGame.c extern struct chessboard* board; ChessGame.c外部结构棋盘*板;

void onLift(char col, char row)
{

    short err = getValidMoves(liftedCol, liftedRow, &validEndPoints, &validRoads, board);
    if (err == -1)
        handleBadPiece();

    /* Do stuff */

}

The board is just full of -51. 板上只有-51。 When I set a watch on the board in the header, I see it being initialized, and then when InitializeGame() exits scope, it becomes the good ol' -51. 当我在表头的板上放置一个手表时,我看到它已初始化,然后在InitializeGame()退出范围时,它变成了很好的ol'-51。

What am I doing wrong here? 我在这里做错了什么?

I miss C++. 我想念C ++。 :-) :-)

Thank you! 谢谢!

Edit small example I tried changing the extern around as proposed, but the same thing happened. 编辑一个小例子,我尝试按照建议更改外部样式,但是发生了同样的事情。 See the below example. 请参见以下示例。

main.c main.c中

#include "a.h"

int main()
{
    masterInitialize();
    printData();

    return 0;
}

(Headers not shown, due to just declarations) (由于声明,没有显示标题)

ac AC

#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: %c\n", datastruct->data[i]);
}

bc 公元前

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

You've got things the wrong way around. 您遇到了错误的方法。

This should be in "chessBoard.c". 这应该在“ chessBoard.c”中。

struct chessboard* board;

and this should be in your header 这应该在您的标题中

extern struct chessboard * board;

As that'll tell all the files where you include it that there exists the variable board declared somewhere and at link time, it'll use the one you've declared in "chessBoard.c" 这样一来,所有文件都将包含在其中的变量board声明为包含链接的位置,并且在链接时将使用您在“ chessBoard.c”中声明的变量board

With the way you have it currently, each C file that includes the header will have it's own unique version of board 按照目前的方式,每个包含标头的C文件都将具有其自己独特的board版本

extern struct chessboard * board; doesn't define anything; 没有定义任何东西; it just declares the identifier board and that it is of type pointer to struct chessboard somewhere. 它只是声明标识符board ,并且它是在某处struct chessboard指针类型。

struct chessboard* board; is a (tentative) definition. 是(暂定)定义。 It defines a single variable with external linkage and static storage duration. 它定义了具有外部链接和静态存储持续时间的单个变量。 However, you've put it into the included source file, which is included in several places. 但是,您已将其放入包含的源文件中,该文件包含在多个位置。 Thus in every place that #include s this file will have a conflicting definition of board . 因此,在#include的每个地方,该文件的board定义都将冲突。

GCC on Linux will merge multiple definitions in separate translation units, but the C standard doesn't state that. Linux上的GCC会将多个定义合并到单独的翻译单元中,但是C标准没有说明。 Instead it says ( C11 6.9 : 而是说( C11 6.9

5 [...] If an identifier declared with external linkage is used in an expression (other than as part of the operand of a sizeof or _Alignof operator whose result is an integer constant), somewhere in the entire program there shall be exactly one external definition for the identifier; 5 [...]如果在表达式中使用了用外部链接声明的标识符(不是作为sizeof或_Alignof运算符的操作数的一部分,其结果是一个整数常量),则在整个程序中的某个位置应恰好有一个标识符的外部定义 otherwise, there shall be no more than one. 否则,不得超过一个。

In your code there were multiple definitions for the same identifier, which will cause your program to have undefined behaviour, because C11 4p2 : 在您的代码中,同一标识符具有多个定义 ,这将导致您的程序具有未定义的行为,因为C11 4p2

If a ''shall'' or ''shall not'' requirement that appears outside of a constraint or runtime- constraint is violated, the behavior is undefined. 如果违反了在约束或运行时约束之外出现的“应”或“不应”要求,则该行为未定义。 [...] [...]


However (I guess it is) POSIX prescribes the common extension J.5.11 : 但是(我想是)POSIX规定了通用扩展名J.5.11

J.5.11 Multiple external definitions J.5.11多个外部定义

There may be more than one external definition for the identifier of an object, with or without the explicit use of the keyword extern ; 无论是否显式使用关键字extern ,一个对象的标识符可能有多个外部定义; if the definitions disagree, or more than one is initialized, the behavior is undefined (6.9.2). 如果定义不一致,或者初始化了多个定义,则行为未定义(6.9.2)。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM