728x90
1. 메모리와 변수
2. 포인터
3. 포인터와 배열
메모리와 변수
- 메모리와 변수
- 메모리는 데이터를 넣고 꺼내 쓰는 공간이다.
- 메모리의 위치는 주소 값으로 식별할 수 있고 주소 값은 바이트(byte) 단위로 구분된다.
- int a; => 메모리를 100번지부터 할당한다 가정하면, 100~103번지에 총 4byte로 할당된다.
- 주소 연산자 (&)
- &변수명
- 변수가 할당된 메모리 공간의 시작 주소가 반환된다.
- 메모리가 할당된 주소
- 시작주소 + 변수의 크기
- 메모리 주소의 출력 변환 문자
- 주소는 보통 16진수로 표기
- 전용 변환문자 %p (ex. printf("%p", &a); )
포인터
- 포인터
- 변수의 메모리 주소를 저장하는 변수
- 포인터가 필요한 경우
- 임베디드 프로그래밍 시, 메모리에 직접 접근하는 경우 필요
- 동적 할당한 메모리를 사용하는 경우 포인트가 필요
- 함수로 여러개의 값을 반환하지 못하기 때문에 이때 포인터를 활용 가능
- 포인터 선언
- 주소 위치에 있는 변수의 자료형 *포인터 변수명; (ex. int *pa;)
- 포인터에 주소값 할당
- 포인터 변수명 = &변수명; (ex. pa = &a;)
- 포인터 초기화
- 자료형 *포인터 변수명 = 주소; (ex. int *pa = &a;)
// 일반 변수 선언
int a;
// 포인터 변수 선언
int *pa;
// 포인터 pa가 변수 a를 가리킬 경우
pa ---> a
// 포인터 변수에 주소값 할당
pa = &a;
//포인터 초기화
int *b = &a
- 간접 참조 / 포인터 연산자 (*)
- 포인터가 가리키는 변수를 사용할 때 쓰는 연산자
- 포인터가 가리키는 변수 사용: *포인터
//포인터로 변수 a에 값 대입
*pa = 10;
//변수 a와 *pa 는 동일
*pa == a
//변수 a의 주소와 pa가 가리키는 변수의 주소는 동일
&a == &*pa
- 포인터와 const
- const 포인터 자료형 *포인터명 = 배열 주소
- 포인터가 가리키는 변수를 포인터가 간접 참조하여 바꿀 수 없도록 한다,
const int *pa = &a;
*pa = 20; //에러 발생
- 주소 vs 포인터
- 주소: 변수에 할당된 메모리 저장 공간의 시작 주소값 자체 (상수)
- 포인터: 주소값을 저장하는 또 다른 메모리 공간 (변수)
- 포인터의 크기
- 모든 주소와 포인터의 크기는 가리키는 자료형과 상관없이 동일하다.
// 자료형과 상관없이 주소는 동일한 크기
char *pc = &ch; //4byte
int *pi = ∈ //4byte
double *pd = &db; //4byte
- 포인터의 대입
- 포인터의 주소 크기는 자료형과 상관없이 같으나 자료형이 다른 포인터를 대입해선 안된다.
int a = 10;
int *p = &a;
double *pd;
pd = p; // int형 포인터가 double형 포인터로 생각하게되어 int형 포인터에 할당된 영역 외도 사용하게 된다.
포인터와 배열
- 배열명(배열 주소)
- 배열명은 첫 번째 배열 요소의 주소 값으로 첫 번째 배열 요소를 가리킨다.
- 컴파일러는 배열명을 컴파일 과정에서 첫번째 배열 요소의 주소로 변경한다.
- 배열 주소의 덧셈
- 배열명(배열 1번째 요소) + 1 => 배열 2번째 요소의 주소값을 반환
- 배열 요소에 사용하는 [] 대괄호는 연산식이다.
- 배열 요소 표현식: ary[1]
- 포인터 연산식: *(ary + 1)
int ary[3];
*(ary + 0) = 10; // => ary[0] = 10;
- 포인터를 이용한 배열요소 제어
- 포인터에 배열명을 저장하여 제어가 가능하다.
int ary[3];
int *pa = ary; //포인터에 배열 주소 저장
*pa = 10; //배열 1번째 요소에 값 10 대입
*(pa + 1) = 20; //배열 2번째 요소에 값 20 대입
*pa[2] = pa[0] + pa[1]; //배열 3번째 요소에 값 30(10+20) 대입
- 배열명 vs 포인터
- 배열명은 상수이고 포인터는 변수이다.
- sizeof 연산 결과가 다르다.
- sizeof(배열명): 배열의 전체 크기
- sizrof(포인터): 포인터 하나의 크기
- 포인터의 뺄셈
- 배열 요소간의 간격 차이를 반환
- 포인터 1 - 포인터 2 => (포인터1 주소값 - 포인터2 주소값) / sizeof(자료형)
int *pa = ary;
int *pb = pa + 3;
printf("pb - pa : %u", pb - pa); //pb - pa : 2
- 포인터의 관계 연산
- 배열 요소는 메모리에 순서대로 할당된다.
- 관계 연산을 통해 배열 요소의 순서를 확인할 수 있다.
int *pa = ary;
int *pb = pa + 3;
if(pa < pb)
{
printf("%d", *pa);
}
- 함수의 배열 처리
- print_ary(ary); / void print_ary(int *pary) { - }
- 배열명( 주소 값 )을 함수의 인수로 주면 주소 계산을 통해 모든 배열 요소를 사용 가능하다.
- 매개변수로 배열을 받을 시, 주소를 저장할 포인터를 선언한다.
- 매개변수 자리에 배열 선언시 저장 공간이 할당되지 않음
- 배열명은 컴파일 과정에서 포인터로 변환되므로 요소 개수가 무의미
- (ex. void func(pa[5]){...} => void func(*pa){...} )
- 배열의 크기(갯수)
- sizeof(배열명) / sizeof(배열 첫번째 요소); ( ex. sizeof(ary) / sizeof(ary[0]); )
- 함수 안에서는 sizeof 연산자로 배열의 크기를 알 수 없다. (호출 시 넘겨줄 것)
int main(void)
{
int ary[5] = {1,2,3,4,5};
//배열의 갯수 구하기
int ary_count = sizeof(ary) / sizeof(ary[0]);
print_ary(ary, ary_count);
}
void print_ary(int *pa, int count)
{
for (int i=0; i < count; i++)
{
printf("%d", pa + i);
}
}
'C > C 문법' 카테고리의 다른 글
| 혼자 공부하는 C언어 (13~14강) (0) | 2025.09.07 |
|---|---|
| 혼자 공부하는 C언어 (11~12강) (1) | 2025.09.07 |
| 혼자 공부하는 C언어 (7~8강) (0) | 2025.09.05 |
| 혼자 공부하는 C언어 (5~6강) (0) | 2025.09.03 |
| 혼자 공부하는 C언어 (3~4강) (1) | 2025.09.02 |