C언어 학습(9) 구조


프로그램을 설계할 때 가장 중요한 단계 중 하나는 데이터를 표현하는 방법을 선택하는 것입니다. 단순한 변수나 심지어 배열은 많은 경우에 충분하지 않습니다. 이를 위해 C에서는 구조체 변수(structure variable)를 제공하여 데이터를 표현하는 능력을 향상시켜 새로운 형태를 만들 수 있도록 합니다.

1. 구조적 기초


1.1 구조체란?

배열과 마찬가지로 구조체는 여러 구성 요소로 구성되며 배열과 달리 구조체의 멤버는 서로 다른 유형일 수 있으며 구조체의 요소는 멤버 이름으로 액세스할 수 있습니다.


1.2 구조문 만들기

구조 선언은 구조의 조직적 레이아웃을 설명합니다. 선언 구문은 다음과 같습니다.

structure 结构体名 {
	数据类型 成员1;
	数据类型 成员2;
	数据类型 成员3;
	...
	}
# include <stdio.h>

#define MAXLARGE  20

// 声明一个结构体名为book的结构体
struct book
{
    
    
	// 定义int类型的BookNum成员
	int booknum;
	// 定义char类型的Title数组成员,数组最大为MAXLARGE
	char title[MAXLARGE];
	// 定义char类型的author数组成员,数组最大为MAXLARGE	
	char author[MAXLARGE];	
	// 定义double类型的price成员
	double price;	
};


int main(void){
    
    

	return 0;
}

이 선언은 int 유형의 변수, char 유형의 두 변수 배열 및 double 유형의 구조로 구성된 구조를 설명합니다. 이 선언은 실제 데이터 개체를 만들지 않고 개체가 무엇으로 구성되어 있는지 설명합니다.

구조체 선언에서 구조체 멤버 목록은 한 쌍의 중괄호로 묶입니다. 각 멤버는 자체 선언으로 설명됩니다. 예: 제목은 MAXLARGE 요소를 포함하는 배열입니다. 멤버는 모든 데이터 유형, 심지어 다른 구조도 될 수 있습니다! 닫는 중괄호 뒤에 세미콜론이 필요하며 구조 레이아웃 정의의 끝을 표시합니다.

구조체 선언은 함수 외부 또는 내부에 배치할 수 있습니다. 함수 내부에 배치되면 함수 사용에 제한이 있는 지역 변수와 같습니다. 외부에 배치하면 선언 이후의 모든 함수를 사용할 수 있습니다.


1.3 구조 변수 정의

구조에는 두 가지 의미가 있습니다. 첫 번째 계층은 구조 레이아웃입니다.구조 레이아웃은 위에서 언급한 바와 같이 컴파일러에게 데이터를 표현하는 방법을 알려주지만 컴파일러가 데이터를 위한 공간을 할당하도록 허용하지는 않습니다. 다음 단계는 구조체에 대한 또 다른 의미 계층인 구조체 변수를 만드는 것입니다.

프로그램에서 구조 변수가 생성됩니다.

// 声明一个结构体名为book的结构体
struct book
{
    
    
	// 定义int类型的BookNum成员
	int booknum;
	// 定义char类型的Title数组成员,数组最大为MAXLARGE
	char title[MAXLARGE];
	// 定义char类型的author数组成员,数组最大为MAXLARGE	
	char author[MAXLARGE];	
	// 定义double类型的price成员
	double price;	
	
// library表示创建一个book结构体的变量名
} library;

等效于:
struct book library;

컴파일러는 이 코드 라인을 실행하고 구조 변수 라이브러리를 생성합니다. 컴파일러는 책 템플릿을 사용하여 이 변수에 대한 공간을 할당합니다.

구조체를 선언하는 과정과 구조체 변수를 정의하는 과정을 한 단계로 결합할 수 있습니다. 그러면 다음과 같이 표시됩니다.

struct 
{
    
    
	// 定义int类型的BookNum成员
	int booknum;
	// 定义char类型的Title数组成员,数组最大为MAXLARGE
	char title[MAXLARGE];
	// 定义char类型的author数组成员,数组最大为MAXLARGE	
	char author[MAXLARGE];	
	// 定义double类型的price成员
	double price;	
} library;  // 声明的右花括号后跟变量名

