Skip to main content

Command Palette

Search for a command to run...

C 언어 자료형

Updated
6 min readView as Markdown

자료형(Data Type)

  • 데이터를 표현하는 기준(방법)

기본 자료형

  1. 정수형

    • char(1 Byte): -128 이상 127 이하

    • short(2 Byte): -32,768 이상 32,767 이하

    • int(4 Byte): -2,147,483,648 이상 2,147,483,647 이하

    • long(4 Byte): int와 동일

    • long long(8 Byte)

  2. 실수형

    • float(4 Byte)

    • double(8 Byte)

    • long double(8 Byte 이상)

많은 수의 자료형을 제공하는 이유

  1. 데이터의 표현방식이 다르기 때문에

  2. 메모리 공간의 적절한 사용을 위해서 다양한 크기의 자료형이 필요

sizeof 연산자를 이용하여 자료형의 크기 확인

#include <stdio.h>

int main(void)
{
    char ch=9;
    int inum=1052;
    double dnum = 3.1415;
    printf("변수 ch의 크기: %d \n", sizeof(ch));
    printf("변수 inum의 크기: %d \n", sizeof(inum));
    printf("변수 dnum의 크기: %d \n", sizeof(dnum));

    printf("char의 크기: %d \n", sizeof(char));
    printf("int의 크기: %d \n", sizeof(int));
    printf("long의 크기: %d \n", sizeof(long));
    printf("long long의 크기: %d \n", sizeof(long long));
    printf("float의 크기: %d \n", sizeof(float));
    printf("double의 크기: %d \n", sizeof(double));
}
// %d 는 10진수 정수형태의 출력을 의미
// 결과
변수 ch의 크기: 1 
변수 inum의 크기: 4 
변수 dnum의 크기: 8 
char의 크기: 1 
int의 크기: 4 
long의 크기: 8 
long long의 크기: 8 
float의 크기: 4 
double의 크기: 8

정수를 표현 및 처리하기 위한 일반적인 자료형의 선택

#include <stdio.h>

int main(void)
{
    char num1=1, num2=2, result1=0;
    short num3=300, num4=400, result2=0;

    printf("size of num1 & num2: %d, %d \n", sizeof(num1), sizeof(num2));
    printf("size of num3 & num4: %d, %d \n", sizeof(num3), sizeof(num4));

    printf("size of char add: %d \n", sizeof(num1+num2));
    printf("size of short add: %d \n", sizeof(num3+num4));
    /* 두 결과가 모두 4 Byte인 이유: 
        일반적으로 CPU가 처리하기에 가장 적합한 크기의 정수 자료형을 int로 정의
        -> int형 연산의 속도가 다른 자료형의 연산속도에 비해서 동일하거나 빠르다
        이로 인해, int보다 작은 크기의 데이터는 int형 데이터로 바꿔서 연산이 진행된다. -> 형 변환 

        따라서, 연산의 대상이 되는 변수를 선언하는 경우, 특히 연산의 횟수가 빈번한 경우에는 저장되는 값의 크기가
        작더라도 int형 변수를 선언 

       char, short가 사용되는 경우: 
        데이터의 양이 많아서 연산속도보다 데이터의 크기를 줄이는 것이 더 중요한 데이터들 */ 

    result1=num1+num2;
    result2=num3+num4;
    printf("size of result1 & result2: %d, %d \n", sizeof(result1), sizeof(result2));
    return 0;
}
// 결과
size of num1 & num2: 1, 1 
size of num3 & num4: 2, 2 
size of char add: 4 
size of short add: 4 
size of result1 & result2: 1, 2

실수를 표현 및 처리하기 위한 일반적인 자료형의 선택

  • 실수 자료형의 선택에 있어서 가장 중요한 요소는 “정밀도"

    • 정밀도: 오차가 발생하지 않는 소수점 이하의 자릿수
  • 보편적으로 선택하는 자료형: double

    • float보다 정밀도가 높다.

    • long double보다 부담이 적다.

#include <stdio.h>

int main(void) // int는 입력 형태, void는 출력 형태
{
    double rad;
    double area;
    printf("원의 반지름 입력: ");
    scanf("%lf", &rad);

    area = rad*rad*3.1415;
    printf("원의 넓이: %f \n", area);
    return 0; // 0은 운영체제에게 전달되는 데, 정상적인 종료의 상황에서 전달되는 값을 의미
}
// 결과
원의 반지름 입력: 2.4
원의 넓이: 18.095040

