카테고리 없음

[C언어] 구조체, 포인터에 대한 이해

codecodekode 2024. 10. 7. 21:00

19. 다음 C언어로 구현된 프로그램을 분석하여 그 실행 결과를 쓰시오.

#include 

struct node {
	int n1;
	struct node *n2;
};

int main() {
	struct node a = {10, 0};
	struct node b = {20, 0};
	struct node c = {30, 0};

	struct node *head = &a;
	a.n2 = &b;
	b.n2 = &c;

	printf("%d", head -> n2 -> n1);

        return 0;
}

코드 분석

  1. 구조체 정의
    • struct node는 두 가지 멤버를 가지고 있습니다:
      • int n1 : 정수를 저장하는 멤버.
      • struct node *n2 : struct node 구조체를 가리키는 포인터. 이는 다른 node 구조체를 가리키기 위해 사용됩니다.
  2. 구조체 변수 선언 및 초기화
    • struct node a: n1 값을 10으로 초기화하고, n2는 0(NULL)로 초기화합니다.
    • struct node b: n1 값을 20으로 초기화하고, n2는 0(NULL)로 초기화합니다.
    • struct node c: n1 값을 30으로 초기화하고, n2는 0(NULL)로 초기화합니다.
  3. 구조체 포인터 및 연결 설정
    • struct node *head = &a : head는 구조체 포인터로 a의 주소를 가리키게 설정합니다.
    • a.n2 = &b : a의 포인터 멤버 n2는 b를 가리킵니다. 즉, a가 b를 가리키도록 설정합니다.
    • b.n2 = &c : b의 포인터 멤버 n2는 c를 가리킵니다. 즉, b가 c를 가리키도록 설정합니다.
    이로써 구조체들은 다음과 같이 연결됩니다:
    • a -> b -> c
  4. 출력 부분
    • head는 a를 가리키고 있습니다. 따라서 head -> n2는 a.n2를 의미하며, 이는 b의 주소를 가리킵니다.
    • head -> n2 -> n1은 b.n1을 의미합니다. b.n1의 값은 20입니다.
    • 따라서 출력 결과는 20입니다.

최종 실행 결과

코드 복사
20

요약

  • struct node 구조체를 사용하여 세 개의 노드를 연결합니다.
  • a는 b를, b는 c를 가리키게 설정하였습니다.
  • head -> n2 -> n1은 b.n1을 의미하며, 출력되는 값은 20입니다.

 


1. 구조체를 가리키는 포인터?

  • 구조체를 가리키는 포인터구조체의 주소를 저장하는 포인터입니다.
  • 일반적으로 포인터는 특정 자료형의 변수나 메모리 위치를 가리키기 위해 사용됩니다. 마찬가지로, 구조체 포인터는 특정 구조체의 주소를 저장하며, 해당 구조체에 접근할 수 있는 수단입니다.

예시:

 
  • struct node *p = &a;에서 p는 구조체 a의 주소를 저장합니다.
  • 이를 통해 p를 사용해 a의 멤버들에 접근할 수 있습니다.

2. head는 구조체 포인터?

  • 코드에서 struct node *head = &a;는 head가 구조체 포인터라는 의미입니다.
  • 여기서 struct node *head는 struct node 타입의 구조체를 가리키는 포인터 변수를 선언한 것입니다.
  • head = &a;는 head에 구조체 변수 a의 주소를 저장하는 것이며, 따라서 head는 구조체 a를 가리키고 있습니다.

3. head는 a를 가리키고 있습니다. 따라서 head -> n2는 a.n2를 의미하며?

  • 포인터 연산자 (->):
    • 포인터 변수가 구조체를 가리키고 있을 때, 해당 구조체의 멤버에 접근하려면 -> 연산자를 사용합니다.
    • head가 구조체 a의 주소를 가리키고 있으므로, head -> n2는 a.n2에 접근하는 것과 동일한 의미입니다.

구체적으로 설명하면

  1. head는 구조체 포인터로, a의 주소를 가지고 있습니다.
  2. 따라서 head -> n2는 포인터 head가 가리키는 구조체의 n2 멤버를 의미합니다.
  3. head -> n2는 구조체 a의 n2 멤버를 나타내며, 이는 a.n2와 동일합니다.

요약

  • 구조체를 가리키는 포인터는 구조체의 주소를 저장하는 포인터입니다.
  • head는 구조체 포인터로, struct node 타입의 구조체를 가리키는 포인터 변수를 의미하며, a의 주소를 저장하고 있습니다.
  • head -> n2는 head가 가리키는 구조체(a)의 n2 멤버에 접근하는 것으로, 이는 a.n2와 동일합니다. a.n2는 구조체 b의 주소를 가리키고 있기 때문에, head -> n2는 b를 가리키게 됩니다.