구조체 변수의 선언에서 struct book의 기능은 일반 선언의 int 또는 float와 동일합니다. 예: struct book 유형의 변수 또는 struct book에 대한 포인터를 정의할 수 있습니다.

struct book doyle, panish, *ptbook;

1.4 초기화 구조

구조 변수 초기화는 배열 초기화와 유사한 구문을 사용합니다.

struct book library=
{
    
    
	100010,
	"Tom and Jerry",
	"unknow",
	10.00
};

1.5 구조체 멤버 접근

그 구조는 슈퍼배열과 유사하며, 이 슈퍼배열에서 하나의 요소는 char형이고 다음 요소는 int형일 수 있으며, 배열에서 첨자를 사용하여 배열의 각 요소에 개별적으로 접근할 수 있다. 구조에서 구조의 구성원에 액세스하려면 구조 구성원 연산자 ------( . )를 사용해야 합니다.

# include <stdio.h>

#define MAXLARGE  20

struct book
{
    
    
	int booknum;	// 定义int类型的BookNum成员
	char title[MAXLARGE];	// 定义char类型的Title数组成员,数组最大为MAXLARGE
	char author[MAXLARGE];	// 定义char类型的author数组成员,数组最大为MAXLARGE
	double price;	// 定义double类型的price成员
};

struct book library=
{
    
    
	100010,
	"Tom and Jerry",
	"unknow",
	10.00
};

int main(void){
    
    

	// 在主函数中,使用结构体成员操作符访问结构体成员的属性。
	printf("%s\n", library.title);
	printf("%d", library.booknum);

	return 0;
}

1.6 구조체 초기화

C99 및 C11은 구조체에 대한 지정 이니셜라이저를 제공하며 구문은 배열에 대한 지정 이니셜라이저와 유사합니다. 그러나 구조체에 대한 지정 이니셜라이저는 점 표기법과 멤버 이름을 사용하여 특정 요소를 식별합니다.

# include <stdio.h>

#define MAXLARGE  20

struct book
{
    
    
	int booknum;	// 定义int类型的BookNum成员
	char title[MAXLARGE];	// 定义char类型的Title数组成员,数组最大为MAXLARGE
	char author[MAXLARGE];	// 定义char类型的author数组成员,数组最大为MAXLARGE
	double price;	// 定义double类型的price成员
};

// 使用C99和C11结构的初始化器初始成员,也可以只初始化部分成员。
struct book ptbook=
{
    
    
	.booknum=10010,
	.title="Tom",
	.author="unknow",
	.price=12.00
};



int main(void){
    
    

	printf("%s\n", ptbook.title);
	printf("%d", ptbook.booknum);

	return 0;
}

둘째, 구조 배열

구조 배열은 기본적으로 배열이며 배열의 각 요소는 구조입니다.


2.1 구조체 배열 선언

구조체 배열 선언은 다른 형식의 배열 선언과 유사합니다. 구조체 배열은 다음과 같이 선언됩니다.

struct book arrayst[MAXARRAY];

위의 코드는 arrayst를 MAXARRAY 요소를 포함하는 배열로 선언합니다. 배열의 각 요소는 책 유형 구조입니다.

배열 이름 arrayat 자체는 구조 이름이 아니라 배열 이름이며 배열의 각 요소는 struct book 유형의 구조 변수입니다.

#include <stdio.h>

#define MAXLARGE  20

struct book
{
    
    
	int booknum;	// 定义int类型的BookNum成员
	char title[MAXLARGE];	// 定义char类型的Title数组成员,数组最大为MAXLARGE
	char author[MAXLARGE];	// 定义char类型的author数组成员,数组最大为MAXLARGE
	double price;	// 定义double类型的price成员
};

struct book arrayst[3]={
    
    

	{
    
    100011, "围城", "钱钟书", 100.00},
	{
    
    100012, "西游记", "吴贯中", 102.00},
	{
    
    100013, "红楼梦", "曹雪芹", 103.00}
};


