我正在使用Keil C51编译器来编程8051微控制器。由于某些原因,我的代码没有运行 - 我设法追踪错误,但我仍然难以理解它。为什么第一个代码与另一个代码相比是错误的?值得注意的是,编译器没有抛出任何错误,代码甚至没有在微控制器上启动。
错误的代码:
file1.h
extern STRUCT_TYPEDEF array_var[];
file2.c中
// Global variable initialization
STRUCT_TYPEDEF array_var[] = some_struct.array2_var;
将这些更改为:
file1.h
extern STRUCT_TYPEDEF *array_var;
file2.c中
// Global variable initialization
STRUCT_TYPEDEF *array_var = &some_struct.array2_var[0];
它开始工作了。
此外,这部分代码仅在“array_var [0] .property = ...”等函数中引用,但这些函数都没有从应用程序中调用过。
some_struct变量在另一个模块中声明。
为什么它会像那样? []和*之间有什么区别我不知道吗?
EDIT1: 据说指针和数组是不同的东西......但是,“[]”语法与“*”的区别是什么?我认为只要方括号为空(例如函数参数),编译器就会将其转换为指针。我还认为提供一个数组会导致给我第一个元素的地址。
现在,每个人都在说指针和数组是不同的 - 但我找不到任何关于它们究竟有什么不同的信息。当我将数组作为rvalue而不是指向其第一个元素的指针时,编译器如何看待它?
答案 0 :(得分:7)
STRUCT_TYPEDEF array_var[] = some_struct.array2_var;
不是在声明中初始化数组的有效方法。数组初始值设定项必须是大括号括起来的初始值设定项列表,例如
T arr[] = { init1, init2, init3 };
您不能使用另一个数组 1 初始化数组,也不能以这种方式将一个数组分配给另一个数组:
T foo[] = { /* list of initializers */ }
T bar[] = foo; // not allowed
T bar[N];
...
bar = foo; // also not allowed
如果您要将some_struct.array2_var
的内容复制到array_var
,则必须使用memcpy
之类的库函数:
memcpy( array_var, some_struct.array2_var, sizeof some_struct.array2_var );
您还必须声明array_var
的大小;如果你想使用它,你就不能完整。如果你提前知道它需要多大,那很简单:
STRUCT_TYPEDEF array_var[SIZE];
...
mempcy( array_var, some_struct.array2_var );
如果你没有提前知道它需要多大,那么你要么必须将它声明为一个可变长度数组(它赢得了&#39 ;如果它需要在文件范围内或具有static
存储持续时间,则工作,或者您可以动态声明内存:
STRUCT_TYPEDEF *array_var = NULL;
...
array_var = malloc( sizeof some_struct.array2_var );
if ( array_var )
{
memcpy( array_var, some_struct.array2_var, sizeof some_struct.array2_var );
}
这都假设some_struct.array2_var
是一个声明为
STRUCT_TYPEDEF array2_var[SIZE];
如果它只是一个指针,那么你必须以其他方式跟踪数组大小。
修改强>
如果您希望array_var
只是指向到some_struct.array2_var
的第一个元素,那么您可以执行以下操作:
STRUCT_TYPEDEF *array_var = some_struct.array2_var;
除非它是sizeof
或一元&
运算符的操作数,否则表达式类型为" N元素数组T
"将被转换("衰减")到类型为&#34的表达式;指向T
"的指针,并且表达式的值将是第一个元素的地址。阵列。上面的代码完全等同于
STRUCT_TYPEDEF *array_var = &some_struct.array2_var[0];
<小时/>
char message[] = "Hello";
;字符串文字"Hello"
是一个数组表达式,但该语言将其视为一种特殊情况。
答案 1 :(得分:1)
这......
extern STRUCT_TYPEDEF array_var[];
...是一个未知大小和外部链接的数组的声明。由于未指定大小,因此该声明会使array_var
留下&#34;不完整类型&#34 ;;除非其类型由同一翻译单元中的另一个声明完成,否则会阻止对该变量的某些使用。例如,它不能是sizeof
运算符的操作数。
这......
STRUCT_TYPEDEF array_var[] = some_struct.array2_var;
...由于提供了初始化程序,声称是array_var
的定义。 然而,初始化程序的数组类型变量的格式不正确。数组初始值设定项由一个或多个数组元素的逗号分隔序列组成,在强制大括号({}
)内。正如C不支持整数组赋值一样,它也不支持数组值作为数组初始化器。
相比之下,这......
extern STRUCT_TYPEDEF *array_var;
...是带有外部链接的指针的声明。它有一个完整的类型。这......
STRUCT_TYPEDEF *array_var = &some_struct.array2_var[0];
...是变量的有效定义,带有合适的初始化程序。因为数组值在这个上下文中衰减为指针,就像大多数(但不是全部)其他的一样,它等同于:
STRUCT_TYPEDEF *array_var = some_struct.array2_var;
在将其与原始代码进行比较时,必须要了解尽管它们具有紧密关联,但指针和数组是完全不同的类型。
此外,这部分代码仅在&#34; array_var [0] .property = ...&#34;等函数中引用,但这些函数都没有从应用程序中调用过。
是否正常访问变量与编译器是否愿意接受代码无关。
[]和*之间是否存在一些差异?我不知道?
显然是这样,因为这个问题似乎假设没有区别。
这两种形式可以互换使用,用于声明功能参数。在该上下文中,都将参数声明为指针。这是一种符号和代码清晰度方便,因为作为函数参数出现的数组值会衰减到指针。你永远不能将数组作为函数参数传递 - 当参数指定数组时,会传递指针。
然而,如上所述,两种形式不等同于声明普通变量。