2018년/C, Java, FileSystem

[C] :: 배열, 주소, 포인터

위지원 2018. 1. 8. 15:20

C의 장점 중 하나는 프로그래머가 메모리 주소에 접근할 수 있다는 것이다.



배열


다음의 코드를 보면 grade는 5개의 정수를 가지고 있는 1차원 배열이다. 각각의 정수가 4바이트 공간을 차지한다면 각 index의 값은 다음과 같다.


    


여기서 grade[n]은 컴퓨터에게 "주소 계산을 해줘" 라고 시킨 것이다.

예를 들어 grade3]은 &grade[0]+( 3칸 * 4byte )  즉 n은 [0]에서 얼마나 떨어져있으며 (3) 얼마만큼 공간을 차지하는지 (4)를 계산하는 것 이다.



포인터의 독특한 특성은 포인터를 사용하는 문장에서 오프셋이 명시되어야 한다는 것이다.

아래 코드에서 14번째 줄의 gPtr+i에서 i가 바로 오프셋이다. gPtr은 grade의 0번째 인덱스를 참조하기 때문에 위의 코드와 같은 결과가 출력된다.

여기서 주의할 점은 *(...) 로 괄호를 쳐야하는데 안그러면 gPtr에 있는 값을 불러온다음에 i값을 더해서 다른 값이 출력되기 때문이다.


    


배열이 만들어질때 컴파일러는 내부적으로 포인터 상수를 만들어 두고 그 배열의 시작주소를 저장한다.

이때 index를 통해 참조하는 것은 grade라는 포인터 변수를 통해 참조하는 것과 같은 결과이다 그래서

grade[i]는 *(grade+i)와 같다.(위의 코드들 주목)


여기서 재미있는 사실은 *numPtr이라는 포인터 변수는 numPtr[i]로 주소를 찾아갈 수 있다.


    




포인터 연산


포인터에 값을 합하거나 뺀다는 것은 새로운 주소를 가지게 된다는 의미이다. 이때 컴퓨터가 자동적으로 연산의 결과가 유효한 값(같은 자료형의 값)을 가르키도록 조정한다.

ex. nPtr = nPtr+2 는 정수가 4byte공간이 필요하다 생각하여 nPtr에 (4*2)값을 더한다. ... ? 그냥 2칸이동한다고 생각하면 된다.


증감, 감소 연산자는 전위와 후위 연산에 모두 적용된다.

total=total_*nPtr++ 대신 total+=*nPtr++;로 쓰는 경우가 더 많다.


    




배열의 주소 전달과 사용


배열이 함수의 인자로 전달될 때 , 그 배열의 주소가 실제로 전달되는 유일한 요소이다.

findMax의 인자를 int findMax(int *vals,int numEls) 이렇게 포인터로 변경해도 아~무 문제 없이 잘 실행이 된다.




다차원 배열의 포인터는 다음과 같이 표시 될 수 있다.


**함수가 int *calc()로 되어있으면 정수현 포인터 변수를 return 한다는 것

**int (*calc)()은 정수형을 return하는 함수에 대한 포인터 calc


포인터를 이용한 문자열의 처리


배열의 이름을 인자로 받는 것은 index 0번째를 받는것과 동일하기때문에 아래와 같이 코드를 변경할 수 있다.


1)




2)


 


3)




포인터를 이용한 문자열의 생성


문자열 정의는 자동적으로 하나의 포인터를 포함한다.


        


%p는 변수의 주소를 헥사로 표현할때 사용한다. 덮어 씌우는것이 아니라 가르키는게 달라지는것이다.

처음엔 1번째로 가르키고 그다음에는 2번째로 변경된다



포인터 배열


문자에 대한 포인터를 원소로 하는 배열의 선언은 각 문자열의 첫 글자의 주소를 원소로 가진다.