250526 공부 노트 - Hwanghyewon06/c- GitHub Wiki
당신이 공부한 struct
, 포인터, 메모리 구조, 그리고 함수 전달 방식에 대한 내용을 정리해서 설명
struct Point {
int x;
int y;
};
-
Point
구조체는int
형 멤버x
,y
를 가짐. - 각각 4바이트이므로
Point
구조체 하나는 8바이트를 차지함.
void PrintPoint(Point* p) {
printf("(%d, %d)\n", p->x, p->y);
}
-
Point
구조체의 주소를 전달하여 복사 없이 직접 접근 가능. -
->
연산자는 포인터가 가리키는 구조체의 멤버에 접근할 때 사용. - 효율적인 방법 (대용량 구조체일 때 유리).
void PrintPoint(Point pt) {
printf("(%d, %d)\n", pt.x, pt.y);
}
- 구조체 전체가 복사되어 전달됨.
- 포인터보다 메모리 사용량이 더 많고, 성능 측면에서 불리할 수 있음 (작은 구조체는 괜찮음).
Point* p = &pt;
(*p).x; // 또는 p->x;
-
*p.x
는 문법적으로 잘못됨..
연산자의 우선순위가*
보다 높기 때문. - 올바른 표현:
(*p).x
또는p->x
printf("%p %p\n", &pt, &pt + 1);
-
&pt
는 구조체 전체의 주소,&pt + 1
은 그 다음 구조체 주소 (즉, 8바이트 차이). -
&pt.x
와&pt.x + 1
은 int형 기준으로 4바이트 차이.
Point pt = {2, 3};
- 구조체
pt
의 크기는int x(4) + int y(4)
= 8바이트 - 구조체는 연속된 메모리 공간에 저장되며 멤버들은 순서대로 배치됨.
-
pt.x
,pt.y
각각은 해당 구조체 내에서 이름으로 접근됨.
항목 | 설명 |
---|---|
구조체 정의 |
struct 키워드로 사용자 정의 데이터 타입 생성 |
멤버 접근 | 변수일 때: pt.x / 포인터일 때: p->x 또는 (*p).x
|
함수 전달 방식 | 포인터 전달(주소): 효율적, 원본 직접 접근 / 값 전달: 복사됨 |
메모리 크기 | 각 멤버의 크기 합 (여기서는 4 + 4 = 8바이트) |
포인터 연산 |
*p.x 는 오류 → (*p).x 또는 p->x 사용 |
주소 출력 | 구조체 단위, 멤버 단위로 주소 확인 가능 |
네! 이해했습니다. 주어진 코드들을 쪼개서 핵심 개념 위주로 깔끔하게 정리해드릴게요.
#include <stdio.h>
#include <stdlib.h>
typedef int I;
typedef int* PI;
-
#include <stdio.h>
: 입출력 함수(printf
,scanf
) 사용 가능하게 함 -
#include <stdlib.h>
: 동적 메모리 함수(malloc
,free
) 사용 가능하게 함 -
typedef int I;
:int
를I
라는 이름으로 별칭 생성 → 코드 간결화 -
typedef int* PI;
:int*
를PI
라는 이름으로 별칭 생성 → 포인터 표현 간단히
void AssignAddress(PI* pp, I* pdata)
{
*pp = pdata;
}
-
PI* pp
는int** pp
와 동일. -
AssignAddress
는 포인터 변수p
의 주소를 받아서p
가 가리키는 값을pdata
(즉, 변수 주소)로 설정함. - 이렇게 하면
main
에서 포인터 변수의 값을 변경할 수 있음 (call by reference 역할).
int main()
{
I a = 10;
I b = 20;
PI p = NULL;
AssignAddress(&p, &b);
printf("data : %d\n", *p);
}
-
I a, b
→int a, b
와 같음 -
PI p
→int* p
-
AssignAddress(&p, &b);
→p
포인터 변수의 주소를 넘겨서p
가b
의 주소를 가리키도록 함 - 출력은
*p
즉b
의 값인 20 출력됨
void AllocIntArray(int** pp, int capacity)
{
*pp = (int*)malloc(sizeof(int) * capacity);
}
- 함수 파라미터
int** pp
는int*
포인터 변수의 주소 -
*pp = malloc(...)
을 통해 실제 포인터 변수에 동적 할당 주소를 저장 -
main
에서 포인터 변수를 넘길 때는&pa
형태로 주소를 넘겨야 함
void InitIntArray(int* pa, int size)
{
for (int i = 0; i < size; ++i)
pa[i] = i + 1;
}
void PrintIntArray(int* pa, int size)
{
for (int i = 0; i < size; ++i)
printf("data : %d\n", pa[i]);
}
-
pa
는int
배열의 시작 주소 - 배열 요소를 순회하면서 값 초기화 및 출력 수행
int main()
{
int* pa = 0;
AllocIntArray(&pa, 10);
InitIntArray(pa, 10);
PrintIntArray(pa, 10);
free(pa);
}
-
AllocIntArray
에서 포인터 변수pa
의 주소를 넘겨서 동적 메모리 할당 - 할당된 메모리에 값 초기화 및 출력 수행
- 사용 후
free(pa);
로 메모리 해제
int main()
{
int a = 10;
int b = 20;
int* p = NULL;
p = &b;
printf("data : %d\n", *p);
}
-
p
에 변수b
의 주소 직접 대입 -
*p
를 통해b
의 값 20 출력
개념 | 설명 | 코드 예시 |
---|---|---|
헤더 포함 | 표준 입출력, 동적 메모리 함수 사용 |
#include <stdio.h> #include <stdlib.h>
|
typedef 별칭 | 타입 이름을 간단하게 별칭 생성 | typedef int I; typedef int* PI; |
이중 포인터 함수 전달 | 포인터 변수 주소를 넘겨 내부에서 포인터 값 변경 가능 | void AssignAddress(PI* pp, I* pdata) |
동적 메모리 할당 | 이중 포인터 받아 malloc 한 주소를 포인터 변수에 저장 |
void AllocIntArray(int** pp, int capacity) |
배열 초기화 및 출력 | 포인터로 배열 접근하여 값 세팅 및 출력 |
InitIntArray , PrintIntArray 함수 |
메모리 해제 | 사용한 동적 메모리는 반드시 free 로 해제해야 함 |
free(pa); |
포인터 직접 주소 대입 | 포인터 변수에 변수 주소 직접 저장 후 접근 가능 | p = &b; printf("%d", *p); |
네! 주어진 여러 코드들을 쪼개서 핵심 개념별로 깔끔하게 정리해드리겠습니다. 아래 내용은 동적 메모리 할당, 포인터 사용, 함수 분리, CRUD 개념 위주로 단계별 설명입니다.
#include <stdio.h>
#include <stdlib.h>
-
stdio.h
: 입출력 함수(printf
,scanf
) 사용 가능 -
stdlib.h
: 동적 메모리 함수(malloc
,free
) 사용 가능
int* AllocInt()
{
return (int*)malloc(sizeof(int));
}
double* AllocDouble()
{
return (double*)malloc(sizeof(double));
}
-
malloc
으로int
,double
크기만큼 메모리 동적 할당 -
(int*)
,(double*)
캐스팅은 C 스타일 타입 변환 (필수는 아님, C++은 권장) - 반환값은 각각
int*
,double*
void SetInt(int* p, int data)
{
*p = data;
}
void SetDouble(double* p, double data)
{
*p = data;
}
- 포인터
p
가 가리키는 주소에 데이터 저장 (*p = data
) - 외부에서 값을 직접 저장하지 않고 함수로 캡슐화
void PrintInt(int data)
{
printf("int :%d\n", data);
}
void PrintDouble(double data)
{
printf("double :%g\n", data);
}
- 직접 값(
int
,double
)을 받아 출력 - 포인터가 아니라 값을 받는 이유: 출력 시 값 복사만 하면 됨
void FreeInt(int* p)
{
free(p);
}
void FreeDouble(double* p)
{
free(p);
}
- 할당된 메모리 해제
- 메모리 누수 방지를 위해
malloc
후 반드시 호출해야 함
int main()
{
int* pa = NULL;
double* pb = NULL;
// Create: 동적 메모리 할당
pa = AllocInt();
pb = AllocDouble();
// Update: 값 저장
SetInt(pa, 10);
SetDouble(pb, 3.14);
// Read: 출력
PrintInt(*pa);
PrintDouble(*pb);
// Delete: 메모리 해제
FreeInt(pa);
FreeDouble(pb);
return 0;
}
- 포인터 변수
pa
,pb
선언 후NULL
초기화 - 할당, 값 저장, 출력, 해제 단계를 함수 호출로 분리하여 명확하게 관리
-
*pa
,*pb
는 실제 값에 접근할 때 사용
int main()
{
int* pa = (int*)malloc(sizeof(int));
double* pb = (double*)malloc(sizeof(double));
*pa = 10;
*pb = 3.14;
printf("int :%d\n", *pa);
printf("double :%g\n", *pb);
free(pa);
free(pb);
return 0;
}
-
malloc
과free
직접 사용 - 동적 메모리 할당 시, 항상
free
호출 필요 - 함수로 분리하지 않아 코드가 간결하지만, 재사용성과 가독성은 떨어짐
기능 | 구현 방법 및 특징 | 코드 핵심 |
---|---|---|
동적 메모리 할당 |
malloc 으로 크기만큼 메모리 확보, 포인터 반환 |
int* pa = (int*)malloc(sizeof(int)); |
값 저장 | 포인터로 주소를 받아 *p = data 로 값 저장 |
SetInt(int* p, int data) |
값 출력 | 값을 복사받아 출력 | PrintInt(int data) |
메모리 해제 | 할당된 메모리는 반드시 free 호출 |
FreeInt(int* p) |
함수 분리 | 기능별 함수 분리하여 코드 관리 용이 |
AllocInt() , SetInt() , 등 |
포인터 직접 사용 | 함수 없이 동적 할당, 직접 포인터 조작 가능 | *pa = 10; printf("%d", *pa); |