문자 출력 함수

모니터에 하나의 문자를 출력할 때 일반적으로 사용하는 함수는 putchar() 과 fputc()가 있다.

#include <stdio.h>
int putchar(int c);
int fputc(int c, FILE * stream);
// 함수 호출 성공시 쓰여진 문자 정보, 실패시 EOF반환

putchar() 함수는 인자로 전달된 문자정보를 stdout 표준 출력 스트림으로 전송하여 모니터로 출력하는 함수이다. 

fputc()함수는 문자를 전송한다는 측면은 putchar()함수와 동일하지만 문자를 전송할 스트림을 지정할 수 있어 파일을 대상으로도 데이터를 저장할 수 있다. fputc() 함수의 두 번째 매개변수 stream은 문자를 출력할 스트림을 지정하는데 사용된다.

 

문자 입력 함수

키보드로 부터 하나의 문자을 입력 받을 때 일반적으로 사용하는 함수는 getchar() 과 fgetc()가 있다.

#include <stdio.h>
int getchar(void)
int fgetc(FILE * stream);
// 파일의 끝에 도달하거나 함수 호출 실패 시 EOF반환

getchar() 함수는 stdin으로 표현되는 표준 입력 스트림으로부터 하나의 문자를 입력받아 반환하는 함수이다. 

fgetc() 함수는 문자를 입력받을 스트림을 지정할 수 있다.

 

#include <stdio.h>

int main(void)
{
    int ch1, ch2;

    ch1 = getchar();    // 문자 입력
    ch2 = fgetc(stdin); // 엔터키 입력

    putchar(ch1);       // 문자 출력
    fputc(ch2, stdout); // 엔터키 출력
    return 0;
}

위 코드에서 문자를 int 형 변수로 선언한 이유는 getchar() 함수와 fgetc()함수의 반환형이 int 이기 때문이다. 

 

문자 입출력에서의 EOF

EOF는 End Of File의 약자로 파일의 끝을 표현하기위해 정의된 상수이다. 따라서 EOF가 반환되면 파일의 끝에 도달하여 더 이상 읽을 내용이 없음을 의미한다. 키보드를 대상으로 하느 fgetc() 와 getchar() 함수는 다음의 경우중 하나가 만족되었을 때 EOF를 반환한다.

  • 함수 호출 실패
  • Windows에서 CTRL + Z, Linux에서 CTRL + D 키가 입력되었을 경우
#include <stdio.h>

int main(void)
{
    int ch;

    while (1)
    {
        ch = getchar();
        if(ch == EOF)
            break;
        putchar(ch);
    }
    return 0;
}

위 코드를 실행하면 문자 입출력이 반복되고 EOF를 반환하는 CTRL + D 키를 입력하면 프로그램이 종료된다.

 

위 함수들의 반환형이 int 이고, int형 변수에 문자를 담는 이유는 EOF 는 -1로 정의된 상수인데, 반환형이 char 이라면 처리하는 컴파일러에 따라 char을 unsigned char로 처리하는 경우가 있어 -1을 양의 정수로 형변환 하는 경우가 발생 할 수 있다. 그래서 어떤 컴파일러라도 -1 을 유지하기 위해 반환형을 int 로 정의해둔것이고, 반환형이 int 이기 때문에 int 형 변수에 값을 저장해야 한다.

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

[C++] 입출력  (0) 2021.08.21
[Project H4C] C언어 코딩도장(6)  (0) 2021.03.02
[C] 스트림  (0) 2021.01.15
[C] main 함수로의 인자 전달  (0) 2021.01.09
[C] void 포인터  (0) 2021.01.08

프로그램 상에서 키보드로 입력받아 모니터로 출력할 때 이를 연결해 주는 매개체를 스트림 이라고 한다.

스트림은 입력 장치에서 실행중인 프로그램으로 연결시켜 주는 입력 스트림과, 프로그램에서 출력장치로 연결시켜주는 출력 스트림이 있다.

 

