Lenguaje C avanzado: vuelva a reconocer la estructura

inserte la descripción de la imagen aquí
1 Conocimiento básico de la estructura

Una estructura es una colección de valores llamados variables miembro. Cada miembro de la estructura puede ser una variable de un tipo diferente.

2 Declaración de estructura

struct tag
{
    
    
 member-list;
}variable-list;

Si describimos a un estudiante a continuación, pensaremos en el nombre del estudiante, grado, género, etc., entonces podemos usar la estructura para crear tal variable para contener estos contenidos.

struct stu
{
    
    
	char name[20];
	int age;
	char sex[5];
	double score;
};

3 Avisos especiales

Al declarar una estructura, puede estar incompleta.

Por ejemplo

//匿名结构体类型
struct
{
    
    
 int a;
 char b;
 float c;
}x;
struct
{
    
    
 int a;
 char b;
 float c;
}a[20], *p;

Estas estructuras solo se pueden usar una vez, porque no hay una etiqueta de estructura para formar un tipo, por lo que la estructura anónima solo se puede usar una vez.
¡Aviso! ! !

La estructura anónima solo se puede usar una vez, por lo que no podemos realizar algunas operaciones, como

//在上面代码的基础上,下面的代码合法吗?
p = &x;

El compilador los tratará como dos tipos completamente diferentes, por lo que p no puede almacenar la dirección de x

4 Autorreferencia de estructuras

¿Está bien tener un miembro en una estructura que sea del tipo de la estructura misma?

Cabe señalar aquí que no contiene variables de estructura, pero contiene punteros de estructura de este tipo (es un puntero, abre los ojos grandes de Kazilan para ver), ¡no puedes tener este tipo de estructura en una estructura! ! !
Veamos un ejemplo

//代码2
struct Node
{
    
    
 int data;
 struct Node* next;
}

el siguiente es un puntero de estructura y el tipo de puntero es struct Node.
código de error

struct Node
{
    
    
 int data;
 struct Node;
}

Esta es la estructura de la estructura incorrecta, somos punteros, no variables.

Mirando un código a continuación

//代码3
typedef struct
{
    
    
 int data;
 Node* next;
}Node;
//这样写代码,可行否?

Esto equivale a redefinir una estructura anónima, lo que equivale a un poeta recluido en la antigüedad que fue sacado por ti para luchar. ¿Crees que esto es razonable? Aunque parezca razonable, debe ser una minoría, ¿no? !
También es equivalente a si el huevo o la gallina van primero. Nuestra estructura aún no se ha creado, pero hay punteros en ella, y no hay ningún tipo de estructura, por lo que le cambiaremos el nombre, por lo que debe ser incorrecto. código correcto

typedef struct Node
{
    
    
 int data;
 struct Node* next;
}Node;

5 Definición e inicialización de variables de estructura
Declarar tipos y crear variables

struct stu
{
    
    
	char name[20];
	int age;
	char sex[5];
	double score;
}s1,s2;

Crear variables s1 y s2 al declarar la estructura
Asignar valores al inicializar

struct stu
{
    
    
	char name[20];
	int age;
	char sex[5];
	double score;
}s1,s2;
int main()
{
    
    
	struct stu s3 = {
    
     "张三",18,"男",99.9 };
	return 0;
}

Las estructuras contienen métodos de estructuras.

//初始化:定义变量的同时赋初值。
struct Point p3 = {
    
     x, y };
struct Stu        //类型声明
{
    
    
	char name[15];//名字
	int age;      //年龄
};
struct Stu s = {
    
     "zhangsan", 20 };//初始化
struct Node
{
    
    
	int data;
	struct Point p;
	struct Node* next;
}n1 = {
    
     10, {
    
    4,5}, NULL }; //结构体嵌套初始化
struct Node n2 = {
    
     20, {
    
    5, 6}, NULL };//结构体嵌套初始化

6 Alineación de memoria estructural
Este es el contenido más importante de este capítulo. Explicaré el método en detalle y daré un ejemplo para ilustrar.
Primero mire las reglas
¿Cómo calcular?
Primero, debe dominar las reglas de alineación de la estructura:

  1. El primer miembro está en el desplazamiento 0 de la variable de estructura.
  2. Otras variables miembro deben alinearse con una dirección que sea un múltiplo entero de un número determinado (número de alineación).
    Alineación = alineación predeterminada del compilador y el valor más pequeño del tamaño del miembro.
    El valor predeterminado en VS es 8
  3. El tamaño total de la estructura es un múltiplo entero de la alineación máxima (cada variable miembro tiene una alineación).
  4. Si una estructura está anidada, la estructura anidada se alinea con un múltiplo entero de su propia alineación máxima y el
    tamaño total de la estructura es un múltiplo entero de todas las alineaciones máximas (incluida la alineación de la estructura anidada).

Por ejemplo

#include<stdio.h>
struct S1
	
{
    
    
	char c1;
	int i;
	char c2;
};
int main()
{
    
    
	printf("%zd\n", sizeof(struct S1));
}

inserte la descripción de la imagen aquí

Debido a que comenzamos desde cero, el char en la estructura solo ocupa un byte, y de acuerdo con nuestra segunda regla, la alineación mínima del entero es 4, por lo que nuestro entero debe comenzar con 4 múltiplos, luego bajamos cuatro bytes desde la posición de 4 a la posición de 7, y otro tipo de char está justo a la posición de 8, pero nuestro tamaño total debe ser un múltiplo entero del número máximo de alineación, aquí El número de alineación es el número máximo de alineación de la estructura, entonces es un múltiplo de 4, es decir, 12, justo en la posición de 11, por lo que el tamaño ocupado es 12.

Echemos un vistazo a los resultados
inserte la descripción de la imagen aquí
, luego tomemos otro ejemplo para una comprensión más profunda.

