Bloc de notas en lenguaje C-01


El original número 100 del hermano Tao

I. Introducción

He estado transfiriendo el código de un proyecto integrado a otra plataforma estos días y descubrí que muchos lugares están usando el estándar C89.

En 1999, el comité de estandarización del lenguaje C lanzó el estándar C99 , que introdujo muchas características, incluidas matrices de longitud variable, miembros de matriz flexibles (utilizados en estructuras), mejoras en los números de punto flotante IEEE754, inicializadores para miembros designados, funciones asociativas internas, Se agregan a los tipos de datos definiciones de macros que admiten un número indefinido de parámetros y tipos de números complejos e int largos largos.

Así que recientemente encontré un libro en lenguaje C relativamente nuevo y lo di vuelta, y descubrí que muchas de las gramáticas más remotas rara vez se usan, incluido algún contenido en el estándar C99, por lo que quiero organizar esta parte del contenido, pero también dejar Yo mismo Reorganizar este lenguaje antiguo.

Segundo, una pequeña prueba

1. Miembros de matriz flexibles

Sin explicar el concepto, primero veamos un ejemplo de código:

// 一个结构体,成员变量 data 是指针
typedef struct _Data1_ {
    int num;
    char *data;
} Data1;

void demo6_not_good()
{
    // 打印结构体的内存大小
    int size = sizeof(Data1);
    printf("size = %d \n", size);

    // 分配一个结构体指针
    Data1 *ams = (Data1 *)malloc(size);
    ams->num = 1;

    // 为结构体中的 data 指针分配空间
    ams->data = (char *)malloc(1024);
    strcpy(ams->data, "hello");
    printf("ams->data = %s \n", ams->data);

    // 打印结构体指针、成员变量的地址
    printf("ams = 0x%x \n", ams);
    printf("ams->num  = 0x%x \n", &ams->num);
    printf("ams->data = 0x%x \n", ams->data);

    // 释放空间
    free(ams->data);
    free(ams);
}

En mi computadora, el resultado de la impresión es el siguiente:

Se puede ver que la estructura tiene un total de 8 bytes (el tipo int ocupa 4 bytes, el tipo de puntero ocupa 4 bytes).

La estructura de datalos miembros es una variable de puntero , ya que requiere una aplicación separada puede usar un espacio. Y después de que se usa la estructura, primero debe liberarse data, y luego el puntero de estructura ams, el orden no puede ser incorrecto .
¿Es un poco problemático usarlo de esta manera?

Por lo tanto, el estándar C99 define una gramática: miembro de matriz flexible (matriz flexible) , cargue directamente el código (si el siguiente código encuentra una advertencia al compilar, verifique el soporte del compilador para esta gramática):

// 一个结构体,成员变量是未指明大小的数组
typedef struct _Data2_ {
    int num;
    char data[];
} Data2;

void demo6_good()
{
    // 打印结构体的大小
    int size = sizeof(Data2);
    printf("size = %d \n", size);

    // 为结构体指针分配空间
    Data2 *ams = (Data2 *)malloc(size + 1024);

    strcpy(ams->data, "hello");
    printf("ams->data = %s \n", ams->data);

    // 打印结构体指针、成员变量的地址
    printf("ams = 0x%x \n", ams);
    printf("ams->num  = 0x%x \n", &ams->num);
    printf("ams->data = 0x%x \n", ams->data);

    // 释放空间
    free(ams);
}

El resultado de la impresión es el siguiente:

Hay varias diferencias con el primer ejemplo :

  1. El tamaño de la estructura pasa a ser 4;
  2. Al asignar espacio para el puntero de estructura, además del tamaño de la estructura en sí, también se aplica al espacio requerido por los datos;
  3. No es necesario asignar espacio por separado para los datos;
  4. Al liberar espacio, simplemente suelte el puntero de estructura directamente;

¿Es más fácil de usar? ! Este es el beneficio de las matrices flexibles.

Sintácticamente hablando, una matriz flexible se refiere a una matriz con un número desconocido de últimos elementos en la estructura, y también se puede entender como una longitud de 0, por lo que esta estructura se puede llamar de longitud variable.

Como se mencionó anteriormente, el nombre de la matriz representa una dirección, que es una constante de dirección constante. En la estructura, el nombre de la matriz es solo un símbolo, solo representa un desplazamiento y no ocupa un espacio específico.