콘솔 입출력을 위한 입력 스트림과 출력 스트림은 프로그램이 생성되면 자동으로 생성되고, 프로그램이 종료되면 자동으로 종료되기 때문에 직접 요구할 필요는 없지만, 파일과의 연결을 위한 스트림의 생성은 직접 요구해야 한다.

 

콘솔 입출력을 위한 스트림은 기본적으로 제공되는 표준 스트림(standard stream)이다. 표준 스트림은 다음과 같다.

  • stdin : 표준 입력 스트림 : 키보드 대상으로 입력
  • stdout : 표준 출력 스트림 : 모니터 대상으로 출력
  • stderr : 표준 에러 스트림 : 모니터 대상으로 출력

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

[Project H4C] C언어 코딩도장(6)  (0) 2021.03.02
[C] 문자 단위 입출력 함수  (0) 2021.01.15
[C] main 함수로의 인자 전달  (0) 2021.01.09
[C] void 포인터  (0) 2021.01.08
[C] 함수 포인터  (0) 2021.01.08

main 함수는 다음과 같이 정의할 수도 있다. 

int main(int argc, char * argv[]) { ... }

프로그램 실행시 main함수로 인자를 전달할 수 있고, main 함수도 인자를 전달받을 수 있도록 한 것이다. 

#include <stdio.h>

int main(int argc, char * argv[])
{
    int i = 0;
    printf("전달된 문자열의 수 : %d\n", argc);
    
    for(i = 0; i < argc; i++)
        printf("%d 번째 문자열 : %s\n", i+1, argv[i]);
    
    return 0;
}
/* 
input : 
# ./argcargv I love you

output:
전달된 문자열의 수 : 4
1 번째 문자열 : ./argcargv
2 번째 문자열 : I
3 번째 문자열 : love
4 번째 문자열 : you
*/

위 코드와 같이 main함수를 구성하면 프로그램을 실행할 때 인자를 전달 할 수 있다. argv는 char형 더블 포인터 변수이다. 

인자 전달 과정에서 공백은 문자열을 나누는 기준이 된다. 인자로 전달된 문자열들이 배열에 묶여 main 함수의 두 번째 인자로 전달이되고, 첫 번째 인자는 문자열의 수가 전달이 된다.

#include <stdio.h>

int main(int argc, char * argv[])
{
    int i = 0;
    printf("전달된 문자열의 수 : %d\n", argc);

    while(argv[i] != NULL)
    {
        printf("%d 번째 문자열 : %s\n", i+1, argv[i]);
        i++;
    }

    return 0;
}
/* 
input : 
# ./argvNull "I Love You"

output : 
전달된 문자열의 수 : 2
1 번째 문자열 : ./argvNull
2 번째 문자열 : I Love You
*/

위 코드를 통해 전달받은 배열의 마지막에 NULL이 삽입됨을 확인할 수 있다. 또한 큰 따옴표로 묶으면 공백을 포함하는 문자열을 인자로 전달할 수 있다.

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

[C] 문자 단위 입출력 함수  (0) 2021.01.15
[C] 스트림  (0) 2021.01.15
[C] void 포인터  (0) 2021.01.08
[C] 함수 포인터  (0) 2021.01.08
[C] 2차원 배열의 포인터  (0) 2020.12.30

다음과 같이 선언되는 포인터를 void형 포인터라 한다.

void * ptr;

void형 포인터 변수는 함수의 주소를 포함한 어떠한 변수의 주소값이든 담을 수 있다.

#include <stdio.h>

void SimpleFunc(void)
{
    printf("Simple function\n");
}

int main(void)
{
    int num = 20;
    void *ptr;
    
    ptr = &num;
    printf("%p\n", ptr);

    ptr = SimpleFunc;
    printf("%p\n", ptr);
    return 0;
}
/* output : 
0x7ffee8607858
0x1075fbf00
*/

위 코드처럼 어떤 형태의 변수의 주소값이든 저장할 수 있다. 그러나 void형 포인터 변수는 형(type)에 대한 정보가 없기 때문에 포인터 연산, 값의 변경, 참조가 불가능하다.

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

