如何在头文件中定义常量以在多个C文件中使用



在编写C代码时,我可能想在头文件中定义一个常量数组,以便它可以在多个.c文件中使用。

看下面的例子:

c

#include <stdio.h>
#include "main.h"
int main() {
int localmat[9];
for (int i = 0; i < 9; i++) {
localmat[i] = HEADERMAT[i];
}
matadd(localmat, HEADERMAT);
return 0;
}

main.h

#ifndef _MAIN_H_
#define _MAIN_H_
// Constant array
const int HEADERMAT[9] = {0,1,2,3,4,5,6,7,8};
// prototype function:
void matadd(int matA[9], const int matB[9]);
#endif

functions.c

#include "main.h"
void matadd(int matA[9], const int matB[9]){
for (int i = 0; i < 9; i++) {
matA[i] += matB[i];
}
}

main.h中声明的常量数组HEADERMAT在两者中都使用main.cfunctions.h。头文件确实使用了ifndef来防止重定义,但是,编译器仍然会抱怨它被定义了多次:

/usr/bin/ld: /tmp/ccVWhI0u.o:(.rodata+0x0): multiple definition of `HEADERMAT'; /tmp/ccRAIQ5u.o:(.rodata+0x0): first defined here
collect2: error: ld returned 1 exit status

让两个C文件都可以访问这个数组的更好方法是什么?

头文件用于声明。这是一种方法:

// main.h
#ifndef _MAIN_H_
#define _MAIN_H_
// Constant array
const int HEADERMAT[9]; // <---- declaration only

// prototype function:
void matadd(int matA[9], const int matB[9]);
#endif
然后,在一些源文件中(最好是main.c,因为我们在main.h中声明过)
// main.c
#include <stdio.h>
#include "main.h"
const int HEADERMAT[9] = {0,1,2,3,4,5,6,7,8}; // <---- definition here
int main() {
int localmat[9];
for (int i = 0; i < 9; i++) {
localmat[i] = HEADERMAT[i];
}
matadd(localmat, HEADERMAT);
return 0;
}

如果你在头文件中这样做:

// main.h
// main.h
#ifndef _MAIN_H_
#define _MAIN_H_
// Constant array
static const int HEADERMAT[9] = {0,1,2,3,4,5,6,7,8}; // <-- static definition
// prototype function:
void matadd(int matA[9], const int matB[9]);
#endif

那么数组将在包含main.h的每个源文件中复制,正如Jonathan Leffler的注释所指出的那样,这不是什么大问题(36字节)。但对于一个相当大的数组,浪费将是一个问题。

如果我理解您只是想使HEADERMAT[]数组在多个源文件中可用,您可以简单地在任何源文件中像往常一样声明它,然后在需要它的任何其他源文件中声明它为extern

要这样做,您需要

  1. 在通用头文件中定义一个数组大小宏,这样所有源文件都知道数组的大小,例如#define HEADERMATSZ 9
  2. 在其中一个C源文件中像往常一样声明数组,例如const int HEADERMAT[HEADERMATSZ] = {0,1,2,3,4,5,6,7,8};
  3. 在其他需要访问的C源文件中声明extern const int HEADERMAT[HEADERMATSZ];

现在,您可以根据需要在任何文件中简单地使用HEADERMAT[],这些文件要么是最初声明的,要么是extern

一个简短的例子,首先是main.csource1.c包含的通用头文件,其中包含一个函数,该函数将使用声明为extern的数组,例如

#ifndef COMMONHDR
#define COMMONHDR  1
#define HEADERMATSZ 9     /* defined size of extern array */
void showoutput (void);   /* declaration of function using extern array*/

#endif

对于main.c,我们将在那里声明数组,包括公共头文件,以提供声明,用于我们将从source1.c调用的函数,该函数使用extern声明的数组,例如

#include <stdio.h>
#include "commonhdr.h"
const int HEADERMAT[HEADERMATSZ] = {0,1,2,3,4,5,6,7,8};

int main (void) {

puts ("output from other file");
showoutput();
}

(showoutput()函数是从source1.c调用的函数,另外请注意,如果您的初始化器具有正确的值数量(包括确保数组大小正确),则可以省略HEADERMATSZ)

最后,在source1.c文件中,我们提供了函数定义,它使用数组extern
#include <stdio.h>
#include "commonhdr.h"
extern const int HEADERMAT[HEADERMATSZ];
/* definition of function using extern array */
void showoutput (void)
{
for (int i = 0; i < HEADERMATSZ; i++) {
printf (" %d  %dn", i, HEADERMAT[i]);
}
}

将两个源代码编译成最终的可执行文件,例如使用gcc,

gcc -Wall -Wextra -pedantic -Wshadow -std=c11 -Ofast source1.c -o main main.c

使用/输出示例

$ ./main
output from other file
0  0
1  1
2  2
3  3
4  4
5  5
6  6
7  7
8  8

无论在您的PC上还是在微控制器上编程,这种方法都很有效。通过使用extern,数组不必是const,如果它是可变的,可以在两个源中修改。

相关内容

  • 没有找到相关文章

最新更新