Reglas de expansión para el anidamiento de macros en lenguaje C incorporado

Editado de: https://mp.weixin.qq.com/s/xos8z1tpptLpAV6kQFXpuQ

En el lenguaje C incrustado, la macro se "reemplaza por texto" el nombre de la macro en el código con el contenido del cuerpo de la macro durante la precompilación.

1. La regla general de expansión es la misma que el parámetro de una función: primero expanda el parámetro y luego analice la función, es decir, expanda desde adentro hacia afuera. 2. Cuando hay un operador # en la macro, el parámetro no se expandirá. 3. Cuando haya un operador ## en la macro, primero expanda la función y luego analice los parámetros. 4. El operador ## se usa para conectar los parámetros. El proceso de preprocesamiento combina los parámetros que aparecen a ambos lados del operador ## en un solo símbolo. Tenga en cuenta que no es una cadena.

2. Reglas para el uso de "#" y "##"

"#" es convertir el parámetro macro en una cadena. No importa cuál sea la macro de parámetros, es decir, la "apariencia original" se muestra con una cadena de caracteres. Eso es envolver los parámetros de la macro con comillas dobles "" para formar una cadena. Por ejemplo:

#define T(x) #x
int temp = 10;
cout<<T(temp)<<endl;//输出 temp 而不是 10
// T(temp) -> "temp" (将宏参数用双引号包含起来形成一个字符串)

"##" se denomina concatenación, que conecta el parámetro macro con el token anterior (parámetro/espacio de cadena, etc.). Por ejemplo:

#define T(x) x##[2]
int a[5] = {1,2,3,4,5};
cout<<T(a)<<endl; //输出 3 即 a[2]
// 1. 宏参数在宏体中未加括号包裹起来
#define T(a) a*10
int a = 1;
cout<<T(a+1)<<endl; //输出 11 而非20

// 2. 整个宏体内容未加括号包裹起来
#define T(x) x+1
cout<<10*T(1)<<endl; //输出 11 而非20

1. En la definición de macro, agregue paréntesis a los parámetros, de modo que se garantice que la expresión entre paréntesis se opere primero al reemplazar. 2. Use paréntesis para encerrar el contenido de la definición de macro completa para asegurarse de que las expresiones en la definición de macro completa se operen primero. El anidamiento de macros es un punto difícil en el uso de macros y también es un punto propenso a errores. Permítanme ilustrar las reglas de expansión del anidamiento de macros con un diagrama de flujo:

imagen

Diagrama de flujo de reglas de expansión anidadas de macros

Nota: 2 y 3 en la figura anterior son condiciones o, siempre que se cumpla una condición, ingresará al proceso 5. El siguiente ejemplo ilustra:

// example 1
#include <cstdio>#define TO_STRING2(x) #x
#define TO_STRING1(x) #x
#define TO_STRING(x) TO_STRING1(x)

#define PARAM(x) #x
#define ADDPARAM(x) INT_##x
 
int main()
{
  const char *str = TO_STRING(PARAM(ADDPARAM(1)));
  printf("%s\n",str); //输出: "ADDPARAM(1)"
 
  str = TO_STRING2(PARAM(ADDPARAM(1)));
  printf("%s\n",str); //输出: PARAM(ADDPARAM(1))
 
  return 0;
}

El proceso de expansión de las dos macros anidadas en el ejemplo anterior es el siguiente:

TO_STRING(PARAM(ADDPARAM(1)))

-> 展开 PARAM:TO_STRING("ADDPARAM(1)")

-> 展开 TO_STRING:TO_STRING1("ADDPARAM(1)")

-> 展开 TO_STRING1:"\"ADDPARAM(1)\""

TO_STRING2(PARAM(ADDPARAM(1)))

-> 展开 TO_STRING2:"PARAM(ADDPARAM(1))"
// example 2
#include <cstdio>#define TO_STRING2(x) a_##x
#define TO_STRING1(x) #x
#define TO_STRING(x) TO_STRING1(x)

#define PARAM(x) #x
#define ADDPARAM(x) INT_##x
 
int main()
{
  const char *str = TO_STRING(TO_STRING2(PARAM(ADDPARAM(1))));
  printf("%s\n",str); //输出: a_PARAM(INT_1)
  return 0;
}

El proceso de expansión de la macro anidada en el ejemplo anterior es el siguiente:

TO_STRING(TO_STRING2(PARAM(ADDPARAM(1))))

-> 展开 TO_STRING2:TO_STRING(a_PARAM(ADDPARAM(1))) //注意此次展开后,PARAM宏名被破坏了,变成了a_PARAM不再是有效的宏名了

-> 展开 ADDPARAM:TO_STRING(a_PARAM(INT_1))

-> 展开 TO_STRING:TO_STRING1(a_PARAM(INT_1))

-> 展开 TO_STRING1:"a_PARAM(INT_1)"

Nota: Las reglas de expansión de las macros anidadas están relacionadas con el compilador, y diferentes compiladores pueden expandir la misma macro anidada de manera diferente. Las pruebas anteriores están todas en VS2010 (x86).

原文:https://zhuanlan.zhihu.com/p/344240420文章来源于网络,版权归原作者所有,如有侵权,请联系删除。

个人微信开放,扫码添加,进高质量嵌入式交流群

关注我【一起学嵌入式】,一起学习,一起成长。
觉得文章不错,点击“分享”、“赞”、“在看” 呗!

Supongo que te gusta

Origin blog.csdn.net/qq_41854911/article/details/131525355
Recomendado
Clasificación