Uso avanzado de la definición de macros C / C ++

c / c ++ definición de macro uso avanzado
1. Estándar ANSI cinco nombres de macro predefinidos

    __LINE__ indica el número de línea de la línea de código
    __FILE__ indica el nombre de archivo del archivo
    fuente __DATE__ indica la fecha en la que se compiló el archivo fuente, formato (mes / día / año)
    __TIME__ indica la hora en que se compiló el archivo fuente en el código de destino, formato (hora: minuto: segundos)
    __STDC__ indica si el compilador es estándar o no, cuando es estándar, significa la constante 1, y no estándar significa otros números

Caso de prueba

#include <stdio.h>
#include <stdlib.h>
 
 
#define INFO(msg) info_debug(__FILE__, __LINE__, __DATE__, __TIME__, msg)
 
void info_debug(const char* filename, int line, const char* date, const char* time, const char* msg)
{
	printf_s("info_debug %s:%d (%s-%s):%s", filename, line, date, time, msg);
}
 
int main()
{
	INFO("Hello world!\n");
	system("pause");
	return 0;
}

Definir funciones o tal:

#define Function(name) void Func##name(void)

//使用
Function(mytest)
{
    ....
}

//编译器宏替换后
void Funcmytest(void)
{
    ...
}

2. Uso de definiciones macro de parámetros indefinidos

__VA_ARGS__ significa todos los parámetros restantes

Uso específico

#define LOG (fmt, ...) log (__ FILE__, __LINE__, fmt, __VA_ARGS__)

"..." significa los parámetros omitidos, __VA_ARGS__ corresponde exactamente a la función de "..."

Caso de prueba
 

#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
 
 
#define INFO(msg) info_debug(__FILE__, __LINE__,  msg)
#define LOG(fmt, ...) log(__FILE__, __LINE__, fmt, __VA_ARGS__)
 
void info_debug(const char* filename, int line, const char* msg)
{
	printf_s("info_debug %s:%d :%s", filename, line, msg);
}
 
void log(const char* filename, int line, const char* fmt, ...)
{
	int size;
	char * msg = NULL;
	va_list args;
	va_start(args, fmt);
	size = vsnprintf(NULL, 0, fmt, args) + 1;
	msg = (char *)malloc(size);
	vsnprintf(msg, size, fmt, args);
	info_debug(filename, line, msg);
	free(msg);
	va_end(args);
}
 
int main()
{
	INFO("Hello world!\n");
	LOG("%s %d\n", "debug", 14);
	system("pause");
	return 0;
}

3. El significado de # y ## en la definición macro

La función de # es clasificar los parámetros de macro detrás de él. En pocas palabras, después de reemplazar la variable de macro a la que se refiere, agregue una comilla doble alrededor

## se llama conector, se usa para conectar dos Tokens en un Token, ## es para reemplazar los parámetros pasados ​​como una cadena

Caso de prueba

#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
 
 
#define INFO(msg) info_debug(__FILE__, __LINE__,  msg)
#define LOG(fmt, ...) log(__FILE__, __LINE__, fmt, __VA_ARGS__)
 
#define VERSION 1.0.0
#define __STR__(x) (#x)  
#define TO_STR(x) __STR__(x)
 
#define LINK(x, y) x##y
 
 
void info_debug(const char* filename, int line, const char* msg)
{
	printf_s("info_debug %s:%d :%s", filename, line, msg);
}
 
void log(const char* filename, int line, const char* fmt, ...)
{
	int size;
	char * msg = NULL;
	va_list args;
	va_start(args, fmt);
	size = vsnprintf(NULL, 0, fmt, args) + 1;
	msg = (char *)malloc(size);
	vsnprintf(msg, size, fmt, args);
	info_debug(filename, line, msg);
	free(msg);
	va_end(args);
}
 
int main()
{
	INFO("Hello world!\n");
	LOG("%s %d\n", "debug", 14);
	printf_s("#把一个宏定义变成字符串:version = %s\n", TO_STR(VERSION));
	int n = LINK(12, 34);
	printf_s("##把两个参数拼接一起:%d\n", n);
	system("pause");
	return 0;
}

