[C 언어] - 사용자 정의 유형에 대한 자세한 설명: 구조, 열거형, 공용체

안녕하세요 여러분, 오늘 저는 C 언어의 사용자 정의 유형인 구조, 열거형, 공용체는 물론 이전에 알지 못했을 수도 있는 구조 메모리 정렬 및 비트 세그먼트와 같은 지식 포인트를 여러분과 공유하고 싶습니다! ! !

1. 구조

구조체는 멤버 변수라고 불리는 값의 집합입니다. 구조체의 각 멤버는 다양한 유형의 변수가 될 수 있습니다.

구조 선언: 예를 들어 학생을 설명하는 경우:

struct Stu
{
    
    
 char name[20];//名字
 int age;//年龄
 char sex[5];//性别
 char id[20];//学号
}; //分号不能丢

이는 학생의 구조 유형을 성공적으로 정의합니다.

특수 구조체 선언:
구조체 선언 시 불완전하게 선언될 수 있습니다.

//匿名结构体类型:结构在声明的时候省略掉了结构体标签
struct
{
    
    
 int a;
 char b;
 float c;
}x;
struct
{
    
    
 int a;
 char b;
 float c;
}a[20], *p;

참고: // 위 코드를 기준으로 볼 때 다음 코드는 합법인가요?
p = &x;
컴파일러는 위의 두 선언을 완전히 다른 두 유형으로 처리합니다.
그러니 불법입니다.

구조의 자체 참조

//正确的自引用
struct Node
{
    
    
 int data;
 struct Node* next;
};
//错误的自引用,促使无法确定结构体的大小
struct Node
{
    
    
 int data;
 struct Node next;
};

해결책:

typedef struct Node
{
    
    
 int data;
 struct Node* next;
}Node;

구조 변수 정의 및 초기화

구조체 타입을 사용하면 변수를 정의하는 방법이 실제로 매우 간단합니다.

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};//结构体嵌套初始化

구조 메모리 정렬:
구조의 기본 사용을 마스터했습니다.
이제 구조의 크기를 계산하는 문제를 살펴보겠습니다.
이것은 또한 특히 인기 있는 지식 포인트입니다: 구조 메모리 정렬

아래 코드를 살펴보면 전체 구조의 크기에 대한 첫인상은 어떻습니까?

struct S1
{
    
    
 char c1;
 int i;
 char c2;
};

여기에 이미지 설명을 삽입하세요.

두 문자에 정수 하나를 더하면 크기가 6바이트가 되어서는 안 되는데, 실행하면 왜 12바이트가 되는지, 상황은 어떤가요? 여기서 우리는 학습 구조 기억 정렬에 대한 지식을 이해해야 합니다!

먼저 구조의 메모리 정렬 규칙을 열어 보겠습니다.

  1. 첫 번째 멤버는 구조 변수의 오프셋 0에 있습니다.
  2. 다른 멤버 변수는 특정 숫자(정렬 번호)의 정수 배수인 주소에 정렬되어야 합니다.
    정렬 번호 = 컴파일러의 기본 정렬 번호와 멤버 크기 중 더 작은 것입니다.
    VS의 기본값은 8입니다.
  3. 구조체의 전체 크기는 최대 정렬 번호의 정수배입니다(각 멤버 변수에는 정렬 번호가 있음).
  4. 구조가 중첩된 경우 중첩된 구조는 자체 최대 정렬 번호의 정수 배수로 정렬되고
    구조의 전체 크기 모든 최대 정렬 번호(중첩 구조의 정렬 번호 포함)의 정수 배수입니다.

여기에 이미지 설명을 삽입하세요.
이 그림을 보면 구조의 메모리 정렬이 무엇인지 대략적으로 이해할 수 있을 것 같고 크기가 12인 이유도 이해할 수 있을 것 같습니다!

중첩된 구조의 크기를 살펴보겠습니다.

struct S4
{
    
    
 char c1;
 struct S1 s1;
 double d;
};
printf("%d\n", sizeof(struct S4));

여기에 이미지 설명을 삽입하세요.

분석을 살펴보겠습니다.
여기에 이미지 설명을 삽입하세요.
구조 메모리 정렬이 있는 이유는 다음과 같습니다.