[C] 스트림  (0) 2021.01.15
[C] main 함수로의 인자 전달  (0) 2021.01.09
[C] 함수 포인터  (0) 2021.01.08
[C] 2차원 배열의 포인터  (0) 2020.12.30
[C] 삼중 포인터  (0) 2020.12.28

프로그램 내에 정의된 다양한 함수들도 바이너리 형태로 메모리에 저장되어 호출시 실행된다. 이런 함수들의 주소도 포인터 변수에 저장할 수 있다. 배열의 이름이 배열의 시작 주소를 가리키듯, 함수의 이름도 함수가 저장된 메모리 주솟값을 나타낸다.

int SimpleFunc(int num) { ... }

위 함수의 반환형은 int 이고, 매개변수는 int num 이다. 함수의 이름 SimpleFunc는 함수의 주솟값을 의미하는 상수형태의 함수 포인터 이다. 이 함수의 포인터 형은 반환형이 int이고, 매개변수로 int형 변수가 하나 선언된 포인터형 이다.

 

포인터 변수의 선언은 다음과 같다.

int (*fptr) (int)

반환형이 int이며, 매개변수 선언이 int 하나인 함수 포인터 변수이다. 

다음과 같은 함수의 경우 아래와 같이 함수 포인터 변수를 선언한다.

int Func(int num1, int num2) { ... }
int (*fptr) (int, int);

그리고 다음과 같은 방식으로 Func 함수를 호출할 수 있다.

fptr(2,5);

다음 코드는 함수 포인터 변수를 활용한 예시이다.

#include <stdio.h>

void SimpleAdder(int n1, int n2)
{
    printf("%d + %d = %d\n", n1, n2, n1+n2);
}

void ShowString(char * str)
{
    printf("%s\n", str);
}

int main(void)
{
    char *str = "Function Pointer";
    int num1 = 10, num2 = 20;

    void(*fptr1)(int, int) = SimpleAdder;
    void(*fptr2)(char *) = ShowString;
    fptr1(num1, num2);
    fptr2(str);
    return 0;
}
/* output : 
10 + 20 = 30
Function Pointer
*/

 

#include <stdio.h>

int WhoIsFirst(int age1, int age2, int (*cmp)(int n1, int n2))
{
    return cmp(age1, age2);
}

int OlderFirst(int age1, int age2)
{
    if(age1 > age2)
        return age1;
    else if(age2 > age1)
        return age2;
    else
        return 0;
}

int YoungerFirst(int age1, int age2)
{
    if(age1<age2)
        return age1;
    else if(age2<age1)
        return age2;
    else
        return 0;
}

int main(void)
{
    int age1 = 20, age2 = 30;
    int first;

    printf("입장순서 1 \n");
    first = WhoIsFirst(age1, age2, OlderFirst);
    printf("%d세와 %d세중 %d세가 먼저 입장\n", age1, age2, first);

    printf("입장순서 2 \n");
    first = WhoIsFirst(age1, age2, YoungerFirst);
    printf("%d세와 %d세중 %d세가 먼저 입장\n", age1, age2, first);
    return 0;
}
/* output : 
입장순서 1 
20세와 30세중 30세가 먼저 입장
입장순서 2 
20세와 30세중 20세가 먼저 입장
*/

위 코드와 같이 함수의  매개변수로 함수 포인터 변수를 넣을 수 도 있다.

 

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

[C] main 함수로의 인자 전달  (0) 2021.01.09
[C] void 포인터  (0) 2021.01.08
[C] 2차원 배열의 포인터  (0) 2020.12.30
[C] 삼중 포인터  (0) 2020.12.28
[C] 더블 포인터  (0) 2020.12.28
int arr2d[3][3];

위의 2차원 배열은 다음과 같은 모양을 갖는다.

[0][0] [0][1] [0][2]
[1][0] [1][1] [1][2]
[2][0] [2][1] [2][2]

2차원 배열의 경우 arr2d[0], arr2d[1], arr2d[2]도 각각 1행, 2행, 3행의 첫 번째 요소를 가리킨다.