양의 정수만 표현하게 하는 unsigned

  • 정수 자료형의 이름 앞에만 unsigned를 붙일 수 있음

  • unsinged가 붙으면, MSB도 데이터의 크기를 표현하는데 사용

  • char는 예외일 수 있음(Default가 unsigned인 경우도 존재)

문자의 표현방식과 문자를 위한 자료형

아스키(ASCII) 코드

  • 숫자를 문자에 mapping해 놓은 코드

문자의 표현

  • 프로그램상에서의 문자표현에는 작은 따옴표가 사용
#include <stdio.h>

int main(void)
{
    char ch1='A', ch2=65;
    int ch3='Z', ch4=90;

    printf("%c %d \n", ch1, ch1); 
    printf("%c %d \n", ch2, ch2);
    printf("%c %d \n", ch3, ch3); 
    printf("%c %d \n", ch4, ch4);
    /*
    %c 는 문자의 형태로 데이터를 출력(또는 입력)하라 라는 의미
    8 ~ 11행을 통해 정수는 출력의 방법에 따라서 문자의 형태로도, 숫자의 형태로도 출력이 가능하다는 것을 알게 됌
    아스키 코드는 0 이상 127 이하이다. 따라서 char형 변수로 저장하는 것이 메모리 효율적으로도 좋다.
    int형은 연산에 이점이 있지만, 문자열을 연산에 사용하지 않으므로, char형이 더 적합하다.
    */ 
    return 0;
}
// 결과
A 65 
A 65 
Z 90 
Z 90

상수에 대한 이해

  • 이름이 있는 상수와 이름이 없는 상수로 나뉨

  • 자료형을 근거로 표현

이름을 지니지 않는 리터럴(Literal) 상수

int main(void)
{
   int num = 30 + 40   // 30과 40은 상수이다!
   /*
      단계 1: 정수 30과 40이 메모리 공간에 상수의 형태로 저장된다.
      단계 2: 두 상수를 기반으로 덧셈이 진행된다.
      단계 3: 덧셈의 결과로 얻어진 정수 70이 변수 num에 저장된다.
      이 때, 상수 30과 40이 할당된 메모리 공간에 이름이 없는데 이를 '리터럴 상수' 혹은 '리터럴'이라 한다.
   */
}

리터럴 상수의 자료형

  • int형으로 표현 가능한 정수형 상수는 int형으로 저장하기로 약속

  • double형으로 표현 가능한 실수형 상수는 double형으로 저장하기로 약속

  • 문자형 상수와 같은 경우로는 char 필드로 선언을 하더라도 아스키 코드에 해당 한다면 int형으로 저장된다.

접미사를 이용한 다양한 상수의 표현

int main(void)
{
   float num1 = 5.789; // 경고 메세지 발생
   float num2 = 3.24 + 5.12; // 경고 메세지 발생
   return 0;
}
/* 
   경고 메세지: 초기화 할 때, double형 데이터를 float형 변수에 저장하였으니, 데이터가 잘려나갈 수 있습니다.
   5.789는 8 Byte의 double형 상수이고, 변수 num1은 4 Byte의 float형 변수이므로, 경고 메세지가 나타남.
*/
   float num1 = 5.789f;  // 경고 메세지 발생 안 함
   float num2 = 3.24F + 5.12F; // 대소문자 구분 없음
  • 정수형을 위한 접미사

    • U: unsigned int

    • L: long

    • UL: unsigned long

    • LL: long long

    • ULL: unsigned long long

  • 실수형을 위한 접미사

    • F: float

    • L: long double

이름을 지니는 심볼릭(Symbolic) 상수: const 상수

  • 상수의 이름은 모두 대문자로 표시하고, 둘 이상의 단어로 연결할 때에는 _를 이용하는 것이 관례
int main(void)
{
   const int MAX=100; // MAX는 상수, 따라서 값의 변경 불가
}

자료형의 변환

  • 데이터의 표현 방식을 바꾸는 것

    • 자동 형 변환(묵시적 형 변환)

    • 강제 형 변환(명시적 형 변환)

대입연산의 전달과정에서 발생하는 자동 형 변환

  • 대입 연산자에서 두 피연산자의 자료형이 일치하지 않으면, 왼편에 있는 피연산자를 대상으로 형 변환이 자동으로 일어난다.
double num1 = 245;  // int형 정수 245를 double형으로 자동 형 변환 -> 245.0

int num2 = 3.1415;  // double형 실수 3.1415를 int형으로 자동 형 변환 -> 3
// 이로 인해 '소수부의 손실'이 발생

