[C Avanzado] Tipo personalizado (1) Estructura

contenido

1. Conocimientos básicos de estructuras

2, la declaración de la estructura

3. Declaración especial

4. Autorreferencia de estructuras

5. Definición e inicialización de variables de estructura.

6. Estructura de la alineación de la memoria

     Ejercicio 1

     Ejercicio 2

     Ejercicio 3

     Ejercicio 4 - Problema de anidamiento de estructuras

7. Modificar el número de alineación predeterminado

8. Parámetros de estructura


1. Conocimientos básicos de estructuras

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, la declaración de la estructura

  • Sintaxis básica:
//struct:结构体的关键字
struct tag  //tag:结构体标签
{
    //大括号内容:结构体相关属性
	member - list; //member - list:成员列表
}variable - list; //变量列表
  • Por ejemplo para describir a un estudiante:
#include<stdio.h>
//结构体类型
struct Stu
{
	char name[20];//名字
	int age;//年龄
	char sex[5];//性别
	char id[20];//学号
}s2, s3, s4; //分号不能丢
//变量列表可有可无,不过上述的s2,s3,s4都是全局变量
int main()
{
	struct Stu s1; //结构体变量
	return 0;
}

3. Declaración especial

  • Al declarar una estructura, puede declararla de forma incompleta.
  • por ejemplo:
//匿名结构体类型
struct  //去掉标签
{
	int a;
	char b;
	float c;
}x;
struct
{
	int a;
	char b;
	float c;
}a[20], * p;

Las dos estructuras anteriores se declaran sin la etiqueta de estructura (tag). es un tipo de estructura anónima

Al definir una variable de tipo variable de estructura anónima, debe definirse después de la estructura { }, de lo contrario no funcionará. como anteriormente

  • Entonces aquí viene la pregunta?
//在上面代码的基础上,下面的代码合法吗?
p = &x;
  • advertir:

El compilador piensa que los dos lados del signo igual tienen diferentes tipos de estructura, por lo que esta forma de escribir es incorrecta.

4. Autorreferencia de estructuras

  • ¿Está bien tener un miembro del tipo de estructura en una estructura?
//代码1
struct Node
{
	int data;
	struct Node next;
};
//可行否? err
  • Si es así, ¿cuál es sizeof (struct Node)?

Esta estructura contiene un número entero de 4 bytes, y luego contiene una variable de estructura... y así sucesivamente, la muñeca anidada infinita, el ciclo infinito no sabe cuál es el tamaño.

  • Método correcto de autorreferencia: para almacenar la dirección del siguiente nodo, solo proporcione el puntero anterior.
//代码2
struct Node
{
	int data;
	struct Node* next;
};
  • Aviso:
//代码3
typedef struct
{
	int data;
	Node* next;
}Node;
//这样写代码,可行否? err
  • solución:
typedef struct Node
{
	int data;
	struct Node* next;
}Node;

5. Definición e inicialización de variables de estructura.

struct Point
{
	int x;
	int y;
}p1; //声明类型的同时定义变量p1
struct Point p2; //定义结构体变量p2
//初始化:定义变量的同时赋初值。
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. Estructura de la alineación de la memoria

  • Regla de alineación:
  1.  El primer miembro está en la dirección 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 (número de alineación). Alineación = el menor de la alineación predeterminada del compilador y el 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 propio número de alineación máximo y el tamaño total de la estructura es un múltiplo entero de todos los números de alineación máximos (incluido el número de alineación de las estructuras anidadas).

Antes de hacer la pregunta, primero debe saber una cosa: offsetof - offset (calcule el desplazamiento de un miembro de la estructura en comparación con la posición inicial de la estructura)

     Ejercicio 1

#include <stdio.h>
#include <stddef.h>
struct S1
{
	char c1;
	int i;
	char c2;
};
// 结构体 S1 的大小是多大?  ---》12
int main()
{
	printf("%d\n", sizeof(struct S1));    //12
	//计算偏移量
	printf("%d\n", offsetof(struct S1, c1));  //0
	printf("%d\n", offsetof(struct S1, i));   //4
	printf("%d\n", offsetof(struct S1, c2));  //8
	return 0;
}

     Ejercicio 2

struct S2
{
	char c1;
	char c2;
	int i;
};
// 结构体 S2 的大小是多大?  ---》8

     Ejercicio 3

struct S3
{
	double d;
	char c;
	int i;
};
// 结构体 S3 的大小是多大?  ---》16

     Ejercicio 4 - Problema de anidamiento de estructuras

 struct S4
 {
	 char c1;
	 struct S3 s3;
	 double d;
 };
 // 结构体 S4 的大小是多大?  ---》32

¿Por qué existe la alineación de la memoria?

  • 1. Motivos de plataforma (motivos de migración):

No todas las plataformas de hardware pueden acceder a los datos en cualquier dirección; algunas plataformas de hardware solo pueden obtener ciertos tipos de datos en ciertas direcciones; de lo contrario, se generará una excepción de hardware.

  • 2. 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; los accesos a la memoria alineada requieren solo un acceso.

  • Comprensión del dibujo:
  • No alineado:

La CPU lee 4 bytes a la vez en un entorno de 32 bits. Los últimos 3 bytes de la primera lectura y el primer byte de la segunda lectura son los datos de mi i.

  •  Alinear:

 Si está alineado, los datos de i se pueden obtener leyéndolo una vez. La alineación es más eficiente.

  • En general:

La alineación de la memoria de las estructuras es la práctica de intercambiar espacio por tiempo.

  • A la hora de diseñar una estructura, no solo debemos satisfacer la alineación, sino también ahorrar espacio ¿Cómo hacerlo?

Mantenga a los miembros con una huella pequeña lo más cerca posible.

  • P.ej:
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. El tamaño de S1 es de 12 bytes y el tamaño de S2 es de 8 bytes.El método de creación de S2 no solo satisface la alineación, sino que también ahorra espacio, lo cual es mejor.

7. Modificar el número de alineación predeterminado

  • El número de alineación predeterminado de VS es 8, pero podemos modificarlo.
#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));  //12
	printf("%d\n", sizeof(struct S2));  //6
	return 0;
}
  • En conclusión:

Cuando la alineación de la estructura no es la adecuada, podemos cambiar la alineación por defecto nosotros mismos.

8. Parámetros de estructura

  • Mira el código:
#include<stdio.h>
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);   //1000
}
//结构体地址传参
void print2(struct S* ps)
{
	printf("%d\n", ps->num); //1000
}
int main()
{
	print1(s); //传结构体
	print2(&s); //传地址
	return 0;
}
  • ¿Cuál de las funciones print1 e print2 anteriores es mejor?
  • La respuesta es: se prefiere la función print2.
  • razón:
  1. Al pasar parámetros a una función, los parámetros deben colocarse en la pila, lo que dará como resultado una sobrecarga del sistema en términos de tiempo y espacio.
  2. Si se pasa un objeto de estructura, la estructura es demasiado grande y la sobrecarga del sistema del apilamiento de parámetros es relativamente grande, por lo que se degradará el rendimiento.
  • Conclusión: cuando se pasan parámetros a la estructura, se debe pasar la dirección de la estructura.

Supongo que te gusta

Origin blog.csdn.net/bit_zyx/article/details/122657181
Recomendado
Clasificación