또한 2차원 배열의 첫 번째 요소의 주소 값을 출력할 때는 다음 두 가지 형태로 동일하게 출력이 가능하다.

printf("%p\n", arr2d);
printf("%p\n", arr2d[0]);
#include <stdio.h>

int main(void)
{
    int arr2d[3][3];
     printf("%d\n", arr2d);
     printf("%d\n", arr2d[0]);
     printf("%d\n\n", &arr2d[0][0]);

    printf("%d\n", arr2d[1]);
    printf("%d\n\n",&arr2d[1][0]);

     printf("%d\n", arr2d[2]);
     printf("%d\n\n", &arr2d[2][0]);

     printf("sizeof(arr2d) : %d\n", sizeof(arr2d));
     printf("sizeof(arr2d[0]) : %d\n", sizeof(arr2d[0]));
     printf("sizeof(arr2d[1]) : %d\n", sizeof(arr2d[1]));
     printf("sizeof(arr2d[2]) : %d\n", sizeof(arr2d[2]));
    return 0;
}
/* output
 -272632624
 -272632624
 -272632624

 -272632612
 -272632612

 -272632600
 -272632600

 sizeof(arr2d) : 36
 sizeof(arr2d[0]) : 12
 sizeof(arr2d[1]) : 12
 sizeof(arr2d[2]) : 12
 */

 위 코드와 같이 arr2d는 첫 번째 요소를 가리키며, 배열 전체를 의미한다.  arr2d[0]은 첫 번째 요소를 가리키며 1행만을 의미한다. 그래서 sizeof 연산 결과 arr2d는 배열 전체의 크기인 36이 출력되었고, arr2d[0]은 첫 번째 행의 크기인 12가 출력되었다.

 

1차원 배열의 경우 다음 코드에서 iarr은 int형 포인터 이기 때문에 iarr+sizeof(int)의 계산 결과가 출력되고,  darr은 double형 포인터 이므로 darr+sizeof(double)이 출력된다.

int iarr[3];
double darr[7];

printf("%p\n", iarr+1);
printf("%p\n", darr+1);

또한 2차원 배열을 대상으로 증가 연산을 진행해보면 다음과 같다.

#include <stdio.h>

int main(void)
{
    int arr1[3][2];
    int arr2[2][3];

    printf("arr1 : %p\n", arr1);
    printf("arr1+1 : %p\n", arr1+1);
    printf("arr1+2 : %p\n\n", arr1+2);

    printf("arr2 : %p\n", arr2);
    printf("arr2+1 : %p\n", arr2+1);
    return 0;
}
/* output : 
@"arr1 : 0x7ffeefbff7c0\r\n"
@"arr1+1 : 0x7ffeefbff7c8\r\n"
@"arr1+2 : 0x7ffeefbff7d0\r\n"
@"\r\n"
@"arr2 : 0x7ffeefbff7a0\r\n"
@"arr2+1 : 0x7ffeefbff7ac\r\n"
*/

첫 번째 배열의 경우 1씩 증가시켰을 때 8이 증가하였고, 두 번째 배열의 경우 1을 증가시키면 12가 증가하였다. 2차원 배열 이름을 대상으로 증가 및 감소 연산을 할 경우 각 행의 첫번째 요소를 가리킨다. arr1은 1행의 첫번째 요소를 가리키며, arr1+1은 두번째 행의 첫번째 요소를 가리킨다. arr1은 가로가 한 행에 두 칸이기 때문에 8이 증가한 것이다. 2차원 배열의 포인터형은 가로의 길이에 따라서 달라진다.

2차원 배열은 포인트 연산시 sizeof(type) x 가로길이 만큼 값이 증가한다.

 

위와 같은 유형의 포인트 변수 선언은 int형이며, sizeof(int)x4의 크기 단위로 증가 및 감소하는 포인터 변수 선언은 다음과 같다.

int (*ptr)[4];

 

