在编写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.c
和functions.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
。
要这样做,您需要
- 在通用头文件中定义一个数组大小宏,这样所有源文件都知道数组的大小,例如
#define HEADERMATSZ 9
, - 在其中一个C源文件中像往常一样声明数组,例如
const int HEADERMAT[HEADERMATSZ] = {0,1,2,3,4,5,6,7,8};
, - 在其他需要访问的C源文件中声明
extern const int HEADERMAT[HEADERMATSZ];
。
现在,您可以根据需要在任何文件中简单地使用HEADERMAT[]
,这些文件要么是最初声明的,要么是extern
。
一个简短的例子,首先是main.c
和source1.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
,如果它是可变的,可以在两个源中修改。