-
[정글 WEEK04_알고리즘] 개발일지 - C 포인터, * 연산자, & 연산자카테고리 없음 2025. 4. 3. 18:37
1. 포인터, 역참조 연산자 "*"
*는 변수 선언 시에는 포인터 선언으로, 변수 사용 시에는 역참조에 쓰임
포인터는 특정 변수 또는 데이터의 주소를 저장하는 특별한 변수
역참조는 주소에 있는 값에 접근
❗️ 포인터도 변수이므로 메모리 어딘가에 저장됨
int *i; // int형 데이터를 '가리키는' 포인터 i 선언 char *c; // char형 데이터를 '가리키는' 포인터 c 선언 double *d; // double형 데이터를 '가리키는' 포인터 d 선언
🗝️ 사용 맥락
1) 함수에서 값 변경(Call by Reference)
#include <stdio.h> void set_to_zero(int *ptr) { // 포인터 선언 *ptr = 0; // 역참조 -> ptr이 가리키는 주소에 저장되는 값ㅇ르 0으로 설정 } int main() { int a = 10; set_to_zero(&a); // a의 주소를 포인터 인자로 함수에 전달 printf("%d\n", a); // 출력: 0 return 0; }
2) 배열이나 자료구조의 데이터 처리
#include <stdio.h> int arr[3] = {10, 20, 30}; int *p = arr; // 포인터 선언, arr의 첫 번째 원소 주소로 초기화 for(int i = 0; i < 3; i++) printf("%d ", *(p + i)); // 역참조를 통해 배열 주소에 있는 원소 접근
3) 동적 메모리 할당 사용
#include <stdio.h> int *p = (int*)malloc(sizeof(int) * 100); // 포인터 선언, malloc을 통해 동적으로 확보한 메모리 100개 주소로 초기화 p[0] = 10; // *(p + 0)과 동일 -> 역참조로 0번 주소에 10 할당
4) 복잡한 데이터 구조 처리
#include <stdio.h> typedef struct Node { int data; struct Node *next; } Node; Node *head = malloc(sizeof(Node)); // 포인터 선언 -> Node 구조체를 가리키는 포인터 head->data = 10; // (*head).data와 동일 -> 역참조 후 멤버 접근 head->next = NULL; printf("%d\n", head->data); // 포인터 역참조로 접근
🔗 포인터 vs 역참조
#include <stdio.h> int main() { int a = 10; int *p = &a; // a의 주소를 '포인터' p에 저장 printf("변수 a의 값: %d\n", a); // 10 printf("변수 a의 주소: %p\n", &a); // 0x7ffe... printf("포인터 p가 가리키는 주소: %p\n", p); // &a → 0x7ffe... printf("포인터 p가 가리키는 값: %d\n", *p); // '역참조' → 10 *p = 20; // 포인터로 a의 값을 20으로 변경 printf("변경 후 변수 a의 값: %d\n", a); // 20 return 0; }
2. 주소 연산자 "&"
변수 앞에 붙여 해당 변수의 주소를 반환함
🗝️ 사용 맥락
1) 포인터 변수 초기화
#include <stdio.h> int a = 10; int *p = &a; // '포인터 p'에 변수 a의 '주소' 할당
2) 직접 주소 출력
#include <stdio.h> printf("%p", &a); // 변수 a의 포인터 주소 출력
3) 함수 인자로 전달
#include <stdio.h> // 함수 선언: 정수형 변수의 주소를 받아서, 값 변경 void change(int *ptr) { *ptr = 100; // 포인터를 역참조해서 원본 값 변경 } int main() { int a = 42; printf("before: %d\n", a); // 출력: 42 change(&a); // a의 주소 넘김 => change 함수에서 a 직접 수정 printf("after: %d\n", a); // 출력: 100 return 0; }
4) 입력 받은 값을 변수의 주소에 직접 접근해 저장(Call by Reference)
int num; // int형 데이터를 저장하는 num 변수 할당 scanf("%d", &num); //
3. Linked List 구현
🔗 Linked List는
- 메모리 공간이 연속적이지 않아도 되고,
- 각 요소가 자신 다음 노드의 주소를 저장하는 포인터를 갖고 있음
C에서 연결 리스트는 구조체와 포인터로 만듦
#include <stdio.h> #include <stdlib.h> // 노드 정의 typedef struct Node { int data; // 실제 저장할 값 struct Node* next; // 다음 노드를 가리키는 포인터 } Node; // 새 노드 생성 함수 Node* create_node(int value) { // 동적으로 노드 만들고 해당 주소 반환 Node* new_node = (Node*)malloc(sizeof(Node)); new_node->data = value; new_node->next = NULL; return new_node; } // 노드 추가 함수 (맨 끝에 추가) void append_node(Node** head, int value) { // head를 직접 바꾸기 위해 이중 포인터 사용 Node* new_node = create_node(value); if (*head == NULL) { *head = new_node; return; } Node* current = *head; while (current->next != NULL) { current = current->next; // 포인터를 따라가며 노드 순회 } current->next = new_node; } // 리스트 출력 함수 void print_list(Node* head) { Node* current = head; while (current != NULL) { printf("%d → ", current->data); current = current->next; // 포인터를 따라가며 노드 순회 } printf("NULL\n"); } // 메모리 해제 함수 void free_list(Node* head) { Node* current; while (head != NULL) { current = head; head = head->next; free(current); // malloc된 메모리 직접 해제 } } // 메인 함수 int main() { Node* head = NULL; append_node(&head, 10); append_node(&head, 20); append_node(&head, 30); printf("Linked List: "); print_list(head); free_list(head); return 0; }