#include <stdio.h>

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

    int (*ptr)[2];
    int i;

    ptr = arr1;
    printf("** Show 2,2 arr1 **\n");
    for(i = 0; i < 2; i++)
        printf("%d %d\n", ptr[i][0], ptr[i][1]);

    ptr = arr2;
    printf("** Show 3,2 arr2 **\n");
    for(i = 0; i < 3; i++)
        printf("%d %d\n", ptr[i][0], ptr[i][1]);
    
    ptr = arr3;
    printf("** Show 4,2 arr3 **\n");
    for(i = 0; i < 4; i++)
        printf("%d %d\n", ptr[i][0], ptr[i][1]);
      
}
/* output : 
@"1 2\r\n"
@"3 4\r\n"
@"** Show 3,2 arr2 **\r\n"
@"1 2\r\n"
@"3 4\r\n"
@"5 6\r\n"
@"** Show 4,2 arr3 **\r\n"
@"1 2\r\n"
@"3 4\r\n"
@"5 6\r\n"
@"7 8\r\n"
*/

위 코드와 같이 포인터 변수를 선언하여 2차원 배열에 접근할 수 있다.

 

2차원 배열의 주소 값을 인자로 전달 받는 함수를 정의할 때 매개 변수는 다음과 같이 선언할 수 있다.

void Function(int (*parr1)[7], double (*parr2)[5]) {...}
void Function(int parr[][7], double parr[][5]) {...}

위 두 방식의 매개변수 선언은 동일한 방식이다.

#include <stdio.h>

void ShowArr2DStyle(int (*arr)[4], int column)
{
    int i,j;
    for(i=0; i<column; i++){
        for(j=0; j<4; j++)
            printf("%d ", arr[i][j]);
        printf("\n");
    }
    printf("\n");
}

int Sum2DArr(int arr[][4], int column)
{
    int i, j, sum=0;
    for(i=0; i<column; i++)
        for(j=0; j<4; j++)
            sum+=arr[i][j];
    return sum;
}

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

    ShowArr2DStyle(arr1, sizeof(arr1)/sizeof(arr1[0]));
    ShowArr2DStyle(arr2, sizeof(arr2)/sizeof(arr2[0]));
    printf("arr1의 합 : %d\n", Sum2DArr(arr1, sizeof(arr1)/sizeof(arr1[0])));
    printf("arr2의 합 : %d\n", Sum2DArr(arr2, sizeof(arr2)/sizeof(arr2[0])));
    return 0;
}
/* output : 
1 2 3 4 
5 6 7 8 

1 1 1 1 
3 3 3 3 
5 5 5 5 

arr1의 합 : 36
arr2의 합 : 36
*/

위 코드의 다음과 같은 연산은 배열의 세로길이를 계산하는 것이다.

sizeof(arr1) / sizeof(arr1[0])
sizeof(arr2) / sizeof(arr2[0])

sizeof(arr1)은 배열의 전체 크기를 나타내고, sizeof(arr1[0])은 배열의 가로의 크기를 나타내기 때문에 위 코드는 배열의 세로 길이를 의미한다.

 

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

2차원 배열이 위와 같이 선언되어 있을 때, 인덱스 [2][1]의 위치의 값을 4로 변경하려면 다음의 코드들을 이용할 수 있다.

arr[2][1] = 4;
(*(arr+2))[1] = 4;
*(arr[2]+1) = 4;
*(*(arr+2)+1) = 4;

 

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

[C] void 포인터  (0) 2021.01.08
[C] 함수 포인터  (0) 2021.01.08
[C] 삼중 포인터  (0) 2020.12.28
[C] 더블 포인터  (0) 2020.12.28
[C] 3차원 배열  (0) 2020.12.26

포인터를 선언할 때 * 연산자가 둘 이상 사용되면 다중 포인터라 한다. *연산자는 얼마든지 사용될 수 있다.

 

다음과 같이 *연산자가 3개이상 삽입된 포인터 변수를 삼중 포인터 변수라고 한다. 

int ***tptr;

삼중 포인터 변수는 이중(더블) 포인터 변수를 가리키는(주소값을 저장하는) 용도로 사용된다.  