대부분의 참고 자료에는 다음과 같이 나와 있습니다.

  1. 플랫폼 이유(이식 이유):
    모든 하드웨어 플랫폼이 모든 주소의 모든 데이터에 액세스할 수 있는 것은 아닙니다. 일부 하드웨어 플랫폼은 특정 주소에서 특정 유형의 데이터만 가져올 수 있습니다
    . 그렇지 않으면 하드웨어 예외가 발생합니다.
  1. 성능 이유:
    데이터 구조(특히 스택)는 가능할 때마다 자연스러운 경계에 정렬되어야 합니다.
    그 이유는 정렬되지 않은 메모리에 액세스하려면 프로세서가 두 번의 메모리 액세스를 수행해야 하지만 정렬된 메모리 액세스에는 한 번의 액세스만 필요하기 때문입니다
    .

구조를 디자인할 때 정렬을 만족시키는 것뿐만 아니라 공간을 절약해야 하는데,
공간을 덜 차지하는 멤버들을 최대한 모아야 한다.

위의 메모리 정렬 질문에는 기본 정렬 번호가 언급되어 있으며 수정이 가능합니다!

우리는 #pragma 전처리 지시문을 보았고 여기서는 이를 다시 사용하여 기본 정렬 번호를 변경합니다.

#include <stdio.h>

#pragma pack(1)//设置默认对齐数为8
struct S2
{
    
    
	char c1;
	int i;
	char c2;
};
#pragma pack()//取消设置的默认对齐数,还原为默认
//在这个区间里面默认对齐数就是1啦

2. 포지션 세그먼트

구조에 대해 이야기한 후에는 비트 세그먼트를 구현하는 구조의 능력에 대해 이야기해야 합니다.
비트
세그먼트 정의 비트 세그먼트의 선언과 구조는 유사하지만 두 가지 차이점이 있습니다:
1. 비트 세그먼트의 구성원은 int, unsigned int 또는 signed int여야 합니다.
2. 비트 필드의 멤버 이름 뒤에는 콜론과 숫자가 있습니다.

다음은 비트 세그먼트의 정의입니다.

struct A
{
    
    
 int _a:2;//_a占2个比特位
 int _b:5;
 int _c:10;
 int _d:30;
};

A는 비트 세그먼트 유형입니다.
세그먼트 A의 크기는 얼마입니까? 콜론 뒤의 비트는 해당 변수가 차지하는 비트입니다.
여기에 이미지 설명을 삽입하세요.

비트 세그먼트에 대한 메모리 할당:

  1. 비트 필드의 멤버는 int unsigned int signed int 또는 char(정수 계열에 속함) 유형일 수 있습니다.
  2. 비트 필드의 공간은 필요에 따라 4바이트(int) 또는 1바이트(char)로 할당됩니다.
  3. 비트 세그먼트에는 많은 불확실성이 포함됩니다. 비트 세그먼트는 크로스 플랫폼이 아닙니다. 이식성에 초점을 맞춘 프로그램은 비트 세그먼트 사용을 피해야 합니다.
struct S
{
    
    
 char a:3;
 char b:4;
 char c:5;
 char d:4;
};
int main()
{
    
    struct S s = {
    
    0};
s.a = 10;
s.b = 12;
s.c = 3;
s.d = 4;}


여기에 이미지 설명을 삽입하세요.

비트 세그먼트와 관련된 플랫폼 간 문제