struct S3
{
    
    
	double d;
	char c;
	int i;
};
#include<stdio.h>
int main()
{
    
    
	printf("%d\n", sizeof(struct S3));
}

inserte la descripción de la imagen aquí
inserte la descripción de la imagen aquí

De hecho, es lo mismo que la explicación anterior. Comienza desde 0 al principio, y luego doble son ocho bytes de memoria, porque es el mismo valor que nuestro número de alineación predeterminado, luego el número de alineación es 8 y uno char ocupa una palabra Sección, la alineación mínima del siguiente int es 4, por lo que debemos comenzar en la posición 12, que es exactamente 16 bytes en total, que también es un múltiplo entero de nuestro doble de alineación máxima, por lo que el la respuesta es 16

Hablemos del tamaño de una estructura anidada, creo que todos también lo olvidarán.

struct S3
{
    
    
	double d;
	char c;
	int i;
};

struct S4
{
    
    
	char c1;
	struct S3 s3;
	double d;
};
#include<stdio.h>
int main()
{
    
    
	printf("%d\n", sizeof(struct S4));
}

inserte la descripción de la imagen aquí
inserte la descripción de la imagen aquí
Entonces, en la posición 31, por ejemplo, 0 es solo 32, que es un múltiplo de nuestro número máximo de alineación de 8, entonces la respuesta es ¿por qué hay alineación de memoria en 32? Podemos dividirlo en dos razones, una
inserte la descripción de la imagen aquí
es
una problema de la plataforma, y ​​el otro es un problema de rendimiento.

  1. Razones de la plataforma (razones para la portabilidad):
    no todas las plataformas de hardware pueden acceder a ningún dato en ninguna dirección; algunas plataformas de hardware solo pueden obtener ciertos tipos
    de datos en ciertas direcciones; de lo contrario, se lanzará una excepción de hardware.
  1. Razones de rendimiento:
    las estructuras de datos (especialmente las pilas) deben alinearse en los límites naturales tanto como sea posible.
    La razón es que para acceder a la memoria no alineada, el procesador necesita hacer dos accesos a la memoria, mientras que los accesos a la memoria alineada requieren solo
    uno .

La alineación de la memoria de la estructura es la práctica de intercambiar espacio por tiempo.
Entonces, ¿cómo debemos diseñar la estructura para asegurarnos de que ahorre espacio y memoria?
Podemos diseñar de esta manera, poniendo pequeños bytes delante, como tipo char Poner el primero, seguido por el corto, que puede ahorrar espacio.Por
ejemplo, las listas de miembros de las siguientes dos estructuras son las mismas, pero sus tamaños de bytes son diferentes.

//例如:
struct S1
{
    
    
 char c1;
 int i;
 char c2;
};
struct S2
{
    
    
 char c1;
 char c2;
 int i;
};

Los miembros de los tipos S1 y S2 son exactamente iguales, pero existen algunas diferencias en el tamaño del espacio ocupado por S1 y S2.

7 Modificar la alineación por defecto

#include <stdio.h>
#pragma pack(8)//设置默认对齐数为8
struct S1
{
    
    
	char c1;
	int i;
	char c2;
};
#pragma pack()//取消设置的默认对齐数,还原为默认
#pragma pack(1)//设置默认对齐数为1
struct S2
{
    
    
	char c1;
	int i;
	char c2;
};
#pragma pack()//取消设置的默认对齐数,还原为默认
int main()
{
    
    
	//输出的结果是什么?
	printf("%d\n", sizeof(struct S1));
	printf("%d\n", sizeof(struct S2));
	
		return 0;
}

Generalmente lo configuramos a la potencia de 2, en lugar de completamente irregular como 1 3, por ejemplo, en nuestra plataforma de máquina de 32 bits, leemos cuatro bytes a la vez, si es 5, no hay En cambio, los regulares deben leerse dos veces, por lo que no se mejora la eficiencia.

8 Estructura Pasando Parámetros
Cuando una estructura pasa parámetros, en realidad tiene el mismo efecto que nuestra función pasando parámetros.Al pasar parámetros, también abre espacio en la pila, y también sigue lo que solemos decir que un parámetro formal es una parte temporal de un parámetro real.


struct S
{
    
    
	int data[1000];
	int num;
};
struct S s = {
    
     {
    
    1,2,3,4}, 1000 };
//结构体传参
void print1(struct S s)
{
    
    
	printf("%d\n", s.num);
}
//结构体地址传参
void print2(struct S* ps)
{
    
    
	printf("%d\n", ps->num);
}
int main()
{
    
    
	print1(s);//传结构体 
	print2(&s); //传地址
	return 0;
}

Miremos el código anterior, todos piensen si print1 o print2 es mejor,
la respuesta es 2 es mejor

Explique que
debido a que pasamos parámetros en la estructura, si es print, seguirá abriendo espacio para el almacenamiento, lo que ocupará mucho espacio, y el espacio para nuestro print2 es como máximo 8 en una plataforma de 64 bits. , porque lo que le pasamos es una Dirección, la dirección es del tamaño de una variable puntero, es decir 4 bytes u 8 bytes, entonces es mejor pasar la dirección

Cuando una función pasa parámetros, los parámetros deben colocarse en la pila, lo que provocará una sobrecarga del sistema en tiempo y espacio.
Si se pasa un objeto de estructura, la estructura es demasiado grande y la sobrecarga del sistema de empujar los parámetros a la pila es relativamente grande, lo que conducirá a una
disminución en el rendimiento.

Eso es todo por lo de hoy, hasta la próxima, ¡gracias a todos! ! !

Supongo que te gusta

Origin blog.csdn.net/2301_76895050/article/details/132000763
Recomendado
Clasificación