C study notes - structure (1)

structure

C provides two aggregate data types: structures and arrays.
Each element stored in an array is of the same type, while a structure can store different types. Each element in a structure is called a member, and each member type can be different.

Unlike array names, structure variables are not replaced with pointers when used in expressions, and structure variables cannot use subscripts to select members.

Declare and create variables

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

The statement does not create an object, that is, no space is allocated for the data. It just describes the structural layout of the object.

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

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

Using typedef declarations is a good technique.

//此声明方式与上面类似,但是使用了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];

Simplified way to create variables

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

We can also create variables directly without declaring the tag

//创建了一个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;

structure member

Structure members can be scalars, arrays, pointers and other structures

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

self-referencing structure

The following self-reference is illegal, because the member s is another complete structure, which will contain its own member s, and the second is a complete structure. When calculating the size of this structure, it is similar to a Recursively repeating endlessly cannot calculate the size, so it is illegal.

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

The following statement is legal, because the statement is a pointer, and the length can be directly calculated.

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

self referencing trap

When we declare structures using typdefs, we expect to declare

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

But it fails, because the type name is not defined until the end of the declaration, and it is not defined when the structure is declared.
One of the solutions is that we don't omit the tag

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

cross-referencing of structures

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

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

initialization

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"
    };

access to structure members

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

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

assignment

Arrays do not allow assignment of one array to another

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

But structs can

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

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

deep copy and shallow copy

However, if a structure contains pointer variables, and dynamic memory allocation is performed in the process of using the structure, and the variables of the same type of structure are assigned to each other at the same time, shallow copy and deep copy problems will be caused. .

shallow copy

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

The problem here is that when std1 assigns a value to std2, because there is a pointer in the structure, the assignment only copies the address pointed to by the pointer in the structure, so when we release the structure std2, because the char* in std1 is already Released, but we released this address again, so repeated releases reported errors.

deep copy

Noticing the above problems, we have a good idea of ​​a solution, that is, pay attention to the pointer of the member variable in the struct when assigning a value, we reallocate a piece of memory, and copy the content, so this is a deep copy.

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;
}

array of structures

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];//
}

structure nesting

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);
}

Guess you like

Origin blog.csdn.net/chongbin007/article/details/126067602