[Tipo personalizado] Te lleva a la estructura, enumeración, unión

Bienvenido al blog de código de aprendizaje de Xiao Wang

Después de la función de carácter, lo siguiente que debemos aprender es la estructura, enumeración y unión en el tipo personalizado.

Tabla de contenido

prefacio

1. Estructura

1.1 Declaración de estructura

1.2 Declaraciones especiales y autorreferencias estructurales

1.4 Autoreferencia de estructura

1.5 Definición e inicialización de variables de estructura

1.6 Alineación de memoria de estructura

1.7 Modificar el número de alineación por defecto

1.8 Paso de parámetros de estructura

dos, enumeración

1. Definición de enumeración

2. Ventajas de la enumeración

3. Uso de la enumeración

 3. Unión (comunidad)

1. Definición de unión

2. Las características de la articulación

3. Cálculo del tamaño de la junta

4. Preguntas de práctica

Resumir


prefacio

Sabemos que hay tipos de datos incorporados y tipos personalizados en lenguaje C. Para obtener más información, consulte [C Language Advanced] Análisis detallado del almacenamiento de datos en la memoria_Xiaowang Xuecode Blog-CSDN Blog

A continuación, introduzcamos en detalle qué son las estructuras, las enumeraciones y las uniones en los tipos personalizados y cómo usarlas.

1. Estructura

Una estructura es una colección de valores llamados variables miembro , y cada miembro de la estructura puede ser una variable de un tipo diferente

1.1 Declaración de estructura

 Demostración de código práctico:

struct Stu {//学生结构体
	char name[20];//姓名
	int age;//年龄
	char id[20];//学号
};//分号是自带的,不能丢失,
int main()
{
	struct Stu stu = { "name",12,"123456" };
	return 0;
}

1.2 Declaraciones especiales y autorreferencias estructurales

Al declarar una estructura, puede usar una declaración incompleta, lo cual es posible en este momento, pero debe establecer la variable global antes del punto y coma, de lo contrario no podrá encontrar esta estructura (estructura anónima)

Manifestación:

struct {
	int age;
	char name[20];
}x;
//是可以这样没有标签的,但是前提是创建x这样的全局变量,否则之后就找不到了
//因为是匿名结构体
struct {
	int age;
	char name[20];
}a[10],*p;
int main()
{
	
	scanf("%s", x.name);
	printf("%s", x.name);
	p = &x;
//非法的,因为p和x不是指向同一个结构体类型的,虽然成员变量一样,但是实际上类型是不同的
	return 0;
}

A continuación, pensemos si la primera y la segunda estructura del código anterior son iguales , ¿puede  p=&x  ?

Gráfico:

Como se explicó anteriormente, el compilador tratará las declaraciones de las dos estructuras anteriores como dos tipos completamente diferentes, por lo que es ilegal

1.4 Autoreferencia de estructura

La autorreferencia de la estructura se usa principalmente en el lado de la estructura de datos, como la lista de secuencias, la lista enlazada, etc. A continuación, presentémoslo, la declaración se llama autorreferencia de la estructura.

La autorreferencia de la estructura, como su nombre lo indica, utiliza las variables miembro del tipo de estructura dentro de la estructura.

Gráfico:

demostración de código:

//正确的自引用方式   有*号
struct Node
{
int data;
struct Node* next;
};
//错误的方式   没有*号
struct Node
{
int data;
struct Node next;
};

1.5 Definición e inicialización de variables de estructura

Arriba presentamos cómo declarar, luego echemos un vistazo a cómo usar la estructura, inicializarla y definirla.

demostración de código:

struct Point {
	int x;
	int y;
}p1;			//声明类型的同时进行定义变量p1  这个是全局变量

struct Point p2;	//这也是定义结构体变量,在结构体外面,函数外面,这也是全局变量

//初始化,定义变量的同时进行赋初值
struct Point p3 = { 1,2 };

struct Stu {
	char name[20];//姓名
	int age;//年龄
};

struct Stu s = { "why",20 };//初始化,这也是全局变量

struct Node {
	int date;
	struct Point p;
	struct Node* next;
}n1={10,{1,2},NULL};	//结构体嵌套初始化

struct Node n2 = { 10,{1,2},NULL };//结构体嵌套初始化

Cómo asignar e inicializar el resto:

struct Point
{
	int x;
	int y;
}p1 = {10, 20};

struct Point p2 = {0,0};

struct S
{
	int num;
	char ch;
	struct Point p;
	float d;
};

int main()
{
	struct Point p3 = {1,2};
	struct S s = { 100, 'w', {2,5}, 3.14f};
//这些属于基础的部分,赋值需要使用大括号,内部如果有其他类型的结构体,也要进行使用大括号
	struct S s2 = {.d=1.2f, .p.x=3,.p.y=5, .ch = 'q', .num=200};
	//创建一个变量之后,可以使用 .d=1.2f 这样的形式进行赋值,可以不用考虑结构体成员变量的顺序

	printf("%d %c %d %d %f\n", s.num, s.ch, s.p.x, s.p.y, s.d);
	printf("%d %c %d %d %f\n", s2.num, s2.ch, s2.p.x, s2.p.y, s2.d);

	return 0;
}

