一、明示常量#define
#define
:
-
#define
用于创建宏定义,可以用来定义符号常量、函数宏和其他代码片段的替代。 -
它不创建新的数据类型,而只是简单地进行文本替换。当你使用
#define
创建一个符号常量时,编译器会在编译时将该符号替换为相应的值。 -
例如:
#define PI 3.14159265359
这会在编译时将所有的
PI
替换为
3.14159265359
#define 与typedef 的区别
- 宏定义 vs. 类型定义:
#define
用于创建宏定义,而不创建新的数据类型。它简单地进行文本替换。例如,#define PI 3.14159265359
会将所有的PI
替换为3.14159265359
,但它仍然被视为一个常量符号而不是新的数据类型。typedef
用于创建类型别名,允许你为现有的数据类型创建一个新的名称。这创建了一个新的类型,可以用来增加代码的可读性和可维护性。
- 编译时替换 vs.类型别名:
#define
进行编译时替换。它只是简单地将一个标识符替换为定义的文本,没有类型检查或类型信息。这可以导致潜在的错误,因为没有关于替换文本的类型信息。typedef
创建一个新的类型别名,与原始类型相关。这有助于提高代码的可读性,并保留了类型检查。类型别名的使用可以帮助减少潜在的类型错误。
- 作用范围:
#define
定义的符号常量可以在整个程序中的任何地方使用,因为它们是简单的文本替换。它们通常不受作用域的限制。typedef
创建的类型别名通常受限于它们的作用域,与类型定义的位置有关。这使得typedef
更具局部性,有助于避免全局污染。
总的来说,#define
用于创建宏定义,主要用于创建符号常量和代码替代,而 typedef
用于创建类型别名,主要用于提高代码的可读性和可维护性,以及创建新的类型别名。它们在用途、作用方式和范围上有很大的不同。
eg:
#define INT_POINTER int *
typedef int* int_pointer;
int main()
{
INT_POINTER a,b;
int_pointer c,d;
}
在以上代码中a、b、c、d谁不是指针?
答案是:b;
为什么呢?
我们对**#define 处理的进行替换**;得到
int *a,b;
我们可以发现只有第一个是指针,因为*只有a才有,b没有,所有b是int类型:
int (*a),b;
我们再对typedef 进行分析:
(int *) a,b;
//等价于
int *a,int *b;
再#define中使用参数
#define MAX(x,y) ((x)>(y)?(x):(y))
//其中x,y宏参数
int main()
{
int a=3;
int b=5;
int ret=MAX(a,b);
}
//当在代码中使用了MAX(a,b),编译器会将其替换((a)>(b)?(a):(b))
需要注意以下几点:
- 带参数的宏的参数被括在圆括号中,这有助于避免潜在的运算优先级问题。
- 使用带参数的宏时,确保将参数括在圆括号中,以避免由于操作符优先级问题而导致意外的行为。
用宏参数擦创造字符串:#
#define PRINT(a,type) printf(" "#a" is type",a);
int main()
{
int b=10b;b
PRINT(b,%d);
}
//在宏中如果我们不使用 #a 而直接使用a,在打印是,只会打印出字符a出来,
//而无法打印我们传递的d
//使用 #a 就是将传递过去的参数给转换为字符串,以供我们打印
条件编译
条件编译是一种在C和C++中用于根据条件选择性包含或排除代码的技术。它使用预处理器指令,通常与 #ifdef
、#ifndef
、#elif
、#else
和 #endif
一起使用。条件编译的主要目的是根据不同的编译时条件来配置程序,以在不同的情况下执行不同的代码。
以下是一些常见的条件编译指令:
-
#ifdef
和#ifndef
:-
#ifdef
检查是否已定义了指定的宏。 -
#ifndef
检查是否未定义指定的宏。 -
例如:
#ifdef DEBUG // 只有在 DEBUG 宏已定义时才编译这部分代码 printf("Debug mode is enabled.\n"); #endif
-
-
#elif
和#else
:-
#elif
允许你在多个条件之间选择一个。 -
#else
用于指定一个条件不满足时要执行的代码块。 -
例如:
#ifdef DEBUG printf("Debug mode is enabled.\n"); #elif RELEASE printf("Release mode is enabled.\n"); #else printf("No build mode defined.\n"); #endif
-
-
#endif
:- 用于结束条件编译块。
条件编译的使用场景包括:
- 跨平台开发:根据不同的操作系统或编译器特性选择性地包含代码。
- 调试信息:根据是否启用调试宏,可以包含或排除调试信息。
- 特性开关:根据用户选项或配置文件中的特性开关选择性地启用或禁用功能。
- 针对不同的硬件架构:可以根据不同的硬件平台选择性地编译代码。
条件编译可以提高代码的灵活性,但过度使用可能会导致代码的可读性下降。因此,建议在需要时谨慎使用条件编译,以确保代码清晰、易维护和可移植。