int main(void){
    
    

	printf("%s\n", arrayst[0].title);
	printf("%d", arrayst[1].booknum);

	return 0;
}

arrayst[1].num은 배열의 두 번째 요소, 즉 두 번째 구조의 num 속성 값에 액세스하는 것을 의미합니다.


3. 중첩 구조

다른 구조체 내에 구조체 포함(예: 중첩 구조체)

예:

#include <stdio.h>

// 第一个结构体
struct names
{
    
    
	char first_name[20];
	char last_name[20];

};

// 第二个结构体
struct friends {
    
    

	// 嵌套第一个结构体
	struct names people;
	int age;
	char gender;
	
	// 初始化第二个结构体
} info={
    
    
	{
    
    "Tom", "jerry"},
	12,
	'm'
};


int main(void){
    
    

	printf("%s\n", info.people);
	printf("%d", info.age);

	return 0;
}

구조체 선언 내에서 중첩 구조체가 생성되는 방식에 주목하십시오. int 유형의 변수를 선언하는 것과 같습니다.

struct names people;

이 선언에서 people은 구조체 이름 유형의 변수입니다. 물론 파일에는 구조 이름의 선언도 포함되어야 합니다.

중첩 구조의 멤버에 액세스하려면 도트 연산자를 두 번 사용해야 합니다.

printf("%s\n", info.people.last_name);

넷째, 구조에 대한 포인터

#include <stdio.h>

#define MAXLARGE  20

struct names
{
    
    
	char first_name[20];
	char last_name[20];

};

struct friends {
    
    

	struct names people;
	int age;
	char gender;
	
};

struct friends info[2]={
    
    
	{
    
    {
    
    "Tom", "jerry"}, 12, 'm'},
	{
    
    {
    
    "John", "Tim"}, 11, 'f'}
};



int main(void){
    
    
	
	// 声明一个结构指针
	struct friends *him;
	// 结构指针指向info的第1个元素
	him = &info[0];

	printf("%s\n", him->people.last_name);
	printf("%d", him->age);

	return 0;
}

4.1 구조체 포인터 선언 및 초기화

위의 프로그램에서 구조체 포인터를 선언하는 것은 간단합니다.

struct friends *him;

먼저 struct 키워드, 태그 구조 friend, 별표, 포인터 이름 순입니다.

배열과 달리 구조체 변수는 구조체 변수의 주소가 아니므로 구조체 변수 이름 앞에 & 연산자를 추가해야 합니다.

이 선언은 새 구조를 생성하지 않지만 포인터 him은 이제 guy 유형의 기존 구조를 가리킬 수 있습니다. 이 예에서 info는 구조의 배열입니다. 즉, info[0]은 구조이므로 그가 info[0]을 가리키도록 하려면 다음과 같이 작성할 수 있습니다.

him = &info[0];

him은 info[0]을 가리키고, him+1은 info[1]을 가리킵니다.


4.2 포인터로 멤버에 접근하기

위의 프로그램에서 그는 info[0]을 가리키고 연산자 섹션에서 -> 연산자를 사용하여 구조체 포인터 멤버의 값을 얻습니다.

// 获取him指向的成员属性值
printf("%s\n", him->people.last_name);
printf("%d", him->age);

5. 구조 정보를 함수에 전달

ANSI C에서는 구조를 매개변수로 사용할 수 있습니다. 따라서 프로그래머는 구조 자체를 전달할지 아니면 구조에 대한 포인터를 전달할지 선택할 수 있습니다. 구조체의 특정 부분에만 관심이 있는 경우 구조체의 멤버를 매개 변수로 사용할 수도 있습니다. 다음으로 이 세 가지 전달 방법을 분석합니다.


5.1 구조체 멤버 전달

구조체 멤버 전달은 구조체 멤버 속성 값을 함수의 매개변수에 전달하여 함수의 기능을 완성하는 것입니다.

#include <stdio.h>

// 定义结构体
struct funds
{
    
    
	double balance;
	double savefunds;
};

