C notas de estudio - estructura (1)

estructura

C proporciona dos tipos de datos agregados: estructuras y matrices.
Cada elemento almacenado en una matriz es del mismo tipo, mientras que una estructura puede almacenar diferentes tipos.Cada elemento de una estructura se denomina miembro, y cada tipo de miembro puede ser diferente.

A diferencia de los nombres de matriz, las variables de estructura no se reemplazan con punteros cuando se usan en expresiones, y las variables de estructura no pueden usar subíndices para seleccionar miembros.

Declarar y crear variables

struct tag 			//类型tag
	{
    
     member-list} //成员列表
	variable_list; //变量列表

La declaración no crea un objeto, es decir, no se asigna espacio para los datos. Simplemente describe el diseño estructural del objeto.

//声明一个struct tag,但是未创建变量,所以不占用空间
struct book {
    
               
    char title[MAXTITL];
    char author[MAXAUTL];
    float value;
};    

//创建变量
struct book lib;
struct book libs[10];

Usar declaraciones typedef es una buena técnica.

//此声明方式与上面类似,但是使用了typedef关键字,把类型struct BOOK_TAG重命名为Book
//此处的BOOT_TAG可以省略,也就是直接使用Book作为别名
typedef struct BOOK_TAG{
    
               
    char title[MAXTITL];
    char author[MAXAUTL];
    float value;
} Book;    //注意这里的Book不是创建变量,而是别名

//创建结构变量时可以省略struct关键字了
Book x;
Book y[20];

Manera simplificada de crear variables

//结构声明并创建变量
struct book {
    
           
    char title[MAXTITL];
    char author[MAXAUTL];
    float value;
} lib;

También podemos crear variables directamente sin declarar la etiqueta.

//创建了一个lib的变量里面包含三个成员
struct {
    
           
    char title[MAXTITL];
    char author[MAXAUTL];
    float value;
} lib;

//声明一个数组,他包含10个结构。
struct {
    
           
    char title[MAXTITL];
    char author[MAXAUTL];
    float value;
} libs[10];

//声明一个指针,指向该结构,注意这里只创建了个指针,并没有指向谁
struct {
    
           
    char title[MAXTITL];
    char author[MAXAUTL];
    float value;
} *l;

miembro de la estructura

Los miembros de la estructura pueden ser escalares, matrices, punteros y otras estructuras.

//创建了一个lib的变量里面包含三个成员
struct {
    
         
	int a;
	int b[23];
	long *lp;
	struct Simple s;
} lib;

estructura autorreferencial

La siguiente autorreferencia es ilegal, porque el miembro s es otra estructura completa, que contendrá su propio miembro dentro, y el segundo es una estructura completa. Al calcular el tamaño de esta estructura, es similar a una repetición recursiva sin fin no puede calcular el tamaño, por lo que es ilegal.

struct Simple {
    
         
	int a;
	struct Simple s;
	flaot b;
};

La siguiente declaración es legal, porque la declaración es un puntero y la longitud se puede calcular directamente.

struct Simple {
    
         
	int a;
	struct Simple *p;
	flaot b;
};

trampa de autorreferencia

Cuando declaramos estructuras usando typdefs, esperamos declarar

typedef struct {
    
         
	int a;
	Simple *p;
	flaot b;
} Simple;

Pero falla, porque el nombre del tipo no se define hasta el final de la declaración, y no se define cuando se declara la estructura.
Una de las soluciones es que no omitimos la etiqueta

typedef struct Simple_TAG{
    
         
	int a;
	struct Simple_TAG *p;
	flaot b;
} Simple;

referencias cruzadas de estructuras

struct B; //不完整声明
struct A {
    
           
    float value;
    struct B *pb;
    
};

struct B {
    
           
    float value;
    struct A *pb;
};

inicialización

struct {
    
           
    char title[MAXTITL];
    char author[MAXAUTL];
    float value;
} lib;
//创建变量并初始化
struct book lib = {
    
    
        "Garlic-Melon Bank",
        "Lucky's Savings and Loan",
        8543.94
    };
//这种方式可以调换每个成员的顺序
struct book lib2 = {
    
    
		.value = 8543.94,
        .author = "Garlic-Melon Bank",
        .title = "Lucky's Savings and Loan"
    };

acceso a los miembros de la estructura

struct COMPLEX {
    
    
    char *name;
    int age;
	};
	
struct COMPLEX comp; //声明变量
comp.age = 4;

struct COMPLEX *c = ∁ //声明指针
c->age = 5;

asignación

Los arreglos no permiten la asignación de un arreglo a otro

