这个 C 错误是关于结构体的,它是什么意思?

3

请问有人能帮我理解C语言中关于结构体的错误吗?以下是我的代码:

struct Orientation
{
    char facing;
    char sensor;
    char mazeDir;
}; 

struct Orientation O[16];
O[0] = {'N', 'F', 'N'};
O[1] = {'N', 'B', 'S'};
O[2] = {'N', 'R', 'E'};
O[3] = {'N', 'L', 'W'};
O[4] = {'S', 'F', 'S'};
O[5] = {'S', 'B', 'N'};
O[6] = {'S', 'R', 'W'};
O[7] = {'S', 'L', 'E'};
O[8] = {'E', 'F', 'E'};
O[9] = {'E', 'B', 'W'};
O[10] = {'E', 'R', 'S'};
O[11] = {'E', 'L', 'N'};
O[12] = {'W', 'F', 'W'};
O[13] = {'W', 'B', 'E'};
O[14] = {'W', 'R', 'N'};
O[15] = {'W', 'L', 'S'};

我遇到了与O[13]、O[14]和O[15]有关的错误。

..\RMNCODE.C(282): error C231: 'O': redefinition
..\RMNCODE.C(283): error C279: 'O': multiple initialization
..\RMNCODE.C(283): error C231: 'O': redefinition
..\RMNCODE.C(284): error C279: 'O': multiple initialization
..\RMNCODE.C(284): error C231: 'O': redefinition
9个回答

8

请改为以下方式初始化数组:

struct Orientation O[16] = {
    {'N', 'F', 'N'},
    {'N', 'B', 'S'},
    {'N', 'R', 'E'},
    {'N', 'L', 'W'},
    {'S', 'F', 'S'},
    {'S', 'B', 'N'},
    {'S', 'R', 'W'},
    {'S', 'L', 'E'},
    {'E', 'F', 'E'},
    {'E', 'B', 'W'},
    {'E', 'R', 'S'},
    {'E', 'L', 'N'},
    {'W', 'F', 'W'},
    {'W', 'B', 'E'},
    {'W', 'R', 'N'},
    {'W', 'L', 'S'}
};

欢呼!

你能解释一下为什么O[13]和随后的行会导致错误吗? - John Feminella
这些错误对于所有行都是相同的,不仅仅是13、14和15行。 - ralphtheninja
我从未见过一个问题里有这么多几乎完全相同的答案! :) - Aiden Bell
哈哈,你必须得快点才能抢到这个声望。我甚至还成功编译和测试了。怎么样?;) - ralphtheninja
4
@Magnus,幸好幸好……当橙色死亡条出现时,我还在使用vim。 - Aiden Bell
"橙色死亡条" 嘿嘿嘿 :) - ralphtheninja

5

如果要初始化O,您需要在声明的一部分中一次性完成:

struct Orientation O[16] = {
  { 'N', 'F', 'N' },
  { 'N', 'B', 'S'),
  ...

};

你不能这样做:

O[0] = {'N', 'F', 'N'};

因为C语言不支持在语句中使用结构体字面量,只能作为初始化列表的一部分。


我认为这样会没问题:O[0] = (char []){'N','F','N'}; 参考 http://gcc.gnu.org/onlinedocs/gcc/Compound-Literals.html#Compound-Literals - Allan Ruin
@AllanRuin:是的,但那是GCC的扩展,不是标准C。 - Ferruccio

3

你必须使用单个初始化器来初始化O,或者在初始化函数中逐个赋值给其成员。你不能像你所做的那样在函数外使用赋值表达式。

例如:

struct Orientation O[16] = { {'N', 'F', 'N'}, {'N', 'B', 'S'} /* , ... */ };

或者

void InitializeO(void)
{
    O[0].facing = 'N';
    O[0].sensor = 'F';
    O[0].mazeDir = 'N';

    O[1].facing = 'N';
    O[1].sensor = 'B';
    O[1].mazeDir = 'S';

    /* ... */
}

2

通过初始化更改赋值。

struct Orientation { char facing; char sensor; char mazeDir; };

