Kim Seon Deok

배열 & 포인터 본문

CC++

배열 & 포인터

seondeok 2022. 11. 25. 03:00

 

 

배열의 선언 및 초기화

둘 이상의 변수를 모아 놓은 것

다수의 데이터를 저장하고 처리하는 경우 유용하게 사용할 수 있는 것

배열 선언에 필요한 것

  • 배열 이름
  • 자료형
  • 길이 정보

배열의 위치정보를 명시하는 인덱스 값은 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
Comments