我在一个文件中定义了一个全局变量char buf[1024]
,在其他文件中声明它的正确性是什么? extern char buf[1024]
,extern char buf[]
或extern char *buf
?我发现extern char buf[]
有效,extern char *buf
没有,但想了解更多解释。
答案 0 :(得分:4)
答案 1 :(得分:0)
extern char buf []和extern char buf [1024]都可以。
在某些情况下,数组是通过指针实现的,例如在两个函数之间传递参数。
答案 2 :(得分:0)
当您将变量设置为extern时,您向编译器指示变量的符号(地址)将在另一个.o文件中找到 - (这在链接阶段完成)。
因此,当您将变量设为extern时,您只需要提及名称,因为它将提供有关地址和大小的信息不是必需的
答案 3 :(得分:0)
这是数组和指针可以互换的老问题。数组和指针是不可互换的:它们恰好恰好在大多数情况下,因为大多数时候你在表达式中使用数组名称,它会衰减成指针。
在一个文件中定义为char数组并在另一个文件中声明为char指针的特定情况在Expert C Programming - Deep C Secrets中有详细说明;见第4章。
数组的声明为您提供了一个数组,指针的声明为您提供了一个指针。区别在于数组是地址 - 第一个元素的地址 - 并且它不是可修改的l值,即它不能被分配。另一方面,指针是一个保存地址的变量。
通常,上下文足以判断您是指变量的地址还是赋值中变量的内容。声明
i = j;
说要将j
的内容存储在i
的地址中。在编译器行话中,i
被认为是l值,j
是r值。编译器必须生成代码,将j
的内存地址内容写入i
的内存地址。
考虑这些声明:
char a[1024];
char *a;
撰写a[i] = j;
时会发生什么?
对于前一种情况,编译器将只选择a
的内容的地址,这些内容在数组中是第一个元素的地址;缩放i
,并将其加到基址。然后它会将存储j
的地址的内容写入该地址。
对于后一种情况,它是完全不同的:编译器必须检查存储a
的内存位置,加载该内存位置的内容,使用THAT作为地址,并写入{的内容{1}}进入该地址。
如果在j
:
file1.c
然后在char a[] = "Hello";
file2
然后,在extern char *a;
中执行a[0] = 'x';
将崩溃:因为您告诉编译器file2.c
是一个指针,它将检查a
' s值存储。实际上,这个地址保存着a
的字符代码,但是编译器错误地将其解释为地址,并最终生成代码以将'H'
写入地址'x'
,其中,如果你很幸运,你的程序会因违反分段而崩溃。
因此,这是声明和定义必须匹配的情况:如果您将其声明为数组,则将其定义为数组;如果您将其声明为指针,请将其定义为指针。您必须将'H'
声明为其他文件中的字符数组。这些形式中的任何一种都是合法且等同的:
buf
或
extern char buf[1024];
答案 4 :(得分:0)
可分配的全局char变量。使所有人可见:
// shared_header.h
extern char current_mode[];
定义,实例化和更新:
// main.c
#include "shared_header.h"
char current_mode[160];
int main(int argc, char * argv [])
{
strcpy(current_mode, "MODE_CONFIGURE");
int a = randomNumber(102);
strcpy(current_mode, "MODE_EXECUTE");
int b = do_foo(a);
// other stuff
strcpy(current_mode, "MODE_TEARDOWN");
// close up shop
}
阅读或更新:
// foo.c
#include "shared_header.h"
int do_foo(int a)
{
printf("Current mode is %s", current_mode);
if (a > 100) {
strcpy(current_mode, "MODE_EXECUTE_SPECIAL_CASE");
printf("Switching to mode %s", current_mode);
}
// do useful things
}