4. Definición de macro de varias líneas y llamada de función en la definición de macro

Ejemplo:

#define  DSPI0_RX  0
#define  DSPI1_RX  1
#define  DSPI2_RX  2
#define  DSPI3_RX  3
#define  DSPI4_RX  4

void  Spi_LLD_IsrRxDma_DSPI();

#define SPI_LLD_ISRRXDMA_DSPI_N_SRV(MCU_DMA_CHANNEL_n_SOURCE) \
if(MCU_DMA_CHANNEL_n_SOURCE == DSPI0_RX)\
{\
    Spi_LLD_IsrRxDma_DSPI();\
}\
else if(MCU_DMA_CHANNEL_n_SOURCE == DSPI1_RX)\
{\
    Spi_LLD_IsrRxDma_DSPI(); \
}\
else if(MCU_DMA_CHANNEL_n_SOURCE == DSPI2_RX)\
{\
    Spi_LLD_IsrRxDma_DSPI();\
}\
else if(MCU_DMA_CHANNEL_n_SOURCE == DSPI3_RX)\
{\
    Spi_LLD_IsrRxDma_DSPI();\
}\
else if(MCU_DMA_CHANNEL_n_SOURCE == DSPI4_RX)\
{\
    Spi_LLD_IsrRxDma_DSPI();\
}

Se llaman diferentes funciones según el valor de MCU_DMA_CHANNEL_n_SOURCE.

5. Definición de puntero nulo

#define NULL_PTR ((void *)0)

6. La definición de macro de variable o valor de retorno especifica el tipo y las habilidades de uso del módulo correspondiente.

Por ejemplo, variables constantes

typedef usigned char uint8;

typedef uint8 Adc_ChannelType; 

#define CONST(consttype, memclass) const consttype

STATIC CONST(Adc_ChannelType, ADC_CONST) AdcGroup_10_Assignment_PB_2_1[4] =
{//AdcGroup_10
    0U,
    1U,
    2U,
    3U,
};

// Adc_ChannelType indica que el elemento de la matriz es el tipo de canal ADC, que es una variable constante del módulo ADC.

Otro ejemplo: declaración de variable ordinaria

 #define VAR(vartype, memclass) vartype

  VAR(Adc_ChannelType, ADC_VAR) chId;

7. La definición macro da cuenta de la afirmación

por ejemplo:

#define  ASSERT(condition, message) {\

  if(!(condition)){\

  logError("Assertion failed:",#condition,message);\

  exit(EXIT_FAILURE);\

}\

}

8. En el desarrollo integrado, use #define y typedef en combinación para cambiar las constantes de dirección en variables de estructura, y use el operador "." Para acceder a los miembros de la variable de estructura.

Ejemplos de uso

typedef volatile union
{
 struct
 {
  unsigned int ECCENLDRAM     : 1;
  unsigned int ECCENDTAG      : 1;
  unsigned int ECCENSPRAM     : 1;
  unsigned int ECCENPTAG      : 1;
  unsigned int ECCENPMU       : 1;
  unsigned int ECCENPRAM      : 1;
  unsigned int ECCENCMEM      : 1;
  unsigned int ECCENCAN       : 1;
  unsigned int ECCENERAY      : 1;
  unsigned int                : 23;
 } B;
 int I;
 unsigned int U;

} SCU_ECCCON_type;


SCU_ECCCON_type SCU_ECCCON_Test;

#define SCU_ECCCON    (*( SCU_ECCCON_type *) 0xffff10000)

#define SCU_ECCCON_Test_ECCENERAY    (SCU_ECCCON.B.ECCENERAY)

//那么直接对SCU_ECCCON_Test_ECCENERAY宏进行操作就是对结构体变量SCU_ECCCON的B成员的ECCENERAY位进行操作。

//注意该案例中的结构体为变量定义的方法。

 

Supongo que te gusta

Origin blog.csdn.net/sunlin972913894/article/details/106308349
Recomendado
Clasificación