0
点赞
收藏
分享

微信扫一扫

【C++进阶学习】第一弹——继承(上)——探索代码复用的乐趣

青青子衿谈育儿 2024-06-18 阅读 3

文章目录

一、C 预处理器

C预处理器(C Preprocessor)是C语言编译器的一个组成部分,它负责在编译过程之前处理源代码。预处理器的主要任务是扫描源代码,对其中的预处理指令进行解释和替换,然后输出一个修改后的源代码文件,这个文件随后会被C编译器处理。

C预处理器指令都以#符号开始,并且必须在每行的开头(前面不能有任何空格或制表符)。下面是一些常见的C预处理器指令:

  1. #include:包含另一个文件的内容。有两种形式:
  • #include <filename>:从标准库路径中搜索filename文件。
  • #include "filename":首先在当前目录或指定的目录中搜索filename文件,如果找不到,再从标准库路径中搜索。
  1. #define:定义一个宏。例如,#define PI 3.14159 会将源代码中所有的PI替换为3.14159
  2. #undef:取消之前由#define定义的宏。
  3. #if#elif#else#endif:条件编译指令,允许你根据条件包含或排除代码段。
  4. #ifdef#ifndef:检查某个宏是否已经被定义。
  5. #line:改变编译器的行号和文件名,这在创建报告错误和警告的宏时很有用。
  6. #error#warning:生成编译时错误或警告。
  7. #pragma:这是预处理器的扩展指令,它允许向编译器发送特定的指令,这些指令可能因编译器而异。

预处理器指令在源代码被编译之前执行,并且通常不会生成目标代码。它们主要用于处理代码中的常量和宏定义,以及控制代码中的条件编译。预处理器指令在大型项目中特别有用,因为它们可以帮助组织和管理代码,减少冗余,并允许在不同的编译配置之间切换。

二、C 预处理器指令

C预处理器指令在C语言编程中非常有用,它们允许你在编译前对源代码进行各种处理。以下是一些C预处理器指令的详细代码案例:

1. #include

// 使用尖括号包含标准库头文件
#include <stdio.h>

// 使用双引号包含用户定义的头文件
#include "myheader.h"

int main() {
    printf("Hello, World!\n"); // 假设myheader.h中没有任何与此冲突的声明
    return 0;
}

2. #define#undef

#define PI 3.14159

int main() {
    double circle_area = PI * 5 * 5; // 使用PI宏替换为3.14159
    printf("Circle area is %.2f\n", circle_area);
    
    #undef PI // 取消PI的宏定义
    // 下面的代码会导致编译错误,因为PI已经被undef了
    // double another_area = PI * 3 * 3;
    
    return 0;
}

3. #if#elif#else#endif

#define DEBUG 1

int main() {
    #if DEBUG
        printf("Debugging is on\n");
    #elif defined(TEST)
        printf("Testing is on\n");
    #else
        printf("Neither debugging nor testing is on\n");
    #endif
    
    return 0;
}

在这个例子中,DEBUG被定义为1,所以程序会输出"Debugging is on"。如果你注释掉#define DEBUG 1并取消注释#define TEST 1,程序会输出"Testing is on"。

4. #ifdef#ifndef

// 假设没有定义MY_FEATURE

int main() {
    #ifdef MY_FEATURE
        printf("My feature is enabled\n");
    #else
        printf("My feature is disabled\n");
    #endif
    
    #ifndef MY_FEATURE
        printf("Again, my feature is disabled\n");
    #endif
    
    return 0;
}

在这个例子中,因为MY_FEATURE没有被定义,所以两个printf都会执行,分别输出"My feature is disabled"和"Again, my feature is disabled"。

5. #line

这个指令通常用于调试目的,允许你改变编译器的行号和文件名。在实际编程中较少直接使用。

6. #error#warning

#if !(defined(WIN32) || defined(__unix__) || defined(__APPLE__))
    #error Unsupported platform!
#endif

int main() {
    // ...
    return 0;
}

在这个例子中,如果代码不是在Windows、Unix或Apple平台上编译的,预处理器会生成一个错误消息"Unsupported platform!"。

7. #pragma

#pragma指令是特定于编译器的,用于提供编译器的特定指令。例如,在某些编译器中,你可以使用#pragma once来确保头文件只被包含一次。

// myheader.h
#pragma once
// ... 其余的头文件内容

注意:#pragma once并不是C语言标准的一部分,但它在许多现代编译器中都被支持。在编写跨平台代码时,你应该避免依赖非标准的预处理器指令。

三、C 预定义宏

C语言预处理器提供了一些预定义的宏,这些宏在编译时总是可用的,而无需显式地定义它们。这些预定义宏通常用于获取关于编译器和编译环境的信息。下面是一些常见的C预定义宏及其详细代码案例:

1. __LINE__

这个宏被预处理器替换为当前源代码行号(十进制整数)。

#include <stdio.h>

int main() {
    printf("This is line %d\n", __LINE__);
    printf("This is line %d\n", __LINE__ + 1); // 下一行
    return 0;
}

2. __FILE__

这个宏被预处理器替换为当前源代码文件的名称(带路径或不带路径,取决于编译器)。

#include <stdio.h>

int main() {
    printf("This file is %s\n", __FILE__);
    return 0;
}

3. __DATE__

这个宏被预处理器替换为编译时的日期,格式为 “Day Mon DD HH:MM:SS YYYY\n”。

#include <stdio.h>

int main() {
    printf("Compilation date: %s", __DATE__);
    return 0;
}

4. __TIME__

这个宏被预处理器替换为编译时的时间,格式为 “HH:MM:SS”。

#include <stdio.h>

int main() {
    printf("Compilation time: %s", __TIME__);
    return 0;
}

5. __STDC__

如果编译器遵循C语言标准,此宏被设置为1。否则,它未定义。

#include <stdio.h>

int main() {
    #if __STDC__
        printf("This is a C Standard compliant compiler\n");
    #else
        printf("This is not a C Standard compliant compiler\n");
    #endif
    return 0;
}

6. __STDC_VERSION__

如果编译器遵循C99或更新的标准,此宏将被设置为一个表示C标准版本的整数。例如,对于C99,它是199901L。如果不支持C99或更新的标准,此宏可能未定义。

#include <stdio.h>

int main() {
    #if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L
        printf("This compiler supports C99 or newer\n");
    #else
        printf("This compiler does not support C99 or newer\n");
    #endif
    return 0;
}

7. __cplusplus

当代码在C++编译器中编译时,此宏被设置为1。在C编译器中,它未定义。

注意:这个宏主要用于区分C和C++代码,而不是在C语言代码中使用。

8. 编译器特定的预定义宏

除了上述标准的预定义宏之外,不同的编译器还可能提供自己的预定义宏。例如,GCC提供了__GNUC____GNUC_MINOR____GNUC_PATCHLEVEL__等宏来表示GCC的版本信息。

四、相关链接

  1. Visual Studio Code下载地址
  2. Sublime Text下载地址
  3. 「C系列」C 简介
  4. 「C系列」C 基本语法
  5. 「C系列」C 数据类型
  6. 「C系列」C 变量及常见问题梳理
  7. 「C系列」C 常量
  8. 「C系列」C 存储类
  9. 「C系列」C 运算符
  10. 「C系列」C 判断/循环
  11. 「C系列」C 函数
  12. 「C系列」C 作用域规则
  13. 「C系列」C 数组
  14. 「C系列」C enum(枚举)
  15. 「C系列」C 指针及其应用案例
举报

相关推荐

0 条评论