C--1--C编程规则避免采坑指南-枚举enum-typedef-预编译指令: #if、#elif-声明外部变量: extern

1、/*宏参数及其本身都应加上括号,不加会破坏运算优先级*/

#include "stdio.h"
#include "stdlib.h"
#include "string.h"
/*宏参数及其本身都应加上括号,不加会破坏运算优先级*/
#define MULTI_MACRO(a, b)  ( (a) * (b) )
#define MULTI_MACRO_E(c, d) ( c * d )

typedef unsigned int uint32_t;

int main(void)
{
	//char a[1000];
	uint32_t s_b;
	uint32_t s_c;

	s_b = MULTI_MACRO (2+3, 2);
	s_c = MULTI_MACRO_E (2+3, 2);
	//printf("%s", a);
	printf("0-%d-0\n", s_b);
	printf("1-%d-1\n", s_c);

	system("pause");
	return 0;
}

2、枚举enum(enumeration) 

       含义:定义某一个数据类型,这种类型只有某几种可能,在定义的同时将这 
       些可能一 一例举出来,此种类型就叫枚举。 

 如下:定义变量Flag为BOOL这种类型,取值为FALSE,

#include "stdio.h"
#include "stdlib.h"
#include "string.h"

typedef unsigned int uint32_t;

enum BOOL{
    TRUE,  // 错误,没有进行显示赋值
    FALSE, // 错误,没有进行显示赋值,且末尾应该没逗号
};
#include "stdio.h"
#include "stdlib.h"
#include "string.h"

typedef unsigned int uint32_t;

enum BOOL{
    TRUE = 1,  // 正确,进行了显示赋值
    FALSE = 0  // 正确,进行了显示赋值,且末尾没逗号
};

  调用:

int main(void)
{
	
    enum BOOL flag = FALSE;

    if()
    {

    }
	system("pause");
	return 0;
}

  如下:定义SWITCH类型只有两种取值可能,ON或者OFF。

enum SWITCH{
    ENUM_ON = 0x0001U,
    ENUM_OFF = 0x1110U,
};

调用:

int main(void)
{
	
    enum SWITCH flag = ENUM_ON;

    if()
    {

    }
	system("pause");
	return 0;
}

3、C typedef

C 语言提供了 typedef 关键字,我们可以使用它来为类型取一个新的名字,来定义自己的类型

为什么通常用typedef 定义一个自己要替换的类型?

原因:增加代码的可读性,让人更容易读懂代码。

#include "stdio.h"
#include "stdlib.h"
#include "string.h"

typedef unsigned int uint32_t;

typedef enum {
    TRUE = 1,  // 正确,进行了显示赋值
    FALSE = 0  // 正确,进行了显示赋值,且末尾没逗号
}BOOL;

 调用(就省掉了写enum)

BOOL flag = FALSE;

 定义与调用:

#include <stdio.h>
#include <string.h>
 
typedef struct BOOKS
{
   char  title[50];
   char  author[50];
   char  subject[100];
   int   book_id;
} Book;
 
int main( )
{
   Book book;
 
   strcpy( book.title, "C 教程");
   strcpy( book.author, "Runoob"); 
   strcpy( book.subject, "编程语言");
   book.book_id = 12345;
 
   printf( "书标题 : %s\n", book.title);
   printf( "书作者 : %s\n", book.author);
   printf( "书类目 : %s\n", book.subject);
   printf( "书 ID : %d\n", book.book_id);
 
   return 0;
}

#define 是 C 指令,用于为各种数据类型定义别名,与 typedef 类似,但是它们有以下不同:

  • typedef 仅限于为类型定义符号名称,而#define 除了可以为类型定义别名外,也能为数值定义别名,比如可以定义 1 为 ON。
  • typedef 由编译器执行解释的,#define 语句是由预编译器进行处理的。
#include <stdio.h>
 
#define TRUE  1
#define FALSE 0
 
int main( )
{
   printf( "TRUE 的值: %d\n", TRUE);
   printf( "FALSE 的值: %d\n", FALSE);
 
   return 0;
}

4、预编译指令:#ifdef、#ifndef、#else、#endif

条件编译中相对常用的预编译指令。模式如下:

#ifdef ABC
// ... codes while definded ABC
#elif (CODE_VERSION > 2)
// ... codes while CODE_VERSION > 2
#else
// ... remained cases
#endif // #ifdef ABC

#ifdef用于判断某个宏是否定义,和#ifndef功能正好相反,二者仅支持判断单个宏是否已经定义,上面例子中二者可以互换。如果不需要多条件预编译的话,上面例子中的#elif和#else均可以不写。

预编译指令:#if、#elif、#else、#endif

#if 可支持同时判断多个宏的存在,与常量表达式配合使用。常用格式如下:

#if 常量表达式1
// ... some codes
#elif 常量表达式2
// ... other codes
#elif 常量表达式3
// ...
...
#else
// ... statement
#endif

在判断某个宏是否被定义时,应当避免使用#if,因为该宏的值可能就是被定义为0。而应当使用#ifdef或#ifndef。
注意: #if、#elif之后的宏只能是对象宏。如果宏未定义,或者该宏是函数宏,则编译器可能会有对应宏未定义的警告。

总结如下:

1)#if是要判断它后面表达式真假的,是真才执行#if后的代码;

2)#if和#elif搭配使用,这就可以用多种条件编译选择;

3)#if也是必须要以#endif配合使用。

示例说明:

#include "stdio.h"
#include "stdlib.h"
#include "string.h"

typedef unsigned int uint32_t;
#define IFTEST1        0
#define IFTEST2        1

int main(void)
{
	#if IFTEST1         //为假,不执行
		printf("if : %d\n", IFTEST1);
	#elif IFTEST2       //为真,执行
		printf("if : %d!\n", IFTEST2);
    #else    //必须要加,不加执行不通过
		printf("if : not true!\n");
	#endif

	system("pause");
	return 0;
}

5、声明外部变量:extern

对于变量来说:

typedef signed char int8_t;

extern int8_t a; // 仅声明一个全局变量 a
int8_t a; // 定义一个全局变量 a
extern int8_t a =0 ; // 定义一个全局变量 a 并给初值。
int8_t a =0;    // 定义一个全局变量 a, 并给初值,

第四个等于第三个,都是定义一个可以被外部使用的全局变量,并给初值。

但是定义只能出现在一处。也就是说,不管是int a;还是extern int a=0;还是int a=0;都只能出现一次,而那个extern int a可以出现很多次。

当你要引用一个全局变量的时候,你就必须要声明,extern int a; 这时候extern不能省略,因为省略了,就变成int a;这是一个定义,不是声明。注:extern int a; 中类型 int 可省略,即 extern a; 但其他类型则不能省略。

总结:

变量而言,如果你想在本源文件(例如文件名A)中使用另一个源文件(例如文件名B)的变量,方法有2种:

(1)在A文件中必须用extern声明在B文件中定义的变量(当然是全局变量);

(2)在A文件中添加B文件对应的头文件(常用前提是这个头文件包含B文件中的变量声明,也即在这个头文件中必须用extern声明该变量,否则,该变量又被定义一次。

如下图:1、.h中外部声明全局变量     2、.c中(包含对应.h)中定义全局变量

函数而言,如果你想在本源文件(例如文件名A)中使用另一个源文件(例如文件名B)的函数,方法有2种:

(1)在A文件中用extern声明在B文件中定义的函数(其实,也可省略extern,只需在A文件中出现B文件定义函数原型即可);

(2)在A文件中添加B文件对应的头文件(常用),前提是这个头文件包含B文件中的函数原型,在头文件中函数可以不用加extern。

如下图:1、.h中外部声明函数     2、.c中(包含对应.h)中定义函数    3、.c中调用函数


6、extern "C"

extern "C"包含双重含义,从字面上可以知道,首先,被它修饰的目标是"extern"的;其次,被它修饰的目标代码是"C"的。

  • 被extern "C"限定的函数或变量是extern类型的

extern是C/C++语言中表明函数和全局变量的作用范围的关键字,该关键字告诉编译器,其申明的函数和变量可以在本模块或其他模块中使用。

#ifndef  _INCMODULE_H_    //为条件编译指令,防止该头文件被重复包含(或重定义)
#define _INCMODULE_H_    //对当前头文件进行定义

#ifdef  __cplusplus       //告诉编译器,若是cpp文件,extern "C"{ } 中这部分代码按C语言的格式进行编译,而不是C++的。
extern "C"{               
#endif

/********字符数组定义*********/

static const char_t  module_buf[100U]="2022-03-23 abcd";       //定义静态常量无符号类型字符数组

static const char_t  module_buf[400]={’a’,’b’,’c’,’d’,’\0’};        //定义静态常量字符数组

#ifdef  __linux__
#define _INTSIZEOF(n)   ( (sizeof(n) + sizeof(int32_t) - 1) )
#endif

#define _crt_va_end(ap)      ( ap = (va_list)0 )
/*…*/


#ifdef  __cplusplus      // 因为cpp文件默认定义了__cplusplus 该宏。
}

#endif       // 与 #ifdef __cplusplus 相对应


#endif        /*与#ifndef 相对应 ,end of _INCMODULE_H_*/


extern “C”的作用详解 - 小金乌会发光-Z&M - 博客园

#ifndef:避免头文件的重复包含和编译_秦燕飞飞的博客-CSDN博客_ifndef防止重复包含

  • 1
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

明宇朗心

你的鼓励将是我创作的最大动力♥

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值