int a[3] = {
    
     1,4,5};
int b[3];
b = a; //这是不允许的

Pero las estructuras pueden

struct namect {
    
    
    char fname[NLEN];
    char lname[NLEN];
    int letters;
};

struct namect a = {
    
    "asndg", "ang", 4};
struct namect b = a; //这是允许的,是把a的每个成员的值都给b,并且其中的数组的值也可以完全拷贝过去。

copia profunda y copia superficial

Sin embargo, si una estructura contiene variables de puntero, y la asignación de memoria dinámica se realiza durante el uso de la estructura, y las variables del mismo tipo de estructura se asignan entre sí al mismo tiempo, se producirán problemas de copia superficial y copia profunda. .

copia superficial

typedef struct Student
{
    
    
    char *name;
    int age;
}Student;
 
int main(int argc, char *argv[])
{
    
    
    Student std1;
    Student std2;
 
    //给结构体1赋值并打印
    std1.name = (char *)malloc(10);
    std1.age = 20;
    strcpy(std1.name, "lele");
 
    printf("std1--->name: %s, age: %d\n", std1.name, std1.age);
 
    //把std1直接赋值给std2,并打印std2的值
    std2 = std1;
    printf("std2--->name: %s, age: %d\n", std2.name, std2.age);
 
    //释放std1成员name所指向的内存空间
    printf("std1--->name addr: %p \n", std1.name);
    free(std1.name);        //可以成功释放空间
 
    //释放std2成员name所指向的内存空间
    printf("std2--->name addr: %p \n", std2.name);
    free(std2.name);        //由于指向的空间已经释放,所以不能重复释放
 
    return 0;
}
// std1--->name: lele, age: 20
// std2--->name: lele, age: 20
// std1--->name addr: 0x7f82b6f05b10 
// std2--->name addr: 0x7f82b6f05b10 
// a.out(46264,0x1108e2600) malloc: *** error for object 0x7f82b6f05b10: pointer being freed was not allocated
// a.out(46264,0x1108e2600) malloc: *** set a breakpoint in malloc_error_break to debug
// Abort trap: 6

El problema aquí es que cuando std1 asigna un valor a std2, porque hay un puntero en la estructura, la asignación solo copia la dirección a la que apunta el puntero en la estructura, así que cuando liberamos la estructura std2, porque el char* en std1 ya está publicado, pero lanzamos esta dirección nuevamente, por lo que los lanzamientos repetidos informaron errores.

copia profunda

Al notar los problemas anteriores, tenemos una buena idea de una solución, es decir, prestar atención al puntero de la variable miembro en la estructura al asignar un valor, reasignamos una parte de la memoria y copiamos el contenido, por lo que esto es una copia profunda.

typedef struct Student
{
    
    
    char *name;
    int age;
}Student;
 
int main(int argc, char *argv[])
{
    
    
    Student std1;
    Student std2;
 
    std1.name = (char *)malloc(10);
    std1.age = 20;
 
    strcpy(std1.name, "lele");
 
    printf("std1--->name: %s, age: %d\n", std1.name, std1.age);
 
    //把std1直接赋值给std2,并打印std2的值
    std2 = std1;
    //为name成员重新分配一段空间,并把内容拷贝过来
    std2.name = (char *)malloc(10);        
    strcpy(std2.name, std1.name);
    printf("std2--->name: %s, age: %d\n", std2.name, std2.age);
 
    //释放std1成员name所指向的内存空间
    free(std1.name);        //可以成功释放空间
 
    //释放std2成员name所指向的内存空间
    free(std2.name);        //由于指向的不是同一段空间,可以成功释放
 
    return 0;
}

matriz de estructuras

struct book {
    
                         /* set up book template     */
    char title[MAXTITL];
    char author[MAXAUTL];
    float value;
};
int main(void)
{
    
    
    struct book library[MAXBKS]; /* array of book structures */
    int count = 0;
    int index;
	library[count].title[0];//
}

anidamiento de estructura

struct names {
    
                         // first structure
    char first[LEN];
    char last[LEN];
};

struct guy {
    
                           // second structure
    struct names handle;           // nested structure
    char favfood[LEN];
    char job[LEN];
    float income;
};

int main(void)
{
    
    
    struct guy fellow = {
    
       // initialize a variable
        {
    
     "Ewen", "Villard" }, 
        "grilled salmon",
        "personality coach",
        68112.00
    };
    printf("Dear %s, \n\n", fellow.handle.first);
}

Supongo que te gusta

Origin blog.csdn.net/chongbin007/article/details/126067602
Recomendado
Clasificación