// 定义相加函数
double sum(double x, double y){
    
    

	return x + y;
}


int main(void){
    
    

	// 初始化结构体
	struct funds per={
    
    
		1000,
		1000
	};

	//调用函数,函数的参数为结构体的成员属性 
	printf("The total balance is : %lf", sum(per.balance, per.savefunds));
	
	return 0;
}

5.2 패스 구조 주소

위에서 계속해서 구조체의 주소가 아래 함수에 전달됩니다.

#include <stdio.h>

// 定义结构体
struct funds
{
    
    
	double balance;
	double savefunds;

};

// 定义加法函数。声明形参为结构体地址。形参地址为money
double sum(const struct funds * money){
    
    

	return (money->balance + money->savefunds) ;
}


int main(void){
    
    
	
	// 初始化结构体
	struct funds per={
    
    
		1000,
		1000
	};

	// 将实参结构体地址传入函数。
	printf("The total balance is : %lf", sum(&per));
	
	return 0;
}

5.3 패스 구조

함수에 대한 구조 전달을 지원하는 컴파일러는 구조를 매개변수로 전달할 수 있습니다.

#include <stdio.h>

// 定义一个结构体
struct funds
{
    
    
	double balance;
	double savefunds;

};

// 定义相加函数,并将结构体传给函数
double sum(struct funds totalbal){
    
    

	return (totalbal.balance + totalbal.savefunds) ;
}


int main(void){
    
    

	// 初始化结构体
	struct funds per={
    
    
		1000,
		1000
	};
	
	// 将结构体传给函数使用
	printf("The total balance is : %lf", sum(per));
	
	return 0;
}

5.4 구조체 및 구조체 포인터 선택

구조체를 전달하는 것과 구조체에 대한 포인터를 전달하는 것은 각각 고유한 장점과 단점이 있습니다. 포인터를 매개변수로 사용하면 주소가 전달되는 한 실행이 빠릅니다. 데이터를 보호할 수 없다는 단점이 있지만 새로운 const 한정자는 이 문제를 해결합니다.

결과를 인수로 갖는 이점은 함수가 원래 데이터를 보존하는 원래 데이터의 복사본에서 작동한다는 것입니다. 단점은 이전 버전에서는 구현하지 못할 수 있으며 구조를 전달하는 것은 시간과 공간의 낭비입니다. 특히 큰 구조를 함수에 전달할 때.


6. 연합

6.1 노동 조합 선언

C 언어에서는 여러 종류의 변수를 같은 메모리 단위에 저장할 수 있습니다.(동시에 저장하지 않음) 일반적인 용도는 불규칙하고 순서를 알 수 없는 혼합된 유형을 저장하도록 테이블을 설계하는 것입니다. 미리. 공용체의 크기가 모두 같고 각 공용체는 다양한 데이터 유형을 저장할 수 있는 공용체 유형의 배열을 사용합니다.

유니온은 구조체와 동일한 방식으로 생성되며 유니온 템플릿과 유니온 변수가 필요합니다. 유니온은 union 키워드로 선언됩니다.

union hold{
    
    
	int dight;
	double big;
	char litter;
}

6.2 유니온 사용

다음은 공용체의 몇 가지 용도입니다.

union hold fit;

fit.dight = 10; // 把10存储在fit的dight中
fit.big = 2.1 // 清除10,存储2.0
fit.litter = 'w' // 清除2.0 存储w

도트 연산자는 사용 중인 데이터 유형을 나타냅니다. 공용체에서는 한 번에 하나의 값만 저장할 수 있습니다. 공간이 충분하더라도 char 타입의 값과 int 타입의 값을 동시에 저장할 수는 없습니다. 따라서 코드를 작성할 때 현재 어떤 데이터 유형이 저장되어 있는지 주의하십시오.

포인터를 사용하여 구조체에 액세스하는 것과 동일, 포인터로 공용체에 액세스할 때 -> 연산자 사용

pu = &fit;

int x = pu->dight; // 相当于fit.dight

Guess you like

Origin blog.csdn.net/qq_46292926/article/details/127719244