728x90
728x90
배열이름은 첫 번째 요소의 주소값을 나타낸다
#include <stdio.h>
int main()
{
int a[5] = {0,1,2,3,4};
printf("%d, %d \n", a[0], a[1]);
printf("%d 번지, %d 번지 \n", &a[0], &a[1]);
printf("배열 이름 : %d \n", a);
return 0;
}
배열 이름 vs 포인터
포인터 = 주소값 + 자료형
배열 이름도 포인터다. 상수 포인터라고 한다.
공통점은 이름이 있는 것, 메모리의 주소를 나타내는 것
차이점은 배열이름은 상수, 포인터는 변수라는 것
배열 이름은 상수다
#include <stdio.h>
int main()
{
int a[5] = {0,1,2,3,4};
int b = 10;
a = &b; //a는 상수이므로 오류. 변수였다면 가능
return 0;
}
a가 상수인 이유?
a 배열 생성과 동시에 첫번째 요소(0x10등의 메모리 주소)를 가리키고,
그것을 a 배열이름으로 하고 소멸 전까지 가리킨다. 즉 상수다.
그래서 상수적 특성을 지닌 포인터다.
배열 이름의 타입 결정짓는 요령?
배열 이름도 포인터라 타입이 있다.
배열 이름이 가리키는 배열 요소에 의해 결정된다.
배열 이름을 포인터처럼, 포인터를 배열이름처럼 활용?
#include <stdio.h>
int main()
{
int arr[3] = {0, 1, 2};
// arr 배열이름은 포인터다
//배열이름의 자료형정보는 배열이름이 가리키는 요소형 자료형과 같다
int *ptr;
int val = 10;
ptr = arr;
// 양측 타입이 같다
// ptr은 변수라 대입 가능
// 배열이름과 포인터는 변수,상수 여부를 빼면 큰 차이가 없다
// 그러나 ptr은 변수, arr은 상수
printf("%d, %d, %d \n", ptr[0], ptr[1], ptr[2]);
// arr[0]과 ptr[0]의 결과는 같다
printf("%d, %d, %d \n", arr[0], arr[1], arr[2]);
ptr = &val;
printf("%d \n", *ptr); //ptr이 가리키는 변수 출력
return 0;
}
포인터 연산 : 포인터가 지닌 값을 증가/감소시키는 연산
포인터가 가리키는 대상의 자료형에 따라서 증가, 감소되는 값이 차이를 보인다.
int* arr1; //arr1을 참조하니 4바이트 메모리공간을 참조한다.
주소값이 1만 증가하지 않고, 포인터의 타입(자료형)에 따라 차이가 있다.
포인터 연산 설명을 위한 예로 실제로 이렇게 사용 ㄴㄴ
#include <stdio.h>
int main()
{
int* ptr1 = 0; //null포인터 : 아무것도 가리키지 않
char* ptr2 = 0;
double* ptr3 = 0;
printf("%d, %d, %d \n", ptr1++, ptr2++, ptr3++); //선연산 후증가
printf("%d, %d, %d \n", ptr1, ptr2, ptr3); //자료형의 값만큼 증가된다
printf("%d, %d, %d \n", ptr1--, ptr2--, ptr3--); //감소
printf("%d, %d, %d \n", ptr1, ptr2, ptr3);
return 0;
}
포인터 연산을 통한 배열 요소의 접근
#include <stdio.h>
int main()
{
int arr[5] = {1,2,3,4,5};
// 배열이름은 첫번째 요소를 가리킨다
int* pArr = arr; // int 형으로 양측이 같다..arr첫 요소를 가리킨다
printf("%d \n", *pArr);
printf("%d \n", *(++pArr)); // 타입에 따라 int 형 값만큼 증가 (4바이트를 건너뛴다)
printf("%d \n", *(++pArr));
printf("%d \n", *(pArr+1)); // pArr의 값 자체는 그대로
printf("%d \n", *(pArr+2));
printf("%d \n", *(++pArr));
return 0;
}
중대한 결론
#include <stdio.h>
int main()
{
int arr[2] = {1,2};
int* pArr=arr; //가리키는 요소가 int라 자료형도 int
// 배열이름을 통한 출력
printf("%d, %d\n", arr[0], *(arr+1)); //int의 포인터형이라는 정보로 4바이트를 건너뜀
// printf("%d, %d\n", *(arr+0), arr[1]); //같은 결과
// 포인터 변수를 통한 출력
printf("%d, %d\n", pArr[0], *(pArr+1)); // 포인터로도 배열의 인덱스연산이 가능
// *(pArr + 0) == *pArr == pArr[0];
// arr[1] == *(arr+1);
// 즉 arr[i] == *(arr+i);
return 0;
}
arr[i] == *(arr+i);
//arr이 포인터거나 배열이름인 경우
문자열 표현 방식의 종류
- 배열 기반의 문자열변수
- 포인터 기반의 문자열 상수
char str1[5] = "abcd";
char *str2 = "ABCD";
큰따옴표로 표현되는 문자열은 상수다..
printf ("abcd");의 경우 문자열이 아니라 올라간 메모리공간의 주소값이 인자로 전달되는 것
#include <stdio.h>
int main()
{
char str1[5] = "abcd";
char *str2 = "ABCD";
printf("%s\n", str1);
printf("%s\n", str2);
str1[0] = 'x'; //가능
str2[0] = 'x'; //상수라서 변경불가능, 에러
// 에러 나지는 않는데 무시되고 정지..
//*(str2+0) = 'x'; //역시 안됨
printf("%s\n", str1);
printf("%s\n", str2);
printf("%d\n", *(str2+0)); //int값 반환
printf("%d\n", str2[0]); //int값 반환
return 0;
}
포인터 배열 : 배열의 요소로 포인터를 지니는 배열
int* arr1[10];
#include <stdio.h>
int main()
{
int a= 10, b=20, c=30;
int* arr[3] = {&a, &b, &c};
printf("%d\n", *arr[0]); // arr 0번째 공간이 가리키는 메모리공간을 참조
return 0;
}
모든 문자열은 선언과 동시에 메모리공간에 올라가고 그 자리에 문자열의 주소값이 리턴
#include <stdio.h>
int main()
{
// 캐릭터형 포인터 3개가 묶여서 형성된 배열
// 캐릭터형 변수에 주소값 3개가 저장
// ** 모든 문자열은 선언과 동시에 메모리공간에 올라가고 그 자리에 문자열의 주소값이 리턴된다 **
char* arr[3] = {"Fervent-lecture", "TCP/IP", "Socket Programming"};
//char* arr[3] = {0x1000, 0x2000, 0x3000};
printf("%s\n", arr[0]); // F부터 저장
printf("%s\n", arr[1]); // T~
printf("%s\n", arr[2]); // S~
return 0;
}
728x90
728x90
'C, C++ > 열혈 C 프로그래밍' 카테고리의 다른 글
열혈 C 17장 포인터의 포인터 (0) | 2021.09.07 |
---|---|
열혈 C 16장 다차원 배열 (0) | 2021.09.06 |
열혈 C 14장 포인터와 함수에 대한 이해 (0) | 2021.09.03 |
열혈 C 12장 포인터 (0) | 2021.09.02 |
열혈 C 11장 1차원배열 (0) | 2021.09.01 |