3차원 배열은 2차원 배열에서 높이의 개념이 추가된 배열이다. 3차원 배열은 다음과 같이 높이. 세로, 가로의 길이를 순서대로 선언한다.

int arr[2][3][4];	// 높이2, 세로3, 가로4

sizeof 연산을 이용하여 3차원 배열의 크기를 확인해보면 int 자료형의 크기 x 높이 x 세로 x 가로로 직육면체 형태의 배열임을 알 수 있다.

#include <stdio.h>

int main(void)
{
    int arr[2][3][4];
    printf("3차원 배열의 크기 : %d\n", sizeof(arr));
    return 0;
}
// output : 3차원 배열의 크기 : 96

 

3차원 배열은 다음과 같이 선언하고 접근한다.

#include <stdio.h>

int main(void)
{
    int sum = 0;
    int arr[3][3][2] = {
        {
            {1,2},
            {3,4},
            {5,6}
        },
        {
            {7,8},
            {9,10},
            {11,12}
        },
        {
            {13,14},
            {15,16},
            {17,18}
        }
    };

    for(int i = 0; i < 3; i++)
    {
        for(int j = 0; j < 2; j++)
        {
            sum += arr[0][i][j];
        }
    }
    printf("첫번째 면 모든 값의 합 : %d\n",sum);
    sum = 0;

    for(int i = 0; i < 3; i++)
    {
        for(int j = 0; j < 2; j++)
        {
            sum += arr[2][i][j];
        }
    }
    printf("세번째 면 모든 값의 합 : %d\n",sum);

    return 0;
}
// output : 
// 첫번째 면 모든 값의 합 : 21
// 세번째 면 모든 값의 합 : 93

3차원 배열은 2차원 배열의 형태를 갖는 여러개의 면이 겹쳐져 있는 형태이다.

'Language > C, C++' 카테고리의 다른 글

[C] 삼중 포인터  (0) 2020.12.28
[C] 더블 포인터  (0) 2020.12.28
[C] 2차원 배열  (0) 2020.12.24
[C] 포인터에서 const 사용  (0) 2020.12.20
[C] Call - by - value, Call - by - reference  (0) 2020.12.20

배열을 통째로 함수의 인자로 전달하는 것은 불가능하다. 그러나 배열을 함수의 인자로 전달하면 배열 시작점의 주소값이 전달 되기 때문에 함수의 매개변수를 포인터 변수로 선언하면 포인터 변수를 이용하여 배열에 접근할 수 있다.

#include <stdio.h>

void ShowArrayElem(int * param, int len)
{
    for(int i = 0; i<len; i++){
        printf("%d ", param[i]);
    }
    printf("\n");
}

int main(void)
{
    int arr1[] = {1,2,3};
    int arr2[] = {4,5,6,7,8};
    ShowArrayElem(arr1, sizeof(arr1)/4);
    ShowArrayElem(arr2, sizeof(arr2)/4);
    return 0;
}

/* output : 
1 2 3 
4 5 6 7 8
*/

 

#include <stdio.h>

void ShowArrayElem(int * param, int len)
{
    for(int i = 0; i<len; i++){
        printf("%d ", param[i]);
    }
    printf("\n");
}

void AddArrayElem(int * param, int len, int add)
{
    for(int i = 0; i < len; i++)
    {
        param[i] += add;
    }
}

int main(void)
{
    int arr[3] = {1,2,3};
    AddArrayElem(arr, sizeof(arr)/4, 1);
    ShowArrayElem(arr, sizeof(arr)/4);

    AddArrayElem(arr, sizeof(arr)/4, 2);
    ShowArrayElem(arr, sizeof(arr)/4);
    return 0;
}
/* output : 
2 3 4 
4 5 6
*/

위 코드와 같이 주소 값만 알면 배열에 저장된 값의 변경도 가능하다.

 

배열을 함수의 인자로 전달받을 때는 다음과 같은 선언도 가능하다. int * param과 동일한 의미이다.

void ShowArrayElem(int param[], int len)

 

