防止全局变量、头文件重复包含与 extern 的使用
2012-08-17 21:25
399 查看
C语言中经常会出现文件重复包含而导致全局变量重复定义,下面以一个例子说明
-----Makefile
-----main.c
【说明】
1、以下这种方式可以防止头文件重复包含或定义:
3、在 errhandle.h 中声明 extern int errcode;而在 errhandle.c 中声明int
errcode;这样即可解决 errcode 因重复包含导致的 "multiple definition"。这种用法在标准C库的 errno.h 和 errno.c 中能见到。
--------------------------------------------------------------------------------------------------------------------------------------
下面介绍另一种方法,参考文章http://www.4ucode.com/Study/Topic/951741
只修改 errhandle.h 和 errhandle.c 2个文件
-----errhandle.h
-----errhandle.c
errhandle.h 中改变的内容:
定义过 ERRHANDLE_GLOBALS 的文件: ERRHANDLE_EXT int errcode; == int errcode;
未定义过 ERRHANDLE_GLOBALS 的文件: ERRHANDLE_EXT int errcode; == extern int errcode;
这样,就只有一份 int errcode; 的声明在 errhandle.c 中,其它文件均为 extern int errcode;
其实,预处理之后跟第一种方法是一样的
-----Makefile
CC = gcc OBJS = main.o errhandle.o strcopy.o CFLAGS = -Wall -std=c99 main: ${OBJS} # or $(OBJS), ${OBJS} is shell style ${CC} ${CFLAGS} -o $@ ${OBJS} main.o: main.c errhandle.h strcopy.h ${CC} ${CFLAGS} -c main.c errhandle.o: errhandle.c errhandle.h ${CC} ${CFLAGS} -c errhandle.c strcopy.o: strcopy.c strcopy.h errhandle.h ${CC} ${CFLAGS} -c strcopy.c clean: rm -f main *.o
-----main.c
#include <stdio.h> #include "errhandle.h" #include "strcopy.h" #define DESTSIZE 10 int main(int argc, char *argv[]) { char dest[DESTSIZE]; char *src = "1234567890"; if(strcopy(dest, DESTSIZE, src) != NULL) { printf("%s\n", dest); } else { printerr(); } if(strcopy(dest, DESTSIZE, NULL) != NULL) { printf("%s\n", dest); } else { printerr(); } return 0; }-----errhandle.h
/* * error handle */ #ifndef _ERRHANDLE_H #define _ERRHANDLE_H // to avoid duplicate(multiple) inclusion or declare(definition) of the header file #ifdef __cplusplus extern "C" { #endif extern int errcode; #define ERR_SHORT 1 /* The dest string is too short */ #define ERR_SRCNULL 2 /* The src string pointer is NULL */ #define ERR_DESTNULL 3 /* The dest string pointer is NULL */ extern void printerr(); #ifdef __cplusplus /* extern "C" */ } #endif #endif /* _ERRHANDLE_H */-----errhandle.c
#include <stdio.h> #include "errhandle.h" int errcode; void printerr() { if(ERR_SHORT == errcode) { printf("The dest string is too short\n"); } else if(ERR_SRCNULL == errcode) { printf("The src string pointer is NULL\n"); } else if(ERR_DESTNULL == errcode) { printf("The dest string pointer is NULL\n"); } }-----strcopy.h
#ifndef _STRCOPY_H #define _STRCOPY_H // to avoid duplicate(multiple) inclusion or declare(definition) of the header file #ifdef __cplusplus extern "C" { #endif extern char *strcopy(char *dest, unsigned int dest_len, const char *src); #ifdef __cplusplus /* extern "C" */ } #endif #endif /* _STRCOPY_H */-----strcopy.c
#include <string.h> #include "errhandle.h" #include "strcopy.h" char *strcopy(char *dest, unsigned int dest_len, const char *src) { char *dest_p = NULL; int i; if(dest == NULL) { errcode = ERR_DESTNULL; return NULL; } if(src == NULL) { errcode = ERR_SRCNULL; return NULL; } if(dest_len < strlen(src) + 1) { errcode = ERR_SHORT; return NULL; } for(i = 0, dest_p = dest; src[i] != '\0'; i++, dest_p++) { *dest_p = src[i]; } *dest_p = '\0'; return dest; }这个例子中 strcopy.c 和 errhandle.c 都要用到 errcode 这个全局变量,其它依赖关系见上面的代码
【说明】
1、以下这种方式可以防止头文件重复包含或定义:
#ifndef _ERRHANDLE_H #define _ERRHANDLE_H // to avoid duplicate(multiple) inclusion or declare(definition) of the header file ... #endif /* _ERRHANDLE_H */2、关于extern "C" 的说明可以见这里:关于extern "C",http://effective-c.googlecode.com/files/effective-c.pdf
#ifdef __cplusplus extern "C" { #endif ... #ifdef __cplusplus /* extern "C" */ } #endif
3、在 errhandle.h 中声明 extern int errcode;而在 errhandle.c 中声明int
errcode;这样即可解决 errcode 因重复包含导致的 "multiple definition"。这种用法在标准C库的 errno.h 和 errno.c 中能见到。
--------------------------------------------------------------------------------------------------------------------------------------
下面介绍另一种方法,参考文章http://www.4ucode.com/Study/Topic/951741
只修改 errhandle.h 和 errhandle.c 2个文件
-----errhandle.h
/* * error handle */ #ifndef _ERRHANDLE_H #define _ERRHANDLE_H // to avoid duplicate(multiple) inclusion or declare(definition) of the header file #ifdef __cplusplus extern "C" { #endif #ifdef ERRHANDLE_GLOBALS #define ERRHANDLE_EXT #else #define ERRHANDLE_EXT extern #endif ERRHANDLE_EXT int errcode; #define ERR_SHORT 1 /* The dest string is too short */ #define ERR_SRCNULL 2 /* The src string pointer is NULL */ #define ERR_DESTNULL 3 /* The dest string pointer is NULL */ extern void printerr(); #ifdef __cplusplus /* extern "C" */ } #endif #endif /* _ERRHANDLE_H */
-----errhandle.c
#define ERRHANDLE_GLOBALS /* 这条语句必须位于 #include "errhandle.h" 的前面 */ #include <stdio.h> #include "errhandle.h" void printerr() { if(ERR_SHORT == errcode) { printf("The dest string is too short\n"); } else if(ERR_SRCNULL == errcode) { printf("The src string pointer is NULL\n"); } else if(ERR_DESTNULL == errcode) { printf("The dest string pointer is NULL\n"); } }【说明】
errhandle.h 中改变的内容:
#ifdef ERRHANDLE_GLOBALS #define ERRHANDLE_EXT #else #define ERRHANDLE_EXT extern #endif ERRHANDLE_EXT int errcode;errhandle.c 中去掉了int errcode; 的声明,增加了:
#define ERRHANDLE_GLOBALS /* 这条语句必须位于 #include "errhandle.h" 的前面 */这种方法的原理很简单:
定义过 ERRHANDLE_GLOBALS 的文件: ERRHANDLE_EXT int errcode; == int errcode;
未定义过 ERRHANDLE_GLOBALS 的文件: ERRHANDLE_EXT int errcode; == extern int errcode;
这样,就只有一份 int errcode; 的声明在 errhandle.c 中,其它文件均为 extern int errcode;
其实,预处理之后跟第一种方法是一样的
相关文章推荐
- 防止头文件被重复包含、extern、变量定义与声明的区别
- 防止头文件重复包含引起的变量重复定义
- 防止 c 头文件以嵌套包含及变量重复定义
- VC、iOS中 防止变量重复定义、头文件重复包含、嵌套包含
- 防止变量重复定义、头文件重复包含、嵌套包含
- extern 用法,全局变量与头文件(重复定义)
- extern 用法,全局变量与头文件(重复定义)
- 多个文件使用同一全局变量(未初始化) 以及局部变量重复定义
- extern 用法,全局变量与头文件(重复定义)
- 防止变量重复定义、头文件重复包含、嵌套包含
- extern 用法,全局变量与头文件(重复定义)
- 防止 c 头文件以嵌套包含及变量重复定义
- extern 用法,全局变量与头文件(重复定义){转}
- 【转载】防止变量重复定义、头文件重复包含、嵌套包含
- C/C++多文件共享全局变量时,使用extern的规范
- extern 声明全局变量,多文件使用
- [C语言]防止头文件和全局变量重复定义
- extern用法,全局变量,全局函数与头文件(重复定义)
- 防止变量重复定义、头文件重复包含、嵌套包含
- 多个文件中使用同一个全局变量extern