int num3 = 129;
char ch = num3; // int형 변수에 num3에 저장된 값이 char형으로 자동 형 변환 -> -127
/*
   129가 저장된 변수 num3의 비트 열:
   00000000 00000000 00000000 10000001
   하지만, char 필드는 1 Byte기 떄문에 변수 ch에 저장하기 위해선 크기를 줄여야 한다.
   따라서, 이 경우에는 '상위 Byte의 손실'이 발생하여,
   10000001 // 이는 정수로 -127
   부호가 바뀌는 결과가 나오게 된다.
*/
  • 데이터의 표현범위가 보다 넓은 자료형으로의 형 변환은, 그 과정에서 데이터 손실이 발생하지 않지만, 반대로는 발생할 수 있다.
#include <stdio.h>

int main(void)
{
    double num1=245;
    int num2=3.1415;
    int num3=129;
    char ch=num3;

    printf("정수 245를 실수로: %f \n", num1);
    printf("실수 3.1415를 정수로: %d \n", num2);
    printf("큰 정수 129를 작은 정수로: %d \n", ch);
    return 0;
}
// 결과
정수 245를 실수로: 245.000000 
실수 3.1415를 정수로: 3 
큰 정수 129를 작은 정수로: -127

명시적 형 변환: 강제로 일으키는 형 변환

#include <stdio.h>

int main(void)
{
    int num1=3, num2=4;
    double divResult;
    divResult = num1 / num2;
    printf("나눗셈 결과: %f \n", divResult);
    return 0;
}

// 결과
나눗셈 결과: 0.000000 

/*
   이같이 나온 이유: 연산결과의 자료형은 피연산자의 자료형과 일치하기 때문에 피연산자인 num1, num2가 int형 이므로
   3과 4의 나눗셈의 몫인 0이 double형으로 형 변환되어 divResult에 저장되서 위와 같은 결과가 나오게 되었다.
*/

#include <stdio.h>

int main(void)
{
    int num1=3, num2=4;
    double divResult;
    divResult = (double)num1 / num2;  // (double) '형 변환 연산자': 제일 먼저 형 변환 연산이 진행되도록 함
    printf("나눗셈 결과: %f \n", divResult);
    return 0;
}

// 결과
나눗셈 결과: 0.750000

More from this blog

선행처리기와 매크로

선행처리는 컴파일 이전의 처리를 의미 선행처리는 선행처리기에 의해서, 컴파일은 컴파일러에 의해서, 링크는 링커에 의해서 진행 소스파일 → 선행처리기 → 선행처리 거친 소스파일 → 컴파일러 → 오브젝트 파일 → 링커 → 실행파일 컴파일 과정을 거치게 되면 바이너리 데이터로 이루어진 오브젝트 파일이 생성 선행처리기가 하는 일 삽입해 놓은 선행처리 명령문대로 소스코드의 일부를 수정 여기서 수정이란, 단순 치환의 형태 /* 간단한 선행처리 명령문 */...

Oct 10, 20246 min read

C 언어의 메모리 구조

프로그램을 실행하면 해당 프로그램의 실행을 위한 메모리 공간이 운영체제에 의해서 미리 마련 그리고 바로 이 메모리 공간 내에서 변수가 선언되고, 문자열이 선언되는 것 메모리의 구성 프로그램 실행 시 운영체제에 의해서 마련되는 메모리의 구조는 네 개의 영역으로 구분 코드 영역 / 데이터 영역 / 힙 영역 / 스택 영역 메모리 공간을 나눠놓은 이유는 유사한 성향의 데이터를 묶어서 저장을 하면, 관리가 용이해지고 메모리의 접근속도가 향상 메모리 영역...

Oct 9, 20246 min read

파일과 스트림(Stream), 그리고 기본적인 파일의 입출력

저기 저 파일에 저장되어 있는 데이터를 읽고 싶어요. 프로그램 상에서 파일에 저장되어 있는 데이터를 참조하길 원한다고(읽기 원한다고) 가정했을 때, 우리가 구현한 프로그램과 참조할 데이터가 저장되어 있는 파일 사이에 데이터가 이동할 수 있는 다리를 놓는 일을 먼저 해야 한다. 이러한 데이터 이동의 경로가 되는 다리를 가리켜 ‘스트림(stream)’이라 함. 스트림이라는 것은 운영체제에 의해서 형성되는 소프트웨어적인 상태를 의미하는 것 따라서, ...

Oct 8, 20249 min read

JinGood

31 posts