'Language > C, C++' 카테고리의 다른 글

[C] 포인터에서 const 사용  (0) 2020.12.20
[C] Call - by - value, Call - by - reference  (0) 2020.12.20
[C] 포인터 배열  (0) 2020.12.19
[C] 문자열 포인터  (0) 2020.12.18
[C] 포인터 연산  (0) 2020.12.17

포인터 변수로 이루어져서 주소 값의 저장이 가능한 배열을 포인터 배열이라고 한다. 포인터 배열은 다음과 같이 선언한다. 

int *arr1[20];	// 길이가 20인 int형 포인터 배열
double *arr2[30];	// 길이가 30인 double형 포인터 배열

포인터 배열의 선언은 기본 자료형 배열의 선언과 비슷하다.

 

#include <stdio.h>

int main(void)
{
    int num1=10, num2=20, num3=30;
    int *arr[3] = {&num1,&num2,&num3};

    printf("%d\n", *arr[0]);
    printf("%d\n", *arr[1]);
    printf("%d\n", *arr[2]);
    return 0;
}
/* output : 
10
20
30
*/

위 코드와 같이 배열과 비슷하게 선언하지만 포인터 배열은 주소값을 저장할 수 있고 주소값으로 접근할 수 있다.

 

다음과 같이 문자열도 포인터 배열로 저장할 수 있다.

#include <stdio.h>

int main(void)
{
    char *strArr[3] = {"simple", "string", "array"};
    printf("%s\n", strArr[0]);
    printf("%s\n", strArr[1]);
    printf("%s\n", strArr[2]);
    return 0;
}
/* output :
simple
string
array
*/

'Language > C, C++' 카테고리의 다른 글

[C] Call - by - value, Call - by - reference  (0) 2020.12.20
[C] 함수 인자로 배열 전달  (0) 2020.12.20
[C] 문자열 포인터  (0) 2020.12.18
[C] 포인터 연산  (0) 2020.12.17
[C] 포인터와 배열  (0) 2020.12.17

다음과 같이 포인터를 기반으로 문자열을 선언하는 것이 가능하다.

char *str = "My String";

이렇게 선언을 하면 메모리 공간에 "My String"이 저장되고, 문자열의 첫 번째 문자 M의 주소 값이 반환되어 포인터 변수 str에 저장된다. 배열로 선언한 문자열의 경우 계속해서 그 문자열을 가리키지만, 포인터로 선언한 문자열은 다음과 같이 다른 위치를 가리키도록 할 수 있다.

int main(void)
{
    char *str = "My String";
    str = "Your String";	// str이 가리키는 대상을 변경
}

배열로 선언된 문자열은 값의 변경이 가능하기 때문에 변수 형태의 문자열 이라 하고,  포인터로 선언된 문자열은 값이 변경이 불가능하여 상수 형태의 문자열 이라 한다.

 

#include <stdio.h>

int main(void)
{
    char str1[] = "My String";
    char *str2 = "Your String";
    printf("%s %s\n", str1, str2);

    str2 = "Our String";    // 가리키는 대상 변경
    printf("%s %s\n", str1, str2);

    str1[0] = 'X';      // 정상적으로 변경됨
    //str2[0] = 'X';    // 컴파일에서 에러 발생
    printf("%s %s\n", str1, str2);
    return 0;
}

위 코드와 같이 포인터로 선언한 문자열의 값을 변경하려 할때 컴파일이 정상적으로 안되는것을 확인할 수 있다.

 

'Language > C, C++' 카테고리의 다른 글

[C] 함수 인자로 배열 전달  (0) 2020.12.20
[C] 포인터 배열  (0) 2020.12.19
[C] 포인터 연산  (0) 2020.12.17
[C] 포인터와 배열  (0) 2020.12.17
[C] 포인터 변수  (0) 2020.12.16

포인터 변수를 대상으로도 증가 및 감소 연산이 가능하다.

#include <stdio.h>

