global char []变量,如何在其他文件中声明它?

时间:2013-11-22 08:51:48

标签: c arrays pointers global extern

我在一个文件中定义了一个全局变量char buf[1024],在其他文件中声明它的正确性是什么? extern char buf[1024]extern char buf[]extern char *buf?我发现extern char buf[]有效,extern char *buf没有,但想了解更多解释。

5 个答案:

答案 0 :(得分:4)

您可以使用

extern char buf[];

extern char *buf;

因为数组不是指针

参考:C FAQ

答案 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
}