Kim Seon Deok
배열 & 포인터 본문
배열의 선언 및 초기화
둘 이상의 변수를 모아 놓은 것
다수의 데이터를 저장하고 처리하는 경우 유용하게 사용할 수 있는 것
배열 선언에 필요한 것
- 배열 이름
- 자료형
- 길이 정보
배열의 위치정보를 명시하는 인덱스 값은 1이 아닌 0부터 시작
int arr1[5]; // 길이가 5인 1차원 배열
int arr2[3][4]; // 세로 3, 가로 4 인 2차원 배열
int arr3[3][4][5]; // 깊이 3, 세로 4, 가로 5인 3차원 배열
int arr4[] = {1,2,3,4,5,6,7} // 배열 선언 및 초기화
len = sizeof(arr4) / sizeof(int) // 배열 arr4의 길이 계산
배열의 크기 → sizeof(arr) → 바이트 단위의 배열 크기
배열의 길이 → sizeof(배열) / sizeof(자료형)
배열을 이용한 문자열 변수 표현
배열을 사용해 문자열을 저장할 수 있다.
문자열 저장을 목적으로 char형 배열을 선언할 땐 특수문자 '\0'이 맨끝에 붙어 배열의 길이는 문자열 길이 + 1이 된다.
'\0' : NULL문자 ≠ 공백
NULL문자의 아스키코드값은 0이고 공백문자의 아스키코드값은 32이다.
NULL문자는 문자열의 끝을 나타내주는 중요한 역할을 한다.
scanf("%d", &num); // 정수를 입력받음
scanf("%s", str); // s는 문자열 서식문자. str은 문자열이 저장될 배열
scanf함수 호출 시 데이터를 저장할 변수 이름 앞에는 &연산자를 붙여주어야 한다.
scanf : 사용자로부터 값을 입력받아서 변수에 그 값을 채우는 역할
그러기 위해선 변수의 주소값을 알아야 하므로 &를 붙이는 것이다. → call by reference형태의 함수호출
하지만 문자열을 입력 받는 배열의 이름 앞에는 &연산자를 붙이지 않는다. → 입력받은 문자열에도 역시 마찬가지로 맨 끝에 null문자가 삽입된다. → 문자열은 그 자체로 배열의 주소값이므로 & 붙이지 않는다.
포인터란?
포인터를 사용하면 메모리에 직접 접근이 가능하다.
메모리에 주소값을 저장하는 이유 ? → 주소값을 출력 하기 위해 & 주소값을 이용한 메모리에 접근(*)하기 위해
메모리 주소값은 1씩 증가하며, 1바이트 메모리 공간을 단위로 하나의 주소값이 할당된다.
int num = 10;
int *ptr = # // 포인터 변수의 선언과 동시에 초기화
int *pnum; // 포인터 변수 선언
pnum = &num //num의 주소값을 포인터 변수에 저장
포인터 변수란 메모리 주소값을 저장하기 위한 변수이다.
특정 변수의 메모리 공간에 대한 정보를 담는다.
포인터는 변수 형태의 포인터와 상수 형태의 포인터를 뜻한다.
& : 피연산자의 주소 값을 반환하는 연산자.
* : 포인터가 가리키는 메모리 공간에 접근할 때 사용하는 연산자.
포인터 변수의 크기 = 시스템 주소값 크기
32비트 시스템 → 주소값 크기 32비트 → 포인터 변수 크기 32비트
64비트 시스템 → 주소값 크기 64비트 → 포인터 변수 크기 64비트
int * pnum1 ; // int형 변수를 가리키는 pnum1
double * pnum2 ; // double형 변수를 가리키는 pnum2
unsigned int * pnum3 ; // unsigned int형 변수를 가리키는 pnum3
포인터 변수는 해당 type형 변수의 주소값을 저장한다. → 포인터 변수의 선언형태만 보고도 이 포인터가 현재 어떤 자료형의 변수를 가리키는 지 알 수 있다.
포인터 형 → int * , char * , double * 등 → 포인터 변수가 가리키는 변수의 자료형 정보를 담음
int num1 = 100, num2 = 100;
int *pnum;
pnum = &num1; // pnum이 num1을 가리킴
*pnum += 30; // pnum값 변경 → num1값 또한 변경됨
pnum = &num2; // pnum이 num2를 가리킴
*pnum -= 30; // pnum값 변경 → num2값 또한 변경됨
포인터 변수에 저장된 값이 바뀌면 포인터 변수가 가리키는 변수가 바뀐 것이다.
포인터와 배열의 관계
배열의 이름 = 포인터. 단 값을 바꿀 수 없는 상수형태의 포인터이다.
int arr[3] = {0,1,2};
printf("%p \n", arr); // 배열의 이름
printf("%p \n", arr[0]); // 첫번 째 요소
printf("%p \n", arr[1]); // 두번 째 요소
printf("%p \n", arr[2]); // 세번 째 요소
배열의 이름은 배열의 시작주소 값을 의미하고, 값의 저장이 불가능한 상수이다.
포인터 변수는 말 그대로 변수지만, 배열의 이름은 가리키는 대상의 변경이 불가능한 상수이다.
포인터
- 변수 형태의 포인터
- 상수 형태의 포인터
포인터 변수 | 배열의 이름 | |
이름 존재 유무 | 존재함 | 존재함 |
무엇을 나타내거나 저장하는가 | 메모리의 주소값 | 메모리의 주소 값 |
주소값의 변경 가능한가 | 가능 | 불가능 |
int arr[3] = {15,25,35};
int * ptr = &arr[0]; // int * ptr = arr;
printf("%d %d \n", ptr[0], arr[0); // 15 15
printf("%d %d \n", ptr[1], arr[1]); // 25 25
printf("%d %d \n", ptr[2], arr[2]); // 35 35
printf("%d %d \n", *ptr, *arr); // 15 15
포인터 연산
int형 포인터를 대상으로 1을 증가시키면 주소값 4증가, double형 포인터를 대상으로 1을 증가시키면 주소값 8 증가한다.
int arr = {11,22,33};
int * ptr = arr; // int * ptr = &arr[0]과 같음
printf(""%d %d %d \ n", *ptr, *(ptr+1), *(ptr+2)); // 11 22 33
*ptr, *(ptr + 1), *(ptr + 2) = arr[0], arr[1], arr[2] = *(arr + 0), *(arr + 1), *(arr + 2)
arr[i] == *(arr+i)
상수형태의 문자열을 가리키는 포인터
문자열의 선언방식
- 배열을 이용한 방식
- char형 포인터 변수 이용하는 방식
char str1[] = "My String"; //배열 기반 문자열 선언 >> 변수 형태의 문자열
char * str2 = "Your String!" // 포인터 기반 문자열 선언 >> 상수 형태의 문자열
상수 형태의 문자열 → 포인터 기반 문자열 선언의 경우 문자열의 첫번째 문자의 주소값이 포인터변수 str2에 저장된다. → 포인터변수 str2가 가리키는 문자열은 내용 변경이 불가능하다.
포인터 배열
포인터 변수로 이루어진 주소값을 저장하는 배열이다.
int num1 = 10, num2 = 20, num3 = 30;
int *arr[3] = {&num1, &num2, &num3};
printf("%d \n", *arr[0]); // 10
printf("%d \n", *arr[1]); // 20
printf("%d \n", *arr[2]); // 30
char * strArr[3] = {"Simple", "String", "Array"};
printf("%s \n", strArr[0]); // Simple
printf("%s \n", strArr[1]); // String
printf("%s \n", strArr[2]); // Array
문자열은 그 자체로 배열의 주소값이므로 문자열 그대로 출력된다.
call by value : 함수를 호출할 때 단순이 값을 전달하는 형태의 함수호출
call by reference : 메모리의 접근에 사용되는 주소값을 전달하는 형태의 함수호출 → scanf
void Swap(int n1, int n2)
{
int temp = n1;
n1 = n2;
n2 = temp;
}
int main(void)
{
int num1 = 10, num2 = 20;
Swap(num1,num2);
printf("%d %d \n", num1,num2); // 실제 num1,num2값 바뀌지 않음
return 0;
}
Swap함수 선언 시 일시적으로 num1,num2값 바뀜
void Swap(int *ptr1, int *ptr2)
{
int temp = *ptr1;
*ptr1 = *ptr2;
*ptr2 = temp;
}
int main(void)
{
int num1 = 10, num2 = 20;
Swap(&num1, &num2);
printf("%d %d \n", num1,num2); // 실제 num1,num2값 바뀜
return 0;
}
Swap함수 선언하면 영구적으로 num1,num2값 변경
'CC++' 카테고리의 다른 글
[C++] 기초적인 사용법 (0) | 2022.11.22 |
---|