struct Orientation O[16] = 
{{'N', 'F', 'N'},
{'N', 'B', 'S'}, 
{'N', 'R', 'E'}, 
{'N', 'L', 'W'}, 
{'S', 'F', 'S'}, 
{'S', 'B', 'N'}, 
{'S', 'R', 'W'}, 
{'S', 'L', 'E'}, 
{'E', 'F', 'E'}, 
{'E', 'B', 'W'}, 
{'E', 'R', 'S'}, 
{'E', 'L', 'N'}, 
{'W', 'F', 'W'}, 
{'W', 'B', 'E'}, 
{'W', 'R', 'N'}, 
{'W', 'L', 'S'}};

1

你不能像你现在这样赋值一个结构体。你需要显式地进行赋值:

O[0].facing = 'N';
O[0].sensor = 'F';
O[0].mazeDir = 'N';

O[1].facing = 'N';
O[1].sensor = 'B';
O[1].mazeDir = 'S';

//etc...

或者你可以像Magnus建议的那样初始化结构体。


1

尝试

struct Orientation O[16] = {
    { 'W','L','S'},
    { 'W', 'R', 'N'},
    ...
}

1

虽然这不是直接回答你的问题,但你可以通过遵循以下语法来解决问题:

struct Orientation O[16] = {
  {'N', 'F', 'N' },
  {'N', 'B', 'S'},
  {'N', 'R', 'E'},
  {'N', 'L', 'W'},
  ...
};

1

C89没有结构体字面量。它确实有初始化列表,看起来像是字面量,但实际上并不是。

这意味着您只能在变量定义时执行“初始化赋值”一次:

struct Orientation O[16] = {
  {'N', 'F', 'N'},
  ...
};

在C99中,这已经改变了,请参见评论中的链接。

0

如果您想在稍后分配值,那么复合字面值就是您要寻找的。您需要的语法如下:

struct Orientation O[16];
O[0] = (struct Orientation){'N', 'F', 'N'};
O[1] = (struct Orientation){'N', 'B', 'S'};
O[2] = (struct Orientation){'N', 'R', 'E'};
O[3] = (struct Orientation){'N', 'L', 'W'};
O[4] = (struct Orientation){'S', 'F', 'S'};
O[5] = (struct Orientation){'S', 'B', 'N'};
O[6] = (struct Orientation){'S', 'R', 'W'};
O[7] = (struct Orientation){'S', 'L', 'E'};
O[8] = (struct Orientation){'E', 'F', 'E'};
O[9] = (struct Orientation){'E', 'B', 'W'};
O[10] = (struct Orientation){'E', 'R', 'S'};
O[11] = (struct Orientation){'E', 'L', 'N'};
O[12] = (struct Orientation){'W', 'F', 'W'};
O[13] = (struct Orientation){'W', 'B', 'E'};
O[14] = (struct Orientation){'W', 'R', 'N'};
O[15] = (struct Orientation){'W', 'L', 'S'};

优点是它可以在函数内的任何地方完成,而不仅仅是在初始化时。

虽然正如其他人建议的那样,你可以将其重写为:

struct Orientation O[16] = 
{
    {'N', 'F', 'N'},
    {'N', 'B', 'S'}, 
    {'N', 'R', 'E'},
    ...
};

甚至更好

struct Orientation O[16] =
{
    [0] = {'N', 'F', 'N'},
    [1] = {'N', 'B', 'S'},
    [2] = {'N', 'R', 'E'},
    [3] = {'N', 'L', 'W'},
    ...
};

如果您只想在初始化时分配值。


你只能在函数体内使用这些赋值语句(特别是,你不能在“任何地方”使用它们,当然也不能像 OP 在函数外部、紧接着类型声明的位置使用它们)。 - jogojapan
@jogojapan,你怎么知道OP不是在函数体内使用它们?问题缺乏任何迹象。可以在“任何地方”进行赋值。我看到的方式是他试图在稍后的时间将一个值分配给O的索引之一。 - Wiz
我知道 OP 正在函数体外使用代码,否则错误消息将是关于直接将 {...} 赋值给变量是非法的。但是错误消息是关于多个定义的。 - jogojapan

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接