C预处理器摘要

Posted microhex

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了C预处理器摘要相关的知识,希望对你有一定的参考价值。

最近在学习C,记录一下C预处理器。C预处理器不是编译器的组成部分,但是它是编译过程中一个单独的步骤。简言之,C预处理器只不过是一个文本替换工具而已,他们会指示编译器在实际编译过程中所需的预处理。我们将C预处理器(C Preprocessor)简写为CPP。

文章目录

#define

#define 

定义宏定义

#define PI 3.1415926

#include

#include 

包含一个源代码的文件,这个我们用得比较多,基本上开始学习C预言的时候就开始了。

#include <stdio.h>

#undef

#undef 

取消宏定义

#undef PI

举个例子:

int main()
    double circle_size = 20 * PI * 2 ;
    printf("周长为为%f", circle_size);

    #undef PI
   
    //取消PI的宏定义之后 下面的代码将不能再使用宏定义
    //double new_circle_size = 20 * PI 
    
    return  0 ;

#ifdef ~ #endif

#ifdef XXX
	xxxx
#endif

#ifdef 和 #endif 配套使用,如果宏已经定义,则返回真。

#define PI 3.1415926

#ifdef PI
#define NEW_DATA 2
#endif

#ifndef ~ #endif

#ifndef XXX
xxx
#endif

如果宏没有定义,则返回为真

#ifndef MESSAGE
#define MESSAGE "hello world"
#endif

printf("the message is %s", MESSAGE);

#if ~ #elif ~ #endif

#if xx
xx
#elif xxx
xx
#endif 

如果给定的条件为真,则编译一下的代码。

#if defined(OS_UNIX)
    getUnixSystemInfo();

#elif defined(OS_WINDOWS)
    getWindowsSystemInfo();
    
#endif

#error

#error "xxxx"

当遇到标准错误时,输出错误消息。

#define OS_UNIX 1

#ifdef OS_UNIX
    #error "OS_UNIX has been defined"
#endif

以上演示#error 异常,用于编译器触发的异常。主要用途是在庞大,复杂的系统中,预处理是否按照自己的思路去走,自己定义的宏是否也被其他文件定义,相当于编译期间的一种错误查找。

#pragma

用法比较多,这里举几个简单的例子:

#pragma message 用于自定义编译信息

#define android_VERSION_8

#if defined ANDROID_VERSION_8
#pragma MESSAGE_NEW "this version is android 8"
#define ANDROID_VERSION 8.0

#elif defined ANDROID_VERSION_9
#pragma MESSAGE_NEW "this version is android 9"
#define ANDROID_VERSION 9.0

#else
#error no version has complied

#endif

在编译期间将会有MESSAGE_NEW的输出,但是在运行时看不见,这就是预处理的强大之处。

#pragma once 用于头文件只被编译一次

#include <stdio.h>
#include "test.h"
#include "test.h"

引入两次test.h, test.h下文件内容为:

#pragma once

int pragma_value = 10;

但还是能正常输出,如果去掉

// #pragma once

程序会报多次定义错误。

#pragma pack 用于指定内存对齐(一般用于结构体)

一般在结构体中,内存对齐需要满足的条件是:

  1. 第一个成员起始于0偏移处;
  2. 每个成员按其类型大小和pack参数中较小的一个进行对齐(偏移地址必须能被对齐参数整除,结构体对齐参数取其内部最大数据成员作为其大小);
  3. 结构体总长度必须为所有对齐参数的整数倍。

举个例子:

#include <stdio.h>

#pragma pack(2)
struct p1       //对齐参数     //偏移参数    //大小
    char c1 ;    //1           0            1
    char c2 ;    //1           1            1
    short s1 ;   //2           2            2
    int i ;      //2           4            4
; //8

#pragma pack()


#pragma pack(4)
struct p2       //对齐参数     //偏移参数    //大小
    char c1;     //1           0            1
    short s;     //2           2            2
    char c2;     //2           4            1
    int i ;      //4           8            4
; //12
#pragma


#pragma pack(8)
struct p3       //对齐参数         //偏移参数    //大小
    char c1;     //1                 0            1
    int i ;      //4                 4            4
    long l;      //8                 8            8
;//16

struct p4          //对齐参数     //偏移参数    //大小
    char s1 ;       //0              0         1
    struct p3 p ;   //16             16        16
    double  d ;     //8              24        8
;//32

#pragma

int main()

    printf("sizeof p1 = %d\\n", sizeof(struct p1)); //8
    printf("sizeof p2 = %d\\n", sizeof(struct p2)); //12
    printf("sizeof p3 = %d\\n", sizeof(struct p3)); //16
    printf("sizeof p4 = %d\\n", sizeof(struct p4)); //32

    return 0;

参考:
1.https://blog.csdn.net/liuchunjie11/article/details/80502529

以上是关于C预处理器摘要的主要内容,如果未能解决你的问题,请参考以下文章

gcc常用的参数说明

gcc常用的参数说明

C 基础 - 预处理器与C库

C语言中带参数的宏

c基础回顾

知识蒸馏实战:使用CoatNet蒸馏ResNet