1. int 비트 필드가 부호 있는 숫자로 간주되는지, 부호 없는 숫자로 간주되는지는 정의되지 않습니다.
2. 비트 필드의 최대 비트 수를 결정할 수 없습니다. (16비트 머신의 최대 개수는 16이고, 32비트 머신의 최대 개수는 32이므로 27로 표기됩니다. 이는
16비트 머신에서는 문제를 발생시킵니다. 3
. 비트 세그먼트는 메모리에서 왼쪽에서 오른쪽으로 할당되거나 오른쪽에서 왼쪽으로 아직 정의되지 않았습니다.
4. 구조체에 두 개의 비트 필드가 포함되어 있고 두 번째 비트 필드의 멤버가 더 크고 나머지 비트를 수용할 수 없는 경우 첫 번째 비트 필드에서는 나머지
비트를 버릴지 아니면 사용할지 확실하지 않습니다.

비트 필드에는 데이터를 보낼 때 데이터 패키징에 특정 응용 프로그램이 있습니다.
여기에 이미지 설명을 삽입하세요.
3. 열거

열거란 이름에서 알 수 있듯이 항목을 하나씩 열거하는 것을 의미합니다.
가능한 값을 하나씩 나열해 보세요.
예를 들어 실생활에서는
월요일부터 일요일까지 일주일에 7일로 제한되어 있으며 하나씩 나열할 수 있습니다.
성별에는 남성, 여성, 기밀이 포함되며 하나씩 나열할 수도 있습니다.

enum Day//星期
{
    
    
 Mon,
 Tues,
 Wed,
 Thur,
 Fri,
 Sat,
 Sun
};


enum Color//颜色
{
    
    
 RED,
 GREEN,
 BLUE
};

위에서 정의한 enum Day와 enum Color는 모두 열거형이다. {}의 콘텐츠는 열거형 상수라고도 하는 열거형의 가능한 값입니다(수정할 수 없음).
이러한 가능한 값은 모두 유효하며 기본적으로 0부터 시작하여 한 번에 1씩 증가합니다.
여기에 이미지 설명을 삽입하세요.
물론 정의 시 초기값을 지정할 수도 있습니다. 예를 들어

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

열거된 유형이 있을 수 있으므로 고유한 장점이 있어야 합니다.

코드의 가독성 및 유지 관리 용이성 향상
#define으로 정의된 식별자와 비교하여 열거형에는 유형 검사가 더 엄격합니다.
명명 오염(캡슐화)을 방지
하고 디버깅을 용이하게 하며, 사용이 간편
하고 한 번에 여러 상수를 정의할 수 있습니다.

열거형 사용:

enum Color//颜色
{
    
    
	RED=1 ,
	GREEN = 2,
	BLUE = 4
};
int main()
{
    
    
	//printf("%d\n", sizeof(union Un1));
	enum Color col=RED ;//只能拿枚举常量给枚举变量赋值,才不会出现类型的差异,枚举常量实质就是整型。
	col = 3.8;
	printf("%d", col);
}

4. 연합(공통)체

공용체의 멤버는 동일한 메모리 공간을 공유하므로 공용체 변수의 크기는 최소한 가장 큰 멤버의 크기 이상이어야 합니다(왜냐하면 공용체는 최소한 가장 큰 멤버를 저장할 수 있어야 하기 때문입니다).

union Un
{
    
    
	int i;
	char c;
};
union Un un;

int main()
{
    
    
	printf("%p\n", &(un.i));
	printf("%p\n", &(un.c));
	un.i = 0x11223344;
	un.c = 0x55;
	printf("%x\n", un.i);
}

여기에 이미지 설명을 삽입하세요.

조합 규모 계산

Union의 크기는 최소한 가장 큰 구성원의 크기입니다.
최대 멤버 크기가 최대 정렬 번호의 정수 배수가 아닌 경우 최대 정렬 번호의 정수 배수로 정렬되어야 합니다.

union Un1
{
    
    
	char c[5];
	int i;
};
int main()
{
    
    
	printf("%d\n", sizeof(union Un1));
	
}


여기에 이미지 설명을 삽입하세요.

분석: 공용체의 크기는 먼저 가장 큰 멤버의 크기이고, c[5]는 5바이트를 차지하고, 배열 c[]의 각 요소 크기는 1이며, vs의 기본 정렬 번호는 8이고, 그 다음은 정렬 번호는 1이고 i는 4바이트를 차지하며 vs의 기본 정렬 번호는 8이고 정렬 번호는 4이고 최대 정렬 번호는 4이며 정수로 정렬된 후 공용체의 크기는 8입니다. 4의 배수

컨소시엄의 적용:

여기에 이미지 설명을 삽입하세요.
여러 항목이 포함된 구조를 정의할 때 다양한 항목의 특정 속성을 통합 유형으로 정의할 수 있으므로 공간이 크게 절약됩니다! ! !

오늘의 내용은 여기에 공유합니다. 모두에게 도움이 되기를 바라며 함께 발전해 갑시다! ! !

Supongo que te gusta

Origin blog.csdn.net/m0_71214261/article/details/133272071
Recomendado
Clasificación