C语言 我应该使用extern吗?

8iwquhpp  于 2023-04-19  发布在  其他
关注(0)|答案(2)|浏览(126)

我有以下文件:

  1. pass_args.c
  2. pass_args.h
  3. kbd.c
  4. kbd.h
  5. main.c
    我需要使用三个全局变量:freq、amp和波形。
    我应该使用extern在every .h文件中声明这些变量,并在其中一个.c文件中定义变量,还是创建一个global_variable. h,在global_variable. h中声明这些变量,并将此global_variable. h包含在every .c文件中。
    以下是最小可重复的示例:
    change_freq.c
#include "change_freq.h"

void increment_freq(double *frequency)
{
    (*frequency)++;
    if (*frequency == 1)
    {
        amp++;
    }
}

change_freq.h

#ifndef CHANGE_FREQ_H
#define CHANGE_FREQ_H

#include "global_variables.h"

void increment_freq(double *frequency);

#endif

global_variables.h

#ifndef GLOBAL_VARIABLES_H
#define GLOBAL_VARIABLES_H
double freq;
double amp;
#endif

main.c

#include "global_variables.h"
#include "change_freq.h"

int main()
{
    freq = 0;
    increment_freq(&freq);
    printf("Hello World!\n");
    printf("freq %lf\n", freq);
    printf("amp %lf\n", amp);
    return 0;
}
kq0g1dla

kq0g1dla1#

你的代码看起来很好。
这是你应该做的:
change_freq.c

#include "change_freq.h"

#include "global_variables.h"  // <<< add this line

void increment_freq(double frequency)
{
    frequency++;
    if (frequency == 1)
    {
        amp++;
    }
}

change_freq.h

#ifndef CHANGE_FREQ_H
#define CHANGE_FREQ_H

// #include "global_variables.h"  <<< remove this line

void increment_freq(double frequency);

#endif

global_variables.h

#ifndef GLOBAL_VARIABLES_H
#define GLOBAL_VARIABLES_H
extern double freq;   // << put extern here
extern double amp;
#endif

main.c

#include <stdio.h>
#include "global_variables.h"
#include "change_freq.h"

double freq;   // << define your global variables here
double amp;

int main()
{
 ...
inn6fuwd

inn6fuwd2#

下面是一个脚本来重现您的项目设置(在空目录中运行):

#!/bin/sh -eu
cat > global_variables.h <<EOF
#ifndef GLOBAL_VARIABLES_H
#define GLOBAL_VARIABLES_H
double freq;
double amp;
#endif
EOF

cat > change_freq.h <<EOF
#ifndef CHANGE_FREQ_H
#define CHANGE_FREQ_H

#include "global_variables.h"

void increment_freq(double *frequency);

#endif
EOF
cat > change_freq.c <<EOF
#include "change_freq.h"

void increment_freq(double *frequency)
{
    (*frequency)++;
    if (*frequency == 1)
    {
        amp++;
    }
}
EOF

cat > main.c <<EOF
#include "global_variables.h"
#include "change_freq.h"
#include <stdio.h> ///ADD!

int main()
{
    freq = 0;
    increment_freq(&freq);
    printf("Hello World!\n");
    printf("freq %lf\n", freq);
    printf("amp %lf\n", amp);
    return 0;
}
EOF

有了这样的代码,它就可以编译并运行了(cc *.c && ./a.out)当且仅当编译器和链接器支持并隐式允许所谓的公共变量,允许未初始化的全局变量(double freq; double amp;)被临时定义在多个翻译单元中,然后用链接器合并它们。对于gcc/clang,你可以用-fcommon显式地请求这个非标准特性。(所以gcc -fcommon *.c && ./a.out应该可以工作)。
一个可移植的解决方案是

extern double freq, amp;

在header中,并且

/*no-extern*/ double freq, amp;

在一个C文件里
(You see,double freq;double amp;在全局范围内没有extern和初始化器都是 * 声明 * 和 * 临时定义 *。临时定义意味着你可以用初始化器重新定义它们一次,之后它们就完成了(并且非试探性的重新定义尝试变成错误),和/或试探性地重新定义它们。如果没有给出初始化器,默认情况下,它们是零初始化的,并在编译单元结束时完成。(相当常见)-fcommon扩展名(也需要链接器的支持)允许您将临时全局变量的概念扩展到多个翻译单元,方法是将临时全局变量的完成时间从编译单元的末尾推迟到链接时间。如果我没记错的话,这是B的一个遗留功能。它依赖于临时全局变量被归类为一种特殊类型的链接器符号,称为公共符号,它与标准C的临时定义相同,除了跨所有被链接的文件,而不仅仅是单个翻译单元。)

相关问题