【问题标题】:c syntax error on common variables between different .c files不同.c文件之间公共变量的c语法错误
【发布时间】:2019-05-21 09:06:54
【问题描述】:

我可能在 c 中遇到语法问题。我有 main.c 和 test.c 我正在尝试使用公共变量。
文件 main.c

extern int a;
extern int b;
uint8_t matrix[(a+1)*b][4];
testFunction(matrix, 10)

文件 test.c

int a=1;
int b=2;
void testFunction(matrix[(a+1)*b][4], uint8_t z){
....}

如果我编译我得到错误“在范围内进行可变修改”。我将 main.c 上的 a+1 更改为 2,我得到了多个定义错误。有什么建议吗?

【问题讨论】:

  • void testFunction() 的定义没有为第一个参数提供 type
  • 您不能声明具有非常量维度的函数原型。
  • @Jean-FrançoisFabre 当然可以,使用 VLA。
  • 您收到的错误消息可能是“在文件范围内可变地修改'矩阵'”,而不是“在范围内可变地修改”。虽然我们知道您在这种情况下的意思,但请在以后准确地复制并粘贴错误消息。细节在计算机编程中很重要。
  • @Lundin 但不在全局范围内,并且以变量作为维度。这就是我的意思。

标签: c syntax


【解决方案1】:

您不能在文件范围内声明变长数组。使用具有外部链接的变量来衡量它们的大小也不是一个明智的主意。你可能想要的是这样的:

void testFunction (int x, int y, uint8_t matrix[x][y]);

在调用者中计算xy,而不是作为函数声明的一部分。

(有种方法可以在函数声明中进行大小计算,但它们很混乱,导致代码不可读。)

【讨论】:

  • 问题中的问题是定义一个数组,而不是将其传递给函数。
  • @EricPostpischil 您不能在文件范围内声明可变长度数组。使用具有外部链接的变量来衡量它们的大小也不是一个明智的主意。
  • 是的,您不能在文件范围内声明可变长度数组。所以OP需要一个替代方案。他们需要一种方法来定义他们想要定义的数组,无论是块范围内的可变长度数组还是分配的数组或在已知大小的情况下定义的恒定大小数组。这个答案没有提出这样的解决方案。它没有回答问题中的问题。
【解决方案2】:

文件范围内的可变修改数组是不可能的。在这种情况下,编译器uint8_t matrix[(a+1)*b][4] 在生成目标文件时无法确定ab 的值。即使可以,这仍然是一个问题,因为数组在开始时是在静态内存中配置的,并且变量可以随时更改。但是,您可以在块范围内拥有可变修改的数组。

不确定您的确切要求,但您在 C99 中的问题的解决方案可能是将 testFunction 声明为:

void testFunction(int x, uint8_t matrix[x][4], uint8_t z) { ... }

并将其称为:

#define AVAL 1
#define BVAL 2
int a= AVAL;
int b= BVAL;
uint8_t matrix[(AVAL+1)*BVAL][4];
testFunction((a+1)*b, matrix, 10);

【讨论】:

  • 您的方式看起来更好,但如果我进行建议的更改,我仍然会收到“第一次定义”here错误。
  • @kostas 您还需要调整原型。仅实现是不够的。
  • @kostas 你能告诉我确切的错误吗?您在哪个文件中遇到错误?
【解决方案3】:

如果在编译时知道矩阵的大小,则可以将其定义为全局对象,但必须知道其尺寸(C 整数常量表达式)在哪里定义。如果test.c 知道维度,它可以定义矩阵,如下所示:

#define a 1
#define b 2
uint8_t matrix[(a+1)*b][4];

然后可以通过在main.c 中声明(但不定义)矩阵来访问它:

extern uint8_t matrix[][4];

如果main.c 还需要知道ab,您可以将这些值放在全局对象中,尽管您需要为这些对象使用与我上面显示的预处理器宏不同的名称。 (从技术上讲,有一种方法可以为两者使用相同的名称,但通常不建议这样做。)

如果您的矩阵大小在运行时而不是编译时已知,那么您可以使用malloc 创建它。例如,在main.c 中,您可以:

extern uint8_t (*matrix)[4];

int main(void)
{
    … Ensure the values of a and b have been set.

    matrix = malloc((a+1)*b * sizeof *matrix);
    if (!matrix) … Handle error

    … Rest of program.

    free(matrix); // (Not strictly necessary in typical multi-user systems.)
}

无论哪种情况,我都展示了在外部可见的矩阵,因为这是您在代码中尝试的。但是,由于您将矩阵作为参数传递给函数,因此您可能不需要矩阵在外部可见,也不需要使用静态存储持续时间对其进行定义。在这种情况下,您可以在 main 中定义它并将其传递给函数:

int main(void)
{
    … Ensure the values of a and b have been set.

    uint8_t (*matrix)[4] = malloc((a+1)*b * sizeof *matrix);
    if (!matrix) … Handle error

    testFunction(matrix, z);
    … Rest of program.

    free(matrix); // (Not strictly necessary in typical multi-user systems.)
}

也可以在main里面定义矩阵:

int main(void)
{
    … Ensure the values of a and b have been set.

    uint8_t matrix[(a+1)*b)][4];

    testFunction(matrix, z);
    … Rest of program.
}

但是,只有在已知 ab 很小时才应使用此选项。在大多数 C 实现中,可用于在块范围内提供数组定义的资源非常有限。

【讨论】:

  • uint8_t (*matrix)[4] 是一个指针,而不是一个数组。您没有包含相关的头文件 stdlib.h 和 stdint.h,因此这将导致 C90 中的错误。 不会编译,因为它不是有效的 C,C 中的 cmets 是用 ///* */ 编写的。这不起作用uint8_t [(a+1)*b)][4];,因为没有变量名。
  • @Lundin: (a) 当然uint8_t (*matrix)[4] 是一个指针,而不是一个数组。答案并没有说它是一个数组。关于该代码,它说“您可以使用malloc 创建它[数组]。”然后代码使用malloc 创建数组。 matrix 仅用于指向分配的对象。 (b) 问题中的代码已经使用来自stdint.h的声明,因此无需说明;它已经被隐式合并(并且您的答案使用uint8_t,但不包括stdint.h)。我已经明确添加了stdlib.h
  • @Lundin: (c) 不打算编译。众所周知,它只是标记其他代码可以去哪里。 (d) 我已经修复了丢失的名字。
猜你喜欢
  • 2023-03-27
  • 1970-01-01
  • 2010-11-05
  • 1970-01-01
  • 2015-03-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多