Además, la matriz flexible puede ser de cualquier tipo . Todo el mundo tiene mucha experiencia en este ejemplo. Este uso se ve a menudo en muchos escenarios de procesamiento de comunicaciones.

2. Definición macro de parámetros indefinidos

El número de parámetros definidos por una macro puede ser indefinido , al igual que llamar a la función printf print. Al definir, puede usar tres puntos (...) para representar parámetros variables, o puede agregar la opción antes de los tres puntos. nombre del parámetro variable.

Si usa tres puntos (...) para recibir parámetros variables, debe usar VA_ARGS para representar parámetros variables cuando lo use , de la siguiente manera:

#define debug1(...)      printf(__VA_ARGS__)

debug1("this is debug1: %d \n", 1);

Si agrega un nombre de parámetro delante de los tres puntos (...), debe usar este nombre de parámetro cuando lo use, y no puede usar VA_ARGS para representar parámetros variables , de la siguiente manera:

#define debug2(args...)  printf(args)

debug2("this is debug2: %d \n", 2);

Sin embargo, si el número de parámetros variables es cero, el procesamiento puede resultar problemático.

Eche un vistazo a esta macro:

#define debug3(format, ...)      printf(format, __VA_ARGS__)

debug3("this is debug4: %d \n", 4);

No hay ningún problema con la compilación y ejecución. Pero si usa la macro así:

debug3("hello \n");

Error de tiempo de compilación se produce: error: expected expression before ‘)’ token. ¿Por qué?

Eche un vistazo al código después de la expansión de la macro ( __VA_ARGS__vacío):

printf("hello \n",);

¿Ves el problema, verdad? ¡Hay una coma adicional después de la cadena de formato ! Para resolver el problema, el preprocesador nos proporciona un método: use el símbolo ## para eliminar automáticamente esta coma adicional .

Por tanto, no hay problema si la definición de la macro se cambia a la siguiente.

#define debug3(format, ...)     printf(format, ##__VA_ARGS__)

Del mismo modo, si define el nombre de un parámetro de variable usted mismo, agregue ## delante de él, de la siguiente manera:

#define debug4(format, args...)  printf(format, ##args)

Tres, anímate

Este artículo es solo el comienzo. Continuaré recopilando información más adelante. El objetivo final es resumir la gramática y el uso del lenguaje C en un folleto. ¡Espero poder ceñirme a él!


Los buenos artículos deben enviarse ; cuanto más compartas, más afortunado eres.

Cuenta oficial de Star , ¡puedes encontrarme más rápido!


Si desea volver a imprimir este artículo en su sitio web, solo conserve el autor, la fuente del artículo y el código QR de arriba.

Si desea reimprimir este artículo en su cuenta oficial, envíe un mensaje privado o deje un mensaje, abriré Changbai para usted.



Lectura recomendada

[Lenguaje C]
Puntero del lenguaje C: desde los principios subyacentes hasta habilidades sofisticadas, con gráficos y código para ayudarlo a explicar
los principios de depuración subyacentes del gdb original de manera tan simple
y análisis paso a paso, cómo usar C para implementar objetos. Programación orientada a
mejorar el código para una herramienta poderosa: Definición de macro: desde la entrada hasta el abandono,
use setjmp y longjmp en lenguaje C para realizar captura de excepciones y corrutina

[Programación de aplicaciones] Se
dice que la arquitectura del software debe dividirse en capas y en módulos, y qué se debe hacer específicamente (1) Se
dice que la arquitectura del software debe dividirse en capas y en módulos, y qué se debe hacer específicamente ( 2)
Desarrollo de pasarela de IoT: basado en el bus de mensajes MQTT Proceso de diseño (en)
Desarrollo de pasarela de IoT: proceso de diseño basado en el bus de mensajes MQTT (abajo)
mi forma favorita de comunicación entre procesos-bus de mensajes

[Sistema operativo]
¿Por qué las naves espaciales y los misiles prefieren usar computadoras de un solo chip en lugar de sistemas integrados?

[Internet de las cosas] Los
aspectos relacionados con el cifrado y los certificados
profundizan en el lenguaje de secuencias de comandos de LUA, para que pueda comprender a fondo el principio de depuración.

[Tonterías] Basado
en mi experiencia laboral fallida: algunos consejos para técnicos que son nuevos en el lugar de trabajo

Supongo que te gusta

Origin blog.csdn.net/u012296253/article/details/115366870
Recomendado
Clasificación