[C] 배열과 포인터

2021. 1. 7. 23:35프로그래밍 공부/C 공부

배열과 포인터 표기법 관계

포인터는 메모리 시작주소를 기준으로 크기에 따라 전체 메모리 주소를 기억한다.

배열도 다르지 않다. 배열도 시작주소를 기준으로 크기에 따라 전체 메모리 주소를 기억한다.

포인터는 *연산자를, 배열은 [ ] 연산자를 쓴다 뿐이지 둘은 본질적으로 유사하다.

 

따라서 다음과 같이 표현할 수 있다.

#include <stdio.h>

// ==== 코드 A : 배열 ====
void main ()
{
	char data[5] ;
    
    /* 아래 둘은 같은 표현임 */
	data[1] = 5;
	*(data +1) = 5; 
    //tip : *(data +0) 은  *(data)로 줄여서 쓸 수 있다.

}

// ==== 코드 B : 포인터 ====

#include <stdio.h>

void main ()
{
	char data;
	char *p = &data;
    
    /* 아래 둘은 같은 표현임 */
	*p = 3;
	p[0] = 3;
 }

 *(data +1) =5 은 배열을 포인터처럼 사용한 예로, *p = 5 의 표현이 의미하는 바를 다시 한번 더 생각하게 만든다.

 

*p는 사실 포인터 p가 가리키고 있는 주소이고, 변수 data 역시 컴퓨터가 봤을때는 그 변수가 가지고 있는 메모리 주소를 나타낸다는 점에서 포인터에 직접적으로 data 를 주는 것은 사실 주소를 지정하는 것돠 다르지 않다.  따라서 *(data +1) = 5 와 data[0] = 5는 같은 표현이된다.

 

코드B의 경우도 같은 맥락에서 포인터는 가리키는 주소를 나타내는 변수의 [0]번째 배열을 가리키는 것이라는 것을 알 수 있다.

 

배열 표기법의 한계

둘이 문법적으로만 다르지 본질은 똑같다는걸 알았다. 그래서 어쩌라는걸까?

배열과 포인터가 본질적으로 같다는 것은 배열에 저장된 데이터를 더 세밀하게 조작할 수 있다는 것을 의미한다. 

이는 포인터의 형변환을 통해 가능하다.

 

아래와 같이 선언된 array에서 

#==== arr 선언
int arr = {0x12345678 , 0x12345678}; 

시작주소 1바이트에 저장된 0x78을 0x22로 바꾸고 싶을때 어떻게 할까?

arr[0] = 0x22;

배열은 선언된 자료형태에 따라 연산된다. 따라서 위와 같은 코드는 첫 메모리 뭉텅이, 그러니까 int에 해당하는 4바이트를  0x22로 바꾼다는 것을 의미하고, 0x12345678이 저장되어있던 4바이트는 0x00000022 가 되어버린다. 

 

이 문제는 포인터를 활용해서 해결할 수 있다. 

*(char *)(arr) = 0x22;

포인터의 형태를 1바이트인 char로 변환하고 (이는 일시적이다.) arr[0]을 주소로 주면 arr[0]의 첫 1바이트를 0x22로 변경하게된다. 

 

포인터 표기의 번잡함

배열을 포인터로 변경함으로써 얻는 이점은 확실하다. 혹시 포인터 표기를 배열 표기로 바꿔서 얻는 이득이 있을까?

int tips = 0x12345678 ;
char *p ;
*p = (char *)&tips; // 1바이트 단위로 쪼개서 주소를 부여.

sum = *(p+0) + *(p+1) + *(p+2) + *(p+3); //각 바이트값을 합산(포인터 표기)

sum = p[0] + p[1]+ p[2] + p[3]; //각 바이트값을 합산(배열 표기)

포인터표기를 배열표기로 바꿔서 얻는 것은 간결함이다. 

다만 이러한 표기는 직접 작성한 사람이 아니라면 p를 배열이라고 착각하도록 만들 수 있기 때문에 항상 권장되는 형태는 아니다.

 

*과 & 표기법

*과 &의 역할이 좀 헷갈린다.

&는 주소를 반환하라는 뜻이고 *는 포인터라는 뜻인가?

 

정확히 말하면 *는 *다음에 오는 것이 가리키는 주소를 의미한다. 

char *p는 그렇다면 p라는 변수가 가리키는 주소를 의미하는 것이다.

따라서 *p = &addr로 쓰지 않던가?

 

 

 

'프로그래밍 공부 > C 공부' 카테고리의 다른 글

[C] 프로세스와 메모리할당  (0) 2021.01.08
[C] 배열과 포인터 2  (0) 2021.01.08
[C] scanf 함수 2  (0) 2021.01.07
[C] scanf 함수 1  (0) 2021.01.07
[C] 문자, 문자열  (0) 2021.01.06