이 개념들은 포인터와 구조체, 그리고 그 두 가지의 조합을 이해하는 데 필수적인 내용입니다. 포인터가 특정 구조체를 가리키고 있을 때 구조체 멤버에 접근하기 위해 사용하는 -> 연산자와, 이를 통한 구조체 간의 연결을 이해하는 것이 중요합니다.


위의 C 언어 문제를 풀기 위해 알아야 하는 주요 개념들은 다음과 같습니다

1. 구조체 (struct)

  • 구조체 정의 : 구조체는 관련된 데이터를 하나의 단위로 묶기 위한 사용자 정의 데이터 형식입니다. 여기서 struct node는 두 가지 멤버를 가지고 있으며, 하나는 정수(int n1), 다른 하나는 자기 참조 포인터(struct node *n2)입니다.
  • 구조체 초기화 : 구조체 변수들을 선언하고 값을 초기화하는 방법에 대해서도 이해해야 합니다. 예를 들어 struct node a = {10, 0};은 멤버 n1을 10으로, n2를 NULL로 초기화합니다.

2. 구조체 포인터

  • 포인터와 구조체의 사용 : struct node *head와 같이 구조체를 가리키는 포인터를 선언할 수 있습니다. 이 포인터는 특정 구조체 변수의 주소를 가리키며, 이를 통해 그 구조체의 멤버에 접근할 수 있습니다.
  • 포인터 연산자 (->) : 구조체 포인터가 가리키는 구조체의 멤버에 접근할 때 -> 연산자를 사용합니다. 예를 들어 head->n2는 head가 가리키는 구조체의 n2 멤버를 의미합니다.

3. 포인터의 개념

  • 주소와 참조 : 포인터는 변수의 주소를 저장하는 변수입니다. &a와 같은 표현은 변수 a의 주소를 의미하며, 이 주소를 포인터 변수에 저장하여 다른 곳에서 사용할 수 있게 합니다.
  • 포인터의 연결 : 문제에서 a.n2 = &b;, b.n2 = &c;와 같은 표현을 통해 구조체 변수들이 연결되어 있으며, 이는 연결 리스트 형태로 구현된 것입니다. 이러한 포인터 연결을 통해 구조체들이 연결되는 구조를 이해해야 합니다.

4. 포인터를 통한 구조체의 연결 (링크드 리스트 형태)

  • 문제에서 구조체 변수 a, b, c가 서로 포인터를 통해 연결되어 있습니다. 이는 단일 연결 리스트(Singly Linked List)와 같은 형태로, 각 구조체는 다음 구조체를 가리키고 있습니다.
  • 이를 통해 각 구조체가 다음 구조체를 가리키도록 설정하여, 포인터를 이용해 구조체들을 순차적으로 탐색할 수 있습니다.

5. 메모리와 주소 이해

  • 변수의 주소 : &a는 변수 a의 주소를 의미합니다. 구조체 포인터에 이 주소를 저장함으로써 구조체 변수에 간접적으로 접근할 수 있습니다.
  • 포인터의 간접 참조 : 포인터를 통해 구조체의 멤버에 접근하는 경우, 직접 변수명을 쓰는 것과 달리 포인터를 사용하여 접근합니다. 이때 * 연산자와 -> 연산자를 적절히 사용하는 것이 중요합니다.

6. printf를 통한 출력

  • 출력 함수 (printf): printf("%d", head->n2->n1);는 포인터를 통해 특정 구조체 멤버에 접근하여 값을 출력하는 예시입니다.
  • 포인터 head가 a를 가리키고 있고, a의 n2가 b를 가리킵니다. 따라서 head->n2->n1은 구조체 b의 멤버 n1에 접근하여 값을 출력하는 것입니다.

요약

  • 구조체 정의 및 초기화: 구조체의 멤버 선언과 초기화 방법을 이해해야 합니다.
  • 구조체 포인터와 포인터 연산자 (->): 구조체를 가리키는 포인터를 선언하고, 이를 통해 구조체 멤버에 접근하는 방법을 알아야 합니다.
  • 주소와 참조, 포인터의 개념: 포인터를 통해 변수나 구조체의 주소를 다루고, 이를 통해 간접적으로 접근하는 방법을 이해해야 합니다.
  • 포인터를 통한 연결 리스트 개념: 여러 구조체가 포인터를 통해 연결될 때, 포인터를 사용하여 연결된 구조체 간의 탐색 및 데이터 접근이 가능하다는 점을 이해해야 합니다.
  • 메모리 주소와 포인터 연산: 구조체의 주소를 저장하고 이를 참조하는 방법을 이해해야 합니다.