1.6 Alineación de memoria de estructura

arriba. Básicamente hemos entendido el uso básico de las estructuras.

Todos sabemos que los tipos de datos ocuparán espacio en la memoria, echemos un vistazo más profundo al cálculo del tamaño de la estructura.

Este es un punto de conocimiento muy importante: alineación de memoria de estructura

¿Qué es la alineación de la memoria? ¿Cómo se alinea? Hay las siguientes reglas

1. El primer miembro está en la dirección cuyo desplazamiento de la variable de estructura es 0.
2. Otras variables miembro deben estar alineadas con una dirección que sea un múltiplo entero de un cierto número (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 el número entero de todas las alineaciones máximas (incluida la alineación de la estructura anidada) veces.

demostración de código:


struct s1 {
	char c1;
	int i;
	char c2;
};
struct s2 {
	char c1;
	char c2;
	int i;
};
int main()
{
	printf("%d\n", sizeof(struct s1));
	printf("%d\n", sizeof(struct s2));
	return 0;
}

Explicación del análisis gráfico:

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

explicar:

1. Motivo de la plataforma (motivo del trasplante):
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 lanzará 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, mientras que los accesos a la memoria alineada requieren solo un acceso.
En resumen: ¡la alineación de la memoria de la estructura es la práctica de intercambiar espacio por tiempo! ! !

Por lo tanto, en el diseño de la estructura en el futuro, debemos hacer todo lo posible para cumplir con la alineación y ahorrar espacio, por lo que debemos

¡Deje que los miembros que ocupan un espacio pequeño se reúnan tanto como sea posible! ! !

1.7 Modificar el número de alineación por defecto

Podemos usar la directiva de preprocesamiento #pragma para cambiar la alineación predeterminada (la alineación predeterminada varía en diferentes compiladores)

#pragma pack(num) modifica el desplazamiento predeterminado a num

#pragma pack () significa cancelar la compensación predeterminada establecida antes y volver a la compensación predeterminada del compilador

demostración de código:

#pragma pack(4)//设置默认对齐数为4

struct s3 {
	char c1;
	int i;
	char c2;
	double c;
};
#pragma pack()//再次使用这个预处理宏,会取消设置的默认对齐数

#pragma pack(1)//设置最大对齐数为1
struct s4 {
	char c1;
	int i;
	char c2;
	double c;
};

int main()
{
	printf("%d ", sizeof(struct s3));
	printf("%d", sizeof(struct s4));

	return 0;
}

Entonces, después de aprender a usar #pragma pack(), puede cambiar el número de alineación predeterminado usted mismo cuando la alineación de la estructura no sea adecuada.

1.8 Paso de parámetros de estructura

Tenemos dos formas de pasar parámetros, la estructura del primer paso, la dirección del segundo paso, ¿cuál es mejor?

demostración de código:

//传参:1.传递结构体,2.传递地址
struct s3 {
	int data;
};
struct s3 s = { 1000 };

void print1(struct s3 s)//传递结构体
{
	printf("%d  ", s.data);
}
void print2(struct s3* s) {//传递地址
	printf("%d", s->data);
}
int main() {
	print1(s);//传递结构体
	print2(&s);//传递地址
}

En los dos métodos, debido a que se pasa la dirección, el espacio no se volverá a aplicar cuando se cree el parámetro formal, y la memoria de la estructura es generalmente relativamente grande, por lo que para ahorrar costos, preferimos pasar la dirección

1. 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.
2. 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.

dos, enumeración

1. Definición de enumeración

La enumeración es enumerar todo tipo de posibilidades una por una.

Enumere todos los valores posibles uno por uno, como siete días a la semana, para que pueda enumerar lunes, martes...

demostración de código:

enum Day//星期
{
Mon,
Tues,   //枚举成员之间使用逗号隔开
Wed,
Thur,
Fri,
Sat,
Sun   //且枚举的成员的取值是从0开始的,逐渐+1
};
enum Sex//性别
{
MALE,
FEMALE,
SECRET
};
enum Color//颜色
{
RED,
GREEN,
BLUE
};
int main()
{
	printf("%d\n", Mon);
	printf("%d\n", Tues);
	printf("%d\n", Wed);
	printf("%d\n", Thur);
	printf("%d\n", Fri);
	printf("%d\n", Sat);
	printf("%d\n", Sun);
	return 0;
}

Presentación gráfica: 

 El enum Day , enum Sex y enum Color definidos anteriormente son todos tipos de enumeración.
 El contenido en {} es el valor posible del tipo de enumeración, también llamado constante de enumeración.
 Estos valores posibles son todos valiosos, comenzando desde 0 por defecto, aumentando de 1 en 1, por supuesto, el valor inicial también se puede asignar al definir

enum Color//颜色
{
RED=1,
GREEN=2,
BLUE=4
};

2. Ventajas de la enumeración

¿Por qué usar la enumeración, hay algo así como la enumeración y la estructura de la enumeración?

Algunos amigos pueden ver que la enumeración no es una colección de constantes definidas por #define, entonces, ¿qué significa crear una enumeración?

¿Cuales son los beneficios?

Ventajas de las enumeraciones:

1. Aumentar la legibilidad y mantenibilidad del código
2. En comparación con el identificador definido por #define, la enumeración tiene verificación de tipo, que es más rigurosa.
3. Evitar la contaminación de nombres (encapsulación)
4. Fácil de depurar
5. Fácil de usar, se pueden definir múltiples constantes a la vez

3. Uso de la enumeración

Ahora hemos entendido la definición de enumeración, ¿qué es la enumeración y cuáles son las ventajas de la enumeración? Finalmente, sepamos cómo usar la enumeración y cómo usarla correctamente.

Presentación gráfica:

 3. Unión (comunidad)

1. Definición de unión

Las uniones son un tipo personalizado especial

Las variables definidas por este tipo también son similares a las estructuras y tienen una serie de miembros, la característica es que estos miembros comparten el mismo espacio

Por ejemplo:

De hecho, la unión es usar un espacio juntos. Cuando se cambia una variable miembro, también se puede cambiar otra variable miembro. Esto es más adecuado, se usa una y la otra no es aplicable.

2. Las características de la articulación

Los miembros de la unión comparten el mismo espacio de memoria , por lo que el tamaño de dicha variable conjunta es al menos el tamaño del miembro más grande ( porque la unión debe tener al menos la capacidad de guardar el miembro más grande ).

Así que echemos un vistazo, ¿cuál es la dirección inicial de los miembros del sindicato? ¿Es lo mismo?

demostración de código:

3. Cálculo del tamaño de la junta

Aprendimos anteriormente que hay muchas reglas para calcular el tamaño de memoria de una estructura, si siente que el cálculo es un poco problemático, entonces la unión es muy simple. solo dos puntos

1. El tamaño de la unión es al menos el tamaño del miembro más grande.     
2. Cuando el tamaño máximo del miembro no es un múltiplo entero del número de alineación máximo, debe alinearse con un múltiplo entero del número de alineación máximo

Primer caso: 

(Es decir, se puede usar el que sea más grande. Cuando no hay matriz o estructura, solo hay tipos básicos incorporados )

Este tamaño es el tamaño en bytes del tipo más grande

Segundo caso:

demostración de código:

union un1 {
	char c[5];//5个char类型为5字节
	int i;//;两种类型int char 所以最后结果为4 的倍数
	//5>4  所以最后为8
};
union un2 {
	short c[7];//相当于7个short类型连着  这样是14个字节
	int i;//un2 中 类型一共两种  int short  所以int为最大类型,所以最后得到的数据应该是4的倍数
	//因为是联合 所以14是这两个联合起来其中最大的一个, 再取4的倍数 ,得到16
};

int main()
{
	printf("%d\n", sizeof(union un1));//8
	printf("%d\n", sizeof(union un2));//16

	return 0;
}

4. Preguntas de práctica

Cómo verificar que el compilador actual es endian

Cuando aprendimos punteros antes, aprendimos el primer método. Consulte el análisis en profundidad del extremo grande y pequeño [lenguaje C avanzado] del almacenamiento de datos en la memoria_Xiaowang Xuecode Blog-CSDN Blog

A continuación, veamos cómo probar con unión.

el código se muestra a continuación:

 Por lo tanto, es little endian en el entorno VS.


Resumir

En este capítulo, aprendimos la definición de estructura, cómo declarar, autorreferencia, definición e inicialización de variables de estructura, alineación de memoria de estructura y cómo modificar la alineación predeterminada. Luego, para la comprensión de la enumeración y el uso, y finalmente las características de definición de la articulación y cómo calcular el tamaño del problema, este artículo termina con una pregunta de entrevista.

Espero que se sienta inspirado cuando lea este artículo. Aunque la enumeración y la unión rara vez se usan en esta etapa, debemos comprender y darnos cuenta de que el contenido de la estructura es muy importante. Auto-referencia El uso razonable se usará con frecuencia en los datos. estructuras! !

Finalmente, sus comentarios, sus gustos y favoritos son la fuerza impulsora para que Xiao Wang avance. Bienvenido a dar consejos. Si hay alguna deficiencia, indíquela, ¡gracias! ! !

Supongo que te gusta

Origin blog.csdn.net/qq_63319459/article/details/128674423
Recomendado
Clasificación