#include <stdio.h>

int main(void)
{
    int num = 100;
    int *ptr = &num;
    int **dptr = &ptr;
    int ***tptr = &dptr;

    printf("%d %d\n", **dptr, ***tptr);
    return 0;
}
// output : 100 100

위 코드는 삼중포인터의 선언과 접근에 대한 예시이다.

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

[C] 함수 포인터  (0) 2021.01.08
[C] 2차원 배열의 포인터  (0) 2020.12.30
[C] 더블 포인터  (0) 2020.12.28
[C] 3차원 배열  (0) 2020.12.26
[C] 2차원 배열  (0) 2020.12.24

포인터 변수를 가리키는 또 다른 포인터 변수를 더블 포인터 또는 이중 포인터 라고 한다. 선언은 다음과 같이 * 연산자를 두 개 이어서 선언 한다.

int **dptr;

 

int main(void)
{
    double num = 3.14;
    double *ptr = &num;
    double **dptr = &ptr;
}

위와 같이 코드를 작성하게 되면 num 변수에는 3.14가 저장되어 있고, ptr변수는 num 변수의 주소를 가리키고 있고, dptr 변수는 ptr변수의 주소를 가리키고 있다. 또한 dptr 변수를 사용하여 다음과 같이 ptr변수와 num 변수에 접근할 수 있다. 

*dptr = ....;		// ptr 변수에 접근
*(*dptr) = ....;	// num 변수에 접근

*(*dptr)의 경우 괄호의 생략이 가능하여 **dptr로 접근할 수도 있다.

#include <stdio.h>

int main(void)
{
    double num = 3.14;
    double *ptr = &num;
    double **dptr = &ptr;
    double *ptr2;

    printf("%9p %9p\n", ptr, *dptr);
    printf("%9g %9g\n", num, **dptr);
    ptr2 = *dptr;   // ptr2 = ptr과 같음
    *ptr2 = 10.22;
    printf("%9g %9g\n", num, **dptr);
    return 0;
}
/* output : 
 0061FF10  0061FF10
     3.14      3.14
    10.22     10.22
*/

위와 같이 코드를 작성했을때 num 변수는 ptr변수와 ptr2변수가 가리키고 있고, ptr변수는 dptr변수가 가리키고 있다.

위와 같은 경우 변수 num에 접근하는 방법은 다음과 같다.

**dptr = 10.5;
*ptr = 10.5;
*ptr2 = 10.5;
num = 10.5;

위 4개의 경우 모두 num 변수에 10.5가 저장된다.

 

배열은 시작점의 주소를 가리키는 하나의 포인터이다. 포인터를 요소로 갖는 배열은 더블 포인터가 된다. 따라서 다음과 같이 포인터를 요소로 갖는 배열은 더블 포인터를 이용하려 접근할 수 있다.

#include <stdio.h>