int main(void)
{
    int * ptr1 = 0x0010;
    double * ptr2 = 0x0010;

    printf("%p %p\n", ptr1+1, ptr1+2);  // 4증가, 8증가
    printf("%p %p\n", ptr2+1, ptr2+2);  // 8증가, 16증가

    printf("%p %p\n", ptr1, ptr2);
    ptr1++;
    ptr2++;
    printf("%p %p\n", ptr1, ptr2);
    return 0;
}
/* output: 
00000014 00000018
00000018 00000020
00000010 00000010
00000014 00000018
*/

위 코드의 결과값을 보면 int형 포인터를 대상으로 1증가 시키면 4가 증가하고, double형 포인터를 대상으로 1증가시키면 8 이 증가한다. 포인터의 증감연산은 n 크기 만큼 증가 및 감소시 n x (자료형의 크기)만큼 주소값이 증가 및 감소함을 알 수 있다. 

 

포인터 연산을 활용하여 다음과 같이 배열의 요소에 접근할 수 있다.

int main(void)
{
    int arr[] = {1,2,3};
    int *ptr = arr;
    
    printf("%d\n", *(ptr+1));	// 2
    return 0;
}

 

'Language > C, C++' 카테고리의 다른 글

[C] 포인터 배열  (0) 2020.12.19
[C] 문자열 포인터  (0) 2020.12.18
[C] 포인터와 배열  (0) 2020.12.17
[C] 포인터 변수  (0) 2020.12.16
[C] 1차원 배열(2)  (0) 2020.12.14

배열의 이름은 값을 바꿀 수 없는 상수 형태의 포인터 이다.

#include <stdio.h>

int main(void)
{
    int arr[] = {0,1,2};
    printf("배열의 이름 : %p\n", arr);
    printf("첫 번째 요소 : %p\n",&arr[0]);
    printf("두 번째 요소 : %p\n",&arr[1]);
    printf("세 번째 요소 : %p\n",&arr[2]);
    return 0;
}
/* output : 
배열의 이름 : 0061FF14
첫 번째 요소 : 0061FF14
두 번째 요소 : 0061FF18
세 번째 요소 : 0061FF1C
*/

int형 배열의 요소간 주소 값의 차는 4바이트 인것을 확인할 수 있다. 또한 모든 배열 요소는 메모리 공간에 나란히 할당됨을 알 수 있다. 배열의 이름은 배열의 시작 주소 값을 의미하고, 그 형태는 값의 저장이 불가한 상수이다. 

 

배열의 이름도 포인터이기 때문에 배열의 이름을 피연산자로 하는  * 연산이 가능하다.

#include <stdio.h>

int main(void)
{
    int arr1[] = {1,2,3};
    double arr2[] = {1.1,2.2,3.3};

    printf("%d %g\n", *arr1, *arr2);
    *arr1 += 100;
    *arr2 += 120.5;
    printf("%d %g\n", *arr1, *arr2);
    return 0;
}
/* output: 
1 1.1
101 121.6
*/

배열의 이름이 가리키는 것은 배열의 첫번째 요소이기 때문에 배열의 이름을 대상으로 *연산을 하면 배열의 첫번째 요소에 접근된다.

 

#include <stdio.h>

int main(void)
{
    int arr[] = {10,20,30};
    int *ptr = &arr[0];

    printf("%d %d\n", ptr[0], arr[0]);
    printf("%d %d\n", ptr[1], arr[1]);
    printf("%d %d\n", ptr[2], arr[2]);
    return 0;
}
/* output : 
10 10
20 20
30 30
*/

위 코드와 같이 포인터를 배열의 이름처럼 사용할 수도 있다.

'Language > C, C++' 카테고리의 다른 글

[C] 문자열 포인터  (0) 2020.12.18
[C] 포인터 연산  (0) 2020.12.17
[C] 포인터 변수  (0) 2020.12.16
[C] 1차원 배열(2)  (0) 2020.12.14
[C] 1차원 배열(1)  (0) 2020.12.12

