3.포인터
DESCRIPTION
TRANSCRIPT
C 언어와 포인터 (3)
포인터 학습
"완전학습을 지향하는" NHN NEXT 정호영
나눔고딕 및 나눔고딕코딩 글꼴을 설치해 주세요 .
오늘의 토픽
1. 함수에 배열을 건네주기2. 2 차원 배열과 포인터3. 문자열과 포인터4. 구조체와 포인터
0. TIP
짧은 팁 :
(*&) 또는 (&*) 는 상쇄되어 사라집니다 .
int main(void) { int a = 4; int *p = &a; printf("%d %d\n", *&a, a); printf("%p %p\n", &*p, p);}
이중 포인터 다시 보기
int x = 10;int *ptr = &x;int **pptr = &ptr;
이중 포인터 다시 보기
/
- * 는 연속해서 올 수 있지만 & 는 안 됩니다 .- 이것보다는 그림이 더 명확합니다 .
int x = 10;int *ptr = &x;int **pptr = &ptr;
/*1) pptr = &ptr, ptr = &x 2) pptr = &ptr = &&x ( 아님 ) 2) *pptr = *(&ptr) = ptr3) **pptr = **(&ptr) = *ptr = *(&x) = x = 10*/
배열과 포인터의 차이점
arr = &arr[0] = &*(arr +0) = arr 입니다 .이 때 arr 은 읽기 전용입니다 !
int arr[] = {0, 1, 2, 3, 4};int *ptr = arr;ptr = ptr + 1; //ok, *ptr = 1;arr = arr + 1; //error
1. 함수에 배열을 건네주기
예제 ) 크기가 n 인 int 배열에 0 ~ n – 1 까지 값을 초기화하는 함수를 작성하고 테스트하시오 .
예제 ) 크기가 n 인 int 배열에 0 ~ n – 1 까지값을 초기화하는 함수를 작성하고 테스트하시오 .
void setArray(int array[], int n) {}
int main(void) {int arr[10];setArray(arr, 10);for( int i = 0; i < 10; i++)
printf(“%d\n”, arr[i]);return 0;
}
배열과 포인터는 다릅니다 .int *a; 와 int a[]; 는 서로 다른 문장인데딱 한 경우에는 완전히 같습니다 .
언제 ?
int *a; 와 int a[]; 는 서로 다른 문장이지만parameter 안에서는 같습니다 .
void foo(int *a)= void foo(int a[])= void foo(int a[10])
마지막 줄의 숫자는 아무 의미가 없습니다 . 무시됩니다 .
1 차원 배열은 배열이 아니라 포인터로 넘겨주기 때문에
1) 자동으로 Call by Reference 가 된다 .2) 배열의 크기를 알 수 없다 .
2 의 이유로 C 언어에서는 배열의 크기를반드시 따로 전달해야 합니다 .
예제 ) 크기가 n 인 배열에 0 ~ n – 1 까지 값을 초기화하는 함수를 작성하고 테스트하시오 .
예제 ) 크기가 n 인 int 배열에 0 ~ n – 1 까지 값을 초기화하는 함수를 작성하고 테스트하시오 .
void setArray(int *array, int n) {for( int i = 0; i < n; i++)
array[i] = i;}
int main(void) {int arr[10];setArray(arr, 10);for( int i = 0; i < 10; i++)
printf(“%d\n”, arr[i]);return 0;
}
예제 ) 크기가 n 인 배열을 동적 할당으로 생성하고0 ~ n – 1 까지 값을 초기화하는 함수를 작성하고 테스트하시오 .
예제 ) 크기가 n 인 배열을 동적 할당으로 생성하고0 ~ n – 1 까지 값을 초기화하는 함수를 작성하고 테스트하시오 .
*array[i] 라고 하면 어떻게 될까요 ?
void setArray(int **array, int n) {*array = calloc(n, sizeof(int)); for( int i = 0; i < n; i++)
(*array)[i] = i;}
int main(void) {int *ptr;setArray(&ptr, 10);for( int i = 0; i < 10; i++)
printf(“%d\n”, (*ptr)[i]);return 0;
}
2. 2 차원 배열과 포인터
1. 메모리는 1 차원인데 2 차원 배열을 어떻게 저장할까요 ?
왜 00, 01, 02, 10, 11, 12 순서로 접근할까요 ? 00, 10, 01, 11, 02, 12 순서도 상관없지 않나요 ?
int arr[2][3] = { { 0, 1, 2 }, { 3, 4, 5 } };
int main(void) {int arr[2][3] = { { 0, 1, 2 },{ 3, 4, 5 } };for (int i = 0; i < 2; i++)
for (int j = 0; j < 3; j++) printf("%p\n", &arr[i][j]);
}
arr[m][n] 배열을 1 차원 포인터로 캐스팅하면
arr[m][n]; //m * n 배열
int *ptr = (int *) arr;
라면…
arr[i][j]= *(ptr + i * n + j)
예제 ) 2 차원 배열과 단일 포인터
int main(void) {int arr[2][3] = { { 0, 1, 2 },{ 3, 4, 5 } };// int *ptr = arr; warning!!int *ptr = (int *) arr;for (int i = 0; i < 2; i++){
for (int j = 0; j < 3; j++) {printf("%d ", *(ptr + i * 3 + j));
}printf("\n");
}}
앞의 예제에서 알 수 있는 것처럼이차원 배열과 단일 포인터는 서로 다른 타입입니다 .그럼 이차원 배열의 이름은 어떤 타입의 주소일까요 ?
int
조금 복잡하지만 - ptr 변수는 int 3 개짜리 배열의 포인터입니다 .-이차원 배열은 1 차원 배열의 배열이다 .
int arr[2][3] = { { 0, 1, 2 }, { 3, 4, 5 } };int (*ptr)[3] = arr; //ok
예제 ) 2 차원 배열과 배열의 포인터
int main(void) {int arr[2][3] = { { 0, 1, 2 }, { 3, 4, 5 } };for (int i = 0; i < 2; i++){
for (int j = 0; j < 3; j++) {printf("%d ", *(*(arr + i) + j));
}printf("\n");
}}
arr[i][j]= (*(arr+ i))[j]= *(*(arr +i) + j)
원리는 이런데 쓸모는 없습니다 .
함수로 이차원 배열을 전달하려면
1. 단일 포인터로 캐스팅해서 전달 또는2. 배열의 포인터로 전달
두 가지 방법이 있습니다 .
예제 )n * 5 이차원 배열을 엣지있게 출력하는 함수를 작성하세요 .
void print2d_arr(int(*arr)[5], int w) {for (int i = 0; i < w; i++){
for (int j = 0; j < 5; j++) {printf("%d ", arr[i][j]);
}printf("\n");
}}int main(void) {
int arr[3][5] = { { 0, 1, 2, 3, 4 }, { 5, 6, 7 }, { 8, 9 } };
print2d_arr(arr, 3);}
3. 문자열과 포인터
문자열은 그냥 문자의 1 차원 배열이예요 .
int main(void) {char a[] = “Hello, world”;printf(“%s\n”, a);return 0;
}
문자열의 끝은 null 문자 (\0) 으로 끝나야 합니다 .
int main(void) {char a[20];//a = “Hi”; //wrong//a[0] = “H”; //wronga[0] = ‘H’;a[1] = ‘i’;a[2] = ‘\0’;printf(“%s\n”, a);
}
문자열 관련 함수
문자열을 복사하는 함수 : strcpy()문자열을 이어주는 함수 : strcat()문자열을 개수를 세는 함수 : strlen()
다양한 함수가 있습니다 .
예제 )문자열을 복사하기 위해 필요한 공간만큼동적 할당을 하고 복사를 하는 함수를 만들어 봅시다 .int strcpy(char **src, const char *str);
#include <stdio.h>#include <stdlib.h>#include <string.h>#pragma warning(disable:4996)
void mystrcpy(char **src, const char* str) {*src = calloc(sizeof(char), strlen(str) + 1);strcpy(*src, str);
}
int main(void) {char *s;mystrcpy(&s, "Hello");printf("%s\n", s);
}
아래 두 개는 어떤 차이일까요 ?
문자열이 가변 길이이므로 위처럼 포인터의 배열의 되어야 합니다 .
아래는 에러입니다 .
char *strings[3] = { “Hello”, “world”, “Hoo” };char (*strings)[10] = { “Hello”, “world”, “Hoo”}; //error
구조체와 구조체의 포인터는 동영상 강의를 참고하세요 .
스탠포드에서 제작한 포인터와 메모리 / 링크드 리스트 문서를 읽으면 도움이 많이 됩니다 .
Thank You