int main(void)
{
    int num1 = 10, num2 = 20, num3 = 30;
    int *ptr1 = &num1;
    int *ptr2 = &num2;
    int *ptr3 = &num3;

    int *ptrArr[] = {ptr1, ptr2, ptr3};
    int **dptr = ptrArr;

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

 

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

[C] 2차원 배열의 포인터  (0) 2020.12.30
[C] 삼중 포인터  (0) 2020.12.28
[C] 3차원 배열  (0) 2020.12.26
[C] 2차원 배열  (0) 2020.12.24
[C] 포인터에서 const 사용  (0) 2020.12.20

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

2차원 배열은 다음과 같이 선언한다.

int arr[3][4];	// 세로가 3, 가로가 2인 int형 2차원 배열

2차원 배열의 선언 방식은 세로와 가로의 길이를 각각 명시한다. 이 선언으로 할당되는 배열의 모습은 다음과 같다.

  1열  2열 3열 4열
1행 [0][0] [0][1] [0][2] [0][3]
2행 [1][0] [1][1] [1][2] [1][3]
3행 [2][0] [2][1] [2][2] [2][3]

위 표에서 삽입된 두개의 숫자는 배열에 접근할 때 사용하게 되는 인덱스값이다. 배열의 이름이 arr이고 배열의 자료형이 TYPE라 할 때 2차원 배열의 선언 형태는 다음과 같다.

TYPE arr[세로길이][가로길이];

 

sizeof 연산자를 이용하여 2차원 배열의 크기를 확인해보면 다음과 같다.

#include <stdio.h>

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

int 형 배열이기 때문에 한 칸에 4씩 계산하여 48이 나온다.

 

2차원 배열은 다음과 같이 접근하여 값을 저장할 수 있다.

arr[2][1] = 5;
arr[0][1] = 3;

 

2차원 배열의 메모리 주소값도 1차원 배열과 동일한 구조이다. 예를 들어 세로3, 가로2인 2차원 배열을 선언하여 메모리 주소를 확인하면 다음과 같다. 

#include <stdio.h>

int main(void)
{
    int arr[3][2];
    
    for(int i = 0; i < 3; i++)
    {
        for(int j = 0; j < 2; j++)
        {
            printf("%p \n", &arr[i][j]);
        }
    }

    return 0;
}
/* output :
0061FF00 
0061FF04 
0061FF08
0061FF0C
0061FF10
0061FF14
*/

int 형 2차원 배열이기 때문에 4바이트 만큼 차이가 나는 상태로 1열로 할당되어 있다.

 

2차원 배열도 선언과 동시에 초기화가 가능하다. 

int arr[3][3] = {
    {1,2,3},
    {4,5,6},
    {7,8,9}
};

위 코드처럼 행 단위로 초기화 할 값들을 별도의 중괄호로 명시해야 한다. 

다음 코드와 같이 초기화를 생략한 요소가 있다면 빈 공간은 0으로 초기화 된다.

int arr[3][3] = {
    {1},
    {4,5},
    {7,8,9}
};

다음 코드와 같이 한 줄로 초기화 하는 것도 가능하다. 

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

위 코드와 같이 부족한 부분이 있다면 마찬가지로 0으로 채워진다.

#include <stdio.h>

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

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

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

    for(int i = 0; i < 3; i++)
    {
        for(int j = 0; j < 3; j++)
        {
            printf("%d ", arr1[i][j]);
        }
        printf("\n");
    }
    printf("\n");

    for(int i = 0; i < 3; i++)
    {
        for(int j = 0; j < 3; j++)
        {
            printf("%d ", arr2[i][j]);
        }
        printf("\n");
    }
    printf("\n");

    for(int i = 0; i < 3; i++)
    {
        for(int j = 0; j < 3; j++)
        {
            printf("%d ", arr3[i][j]);
        }
        printf("\n");
    }
    
    return 0;
}
/* output : 
1 2 3 
4 5 6
7 8 9

1 2 3
4 5 0
7 0 0

1 2 3
4 5 6
0 0 0
*/

 

1차원 배열처럼 배열의 길이를 명시하지 않고 초기화 하는것도 가능하다. 그러나 다음과 같이 가로와 세로의 길이를 모두 명시하지 않는 것은 불가능하다.

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

배열의 요소가 8개 이므로 1x8, 2x4, 4x2, 8x1의 경우로 여러개의 경우가 있기 때문이다.  그래서 하나를 알려줘야 하는데, 다음과 같이 세로의 길이는 생략이 가능하다. 가로 길이는 생략이 불가능하다. 가로의 길이를 생략하면 위 코드와 같이 컴파일러에서 에러를 발생한다.

int arr[][4] = {1,2,3,4,5,6,7,8};
int arr2[][2] = {1,2,3,4,5,6,7,8};

 

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

[C] 더블 포인터  (0) 2020.12.28
[C] 3차원 배열  (0) 2020.12.26
[C] 포인터에서 const 사용  (0) 2020.12.20
[C] Call - by - value, Call - by - reference  (0) 2020.12.20
[C] 함수 인자로 배열 전달  (0) 2020.12.20

+ Recent posts