간단 지식/C

04. 구조체 - 포인터, malloc, 화살표연산자, 역참조

납작한돌맹이 2020. 12. 2. 03:28
반응형

이전 글에서 구조체의 개념과 기본 예제, 그리고 구조체 배열에 대해서 설명했다. 

이전 글: 2020/11/06 - [1학년/c언어] - 03. 구조체, 공용체, 열거형

 

03. 구조체, 공용체, 열거형

구조체 자바에 생성자가 있어 개발의 편의성, 다양성이 향상된다면 c언어에는 구조체가 있다. 구조체란, 서로 다른 변수의 형태를 하나의 block으로 묶는 기법이다. 이로 인해 함수에 데이터를 넘

20plus3.tistory.com

이번엔 좀 더 나아가 구조체 포인터와 malloc으로 메모리를 할당하는 방법을 알아보자.

 

구조체 포인터는 구조체의 주소를 갖는다. 아래 예제를 보자.

typedef struct _student {
	char name[10];
	int age;
	char grade;
}student;

void main() {
	student s3;
	student *p;       ------------------(1)
	p = &s3;
    
    	printf("이름을 입력해주세요: ");
	scanf_s("%s", p->name, 10);       ----------(2)
	printf("나이를 입력해주세요: ");
	scanf_s("%d", &p->age);
	printf("성적을 입력해주세요: ");
	scanf_s("%c ", &p->grade);
	
	printf("%s의 이름, 나이, 반이 변경되었습니다.\n", p->name);
   	strcpy_s(p->name, 5, "yuri");
	p->age = 24;
	p->grade = 'C';
	printf("이름: %s, 나이: %d, 반: %c \n", (*p).name, (*p).age, (*p).grade);   ------------(3)
}

코드라인 (1)에서 포인터 변수 p를 선언했다. p에는 구조체 변수 s3의 주소가 저장된다. 이런 방식으로 구조체 포인터를 사용해도 되지만 효율적인 메모리 사용을 위해 이 부분을 malloc을 사용하여 동적 메모리를 할당하는 방식으로 변경할 수 있다. malloc과 관련된 예제는 아래에서 확인하자.

코드라인 (2)의 ->는 화살표연산자로, 멤버에 접근할 수 있게 해주는 역할을 한다. 

코드라인 (3)은 화살표연산자를 사용하는 것과 동일한 의미를 가지는데, 괄호와 역참조를 사용하여 .으로 멤버에 접근하는 방식이다. 역참조의 피연산자는 포인터여야하지만 괄호와 같이 사용하면 일반 변수에도 적용할 수 있다.

여기까지는 구조체의 가장 기본적인 사용방식 예제이고 아래를 통해 malloc과 역참조에 대해서 이해해보자.


구조체도 자료형이기 때문에 포인터를 선언할 수 있는 것이다. 그 말은 구조체포인터도 malloc을 사용하여 동적 메모리를 할당할 수 있다는 의미이다. 기본 사용 형식은 아래와 같다.

struct 구조체 이름 *p = malloc(sizeof(struct 구조체이름));

우리는 typedef를 이용한 구조체를 사용할 것이므로 struct이 생략되어도 좋다. 아래 예제를 보자.

typedef struct _data {
	char grade;
	int level;
	int *score;
}data;

void main()
{
	int MaxScore = 100;
	data s1;
	data *s2 = malloc(sizeof(data));	----(1)

	s1.score = &MaxScore;			----(2)	
	(*s2).score = &MaxScore;		

	printf("%d \n", *s1.score);		----(3)
 	printf("%d \n", *(*s2).score);
 
	(*s2).grade = 'A';
	printf("%c\n", (*s2).grade);
	
	s2->level = '3';
	printf("%d\n", s2->level);

	free(s2);   
}

 

코드라인 (1)에서 malloc을 이용하여 포인터변수 s2를 선언함과 동시에 메모리도 할당해주었다.

코드라인 (2)에서 멤버에 접근하여 변수 MaxScore이 위치한 주소를 저장해주었다. s1.score과 (*s2).score을 출력해보면 동일한 주소번지가 출력될 것이다.

코드라인 (3)에서 멤버의 역참조한 결과를 출력해보았다. 즉, s1.score와 (*s2).score은 주소가 저장되있으니 역참조하면 해당 주소가 가리키는 곳에 저장된 값을 가져온다는 의미이다. 따라서 출력결과는 둘다 100이다.

다시한번 말하지만 역참조의 대상은 포인터 멤버이다.

 

 

(이 글이 도움이 됐다면 광고 한번씩만 클릭 해주시면 감사드립니다, 더 좋은 정보글 작성하도록 노력하겠습니다 :) )

반응형