배열은 일반적인 변수와 다르게 여러 개의 값을 저장할 수 있다. 여러 개의 변수가 모여서 배열을 이룬다.

배열은 다음과 같이 선언할 수 있다.

int arr[4];

위 코드에는 배열을 이루는 요소의 자료형, 배열의 이름, 배열의 길이 이다. 따라서 위 코드의 의미는 'int형 변수 4개로 이뤄진 arr이라는 이름을 갖는 배열을 선언한다.' 이다. 이 형식을 갖추어 다양한 자료형과 다양한 길이의 배열을 선언할 수 있다.

 

배열은 다음과 같이 배열 이름 뒤의 대괄호([]) 안의 인덱스 값으로 접근할 수 있다. 인덱스 값은 0부터 시작한다. 배열의 길이가 3일 경우 인덱스 값은 2까지 있다.

#include <stdio.h>

int main(void)
{
    int arr[3];
    int sum = 0;

    arr[0] = 10, arr[1] = 30, arr[2] = 20;

    for(int i = 0; i < 3; i++)
        sum += arr[i];
    
    printf("배열 요소에 저장된 값들의 합 : %d\n", sum);
    return 0;
}

//output : 배열 요소에 저장된 값들의 합 : 60

위 코드는 크기가 3인 배열에 값들을 저장하여 배열의 값들의 합을 구하는 코드이다. 배열의 모든 요소는 반복문을 활용하여 순차적으로 접근 가능하다는 것을 알 수 있다.

 

배열도 기본 자료형 변수들과 마찬가지로 선언과 동시에 초기화하는 것이 가능하다.

다음 코드와 같이 중괄호 내에 초기화 할 값들을 나열하면 해당 값들이 순서대로 저장된다.

int arr[5] = {1,2,3,4,5};

위와 같이 초기화 리스트가 사용된 경우 배열의 길이정보를 생략할 수 있다. 

int arr[] = {1,2,3,4,5};

위 코드의 경우 배열의 길이정보 5가 자동으로 채워진다.

int arr[5] = {1,2};

위 코드의 경우 배열의 길이는 5이지만 초기화할 값은 2개밖에 존재하지 않는다. 위와 같은 경우 순차적으로 값을 채우고 채울 값이 존재하지 않는 요소들은 0으로 채워진다. 위의 경우 배열의 값은 1,2,0,0,0 과 같다.

 

#include <stdio.h>

int main(void)
{
    int arr1[5] = {1,2,3,4,5};
    int arr2[ ] = {1,2,3,4,5,6,7};
    int arr3[5] = {1,2};

    printf("arr1의 크기 : %d\n", sizeof(arr1));
    printf("arr2의 크기 : %d\n", sizeof(arr2));
    printf("arr3의 크기 : %d\n", sizeof(arr3));

    int ar1Len = sizeof(arr1) / sizeof(int);
    int ar2Len = sizeof(arr2) / sizeof(int);
    int ar3Len = sizeof(arr3) / sizeof(int);

    for(int i = 0; i<ar1Len; i++)
        printf("%d ", arr1[i]);
    printf("\n");
    for(int i = 0; i<ar2Len; i++)
        printf("%d ", arr2[i]);
    printf("\n");
    for(int i = 0; i<ar3Len; i++)
        printf("%d ", arr3[i]);
    printf("\n");

    return 0;
}
/* output : 
arr1의 크기 : 20
arr2의 크기 : 28
arr3의 크기 : 20
1 2 3 4 5       
1 2 3 4 5 6 7   
1 2 0 0 0
*/

sizeof로 배열의 크기를 반환하면 바이트 단위로 반환된다. 따라서 배열의 길이를 계산하려면 int 바이트수만큼 나눠줘야 한다.

'Language > C, C++' 카테고리의 다른 글

[C] 포인터 변수  (0) 2020.12.16
[C] 1차원 배열(2)  (0) 2020.12.14
[C] 재귀함수  (0) 2020.12.10
[C] register 변수  (0) 2020.12.10
[C] static 변수  (0) 2020.12.10

+ Recent posts