주소 값의 저장을 목적으로 선언되는 포인터 변수

int main(void)
{
    char ch1='A', ch2='Q';
    int num=7;
}
/* 총 6바이트(1바이트 + 1바이트 + 4바이트)가 메모리 공간에 할당 
   1바이트의 메모리 공간을 단위로 하나의 주소 값이 할당되며, 주소 값도 1씩 증가
   C언어에서는 시작번지만을 가지고 위치를 표현 */

포인터 변수란 메모리의 주소 값을 저장하기 위한 변수

포인터 변수와 & 연산자

“정수 7이 저장된 int형 변수 num을 선언하고 이 변수의 주소 값 저장을 위한 포인터 변수 pnum을 선언 → pnum에 변수 num의 주소 값 저장"

int main(void)
{
    int num=7;
    int * pnum;    // 포인터 변수 pnum의 선언
    pnum = #   // num의 주소 값을 포인터 변수 pnum에 저장
}
/* &연산자는 '오른쪽에 등장하는 피연산자의 주소 값을 반환하는 연산자' 
   pnum에는 변수 num의 시작번지 주소 값이 저장
   -> 포인터 변수 pnum이 int형 변수 num을 가리킨다. 
   32비트 시스템 포인터 변수 -> 4바이트
   64비트 시스템 포인터 변수 -> 8바이트 */

포인터 변수 선언

  • 포인터 변수는 가리키고자 하는 변수의 자료형에 따라서 선언하는 방법이 달라짐, 사실 주소 값은 동일한 시스템에서 그 크기가 동일하며 모두 정수의 배열들 띔.

⁠type * ptr;  // type형 변수의 주소 값을 저장하는 포인터 변수 ptr의 선언⁠


포인터와 관련있는 연산자: & 연산자, * 연산자⁠

변수의 주소 값을 반환하는 & 연산자

int main(void)
{
    int num = 5;
    int * pnum = &num  // num의 주소 값을 반환해서 포인터 변수 pnum을 초기화
}

/* & 연산자의 피연산자는 변수이여야 하며, 상수는 피연산자가 될 수 없다 */
 
int main(void)
{
    int num1 = 5;
    double * pnum1 = &num1;  // 일치하지 않음!

    double num2 = 5;
    int * pnum2 = &num2;  // 일치하지 않음!
}

포인터가 가리키는 메모리를 참조하는 * 연산자

int main(void)
{
    int num=10;
    int * pnum=#  // 포인터 변수 pnum이 변수 num을 가리키게 하는 문장
    *pnum=20;    // pnum이 가리키는 변수에 20을 저장하라!
    printf("%d", *pnum);    // pnum이 가리키는 변수를 부호 있는 정수로 출력하라!
}

/* *pnum이 의미하는 바: 포인터 변수 pnum이 가리키는 메모리 공간인 변수 num에 접근 */
 
#include <stdio.h>

int main(void)
{
    int num1=100, num2=100;
    int * pnum;

    pnum=&num1;     // 포인터 pnum이 num1을 가리킴
    (*pnum)+=30;        // num1+=30; 과 동일

    pnum=&num2;     // 포인터 pnum이 num2를 가리킴
    (*pnum)-=30;        // num2-=30; 과 동일

    printf("num1: %d, num2: %d\n", num1, num2);
    return 0;
}

/* 결과 
num1: 130, num2: 70 */

다양한 ‘포인터 형'이 존재하는 이유

포인터 기반의 메모리 접근 기준을 마련하기 위해

잘못된 포인터의 사용과 null 포인터

  • 포인터 변수를 선언만하고 초기화하지 않으면, 포인터 변수는 쓰레기 값으로 초기화 → 어디를 가리킬 지 모르게 됌.

포인터 변수는 어떤 값으로 초기화를 시켜야 할까

int main(void)
{
    int * ptr1=0;
    int * ptr2=NULL;  // NULL은 사실상 0을 의미
}

/* ptr1을 초기화하는 값 0을 가리캬 'Null 포인터'라 함.
   "아무데도 가리키지 않는다!"를 의미함 */

'C' 카테고리의 다른 글

배열의 이해와 배열의 선언 및 초기화 방법  (0) 2025.03.12
변수의 존재기간과 접근범위  (0) 2025.03.12
조건에 따른 흐름의 분기  (0) 2025.03.12
반복 실행을 명령하는 반복문  (0) 2025.03.12
printf, scanf  (3) 2025.03.12

배열이란

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

1차원 배열의 선언에 필요한 것 세 가지: 배열 이름, 자료형, 길이 정보

⁠int oneDimArr[4];⁠

위의 문장을 이루는 요소 셋

  • int: 배열을 이루는 요소(변수)의 자료형
  • oneDimArr: 배열의 이름
  • [4]: 배열의 길이

배열의 길이 정보는 상수로 지정한다.

선언된 1차원 배열의 접근

#include <stdio.h>

int main(void)
{
    int arr[5];     // 길이가 5인 배열을 선언
    int sum=0, i;

    arr[0]=10, arr[1]=20, arr[2]=30, arr[3]=40, arr[4]=50;
    // 각 배열 요소의 값을 저장
    for(i=0 ; i<5 ; i++)
        sum += arr[i];

    printf("배열 요소에 저장된 값의 합: %d\n", sum);
    return 0;
}

/*
결과
배열 요소에 저장된 값의 합: 150
*/

배열의 모든 요소는 반복문을 이용해서 순차적으로 접근하는 것이 가능

배열! 선언과 동시에 초기화하기

⁠int arr1[5]={1, 2, 3, 4, 5};  // 순차적으로 1, 2, 3, 4, 5로 초기화⁠

⁠int arr2[ ]={1, 2, 3, 4, 5, 6, 7};  // 컴파일러에 의해서 자동으로 7이 삽입

int arr3[5]={1, 2};  // 3, 4, 5번째 배열 요소는 0으로 채워짐

배열을 이용한 문자열 변수의 표현

char형 배열의 문자열 저장과 null 문자

⁠char str[14]="Good morning!";  // Good morning!\0⁠

  • 위 코드를 보면 공백을 합해서 총 13자로 되어있지만, 문자열의 끝에 \0이라는 특수문자(escape sequence)가 자동으로 삽입이 되어
    실제 문자열의 길이는 14로 된다.
  • \0: null 문자

C 언어에서 표현하는 모든 문자열의 끝에는 null 문자가 자동으로 삽입

문자열의 끝에 null 문자가 필요한 이유

  • 문자열의 끝을 표시하기 위해
#include <stdio.h>

int main(void)
{
    char str[50] = "I like C programming";
    printf("string: %s\n", str);

    str[8] = '\0';      // 9번째 요소에 Null 문자 저장
    printf("string: %s\n", str);

    str[6] = '\0';      // 7번째 요소에 Null 문자 저장
    printf("string; %s\n", str);

    str[1] = '\0';      // 2번째 요소에 Null 문자 저장
    printf("string: %s\n", str);
    return 0;
    // str[8] = '\0'과 str[8] = 0 은 동일한 문장이다. 
}

// 결과
string: I like C programming
string: I like C
string; I like
string: I

'C' 카테고리의 다른 글

포인터 변수  (0) 2025.03.12
변수의 존재기간과 접근범위  (0) 2025.03.12
조건에 따른 흐름의 분기  (0) 2025.03.12
반복 실행을 명령하는 반복문  (0) 2025.03.12
printf, scanf  (3) 2025.03.12

변수의 존재기간과 접근범위 1: 지역변수

전역변수와 지역변수의 차이점

  • 메모리상에 존재하는 기간
  • 변수에 접근할 수 있는 범위

지역변수

  • ‘지역’이란 중괄호에 의해 형성되는 영역
  • 중괄호 내에 선언되는 변수는 모두 지역변수
  • 지역변수는 해당 지역을 벗어나면 자동으로 소멸
  • 지역변수는 선언된 지역 내에서만 유효하기 때문에 선언된 지역이 다르면 이름이 같아도 문제가 되지 않음
  • 지역변수는 반복문이나 조건문에도 선언이 가능

지역변수의 할당과 소멸

  • 지역변수는 '스택(Stack)'이라는 메모리 영역에 할당
  • 지역변수는 접시에 쌓듯이 할당
  • 지역변수는 해당 선언문이 실행될 때 메모리 공간에 할당되었다가, 선언문이 존재하는 함수가 반환을 하면(종료를 하면) 메모리 공간에서 소멸

지역변수의 일종인 매개변수

  • 선언된 함수 내에서만 접근이 가능
  • 선언된 함수가 반환을 하면, 지역변수와 마찬가지로 소멸

 

변수의 존재기간과 접근범위 2: 전역변수, static 변수, register 변수

전역변수

  • 처음 실행되면 메모리 공간에 할당되어서 프로그램이 종료될 때까지 메모리 공간에 남아있는 변수
  • 별도의 값으로 초기화하지 않으면 0으로 초기화
  • 프로그램 전체 영역 어디서든 접근이 가능

전역변수와 동일한 이름의 지역변수가 선언되면?

  • 해당 지역 내에서는 전역변수가 가리워지고, 지역변수로의 접근이 이뤄짐

지역변수에 static 선언을 추가해서 만드는 static 변수

  • 선언된 함수 내에서만 접근이 가능하다. (지역변수 특성)
  • 딱 1회 초기화되고 프로그램 종료 시까지 메모리 공간에 존재한다. (전역변수 특성)

보다 빠르게! register 변수

int SoSimple(void)
{
    register int num=3;
    .
    .
}
  • 위와 같이 선언이 되면 변수 num은 CPU 내에 존재하는 ‘레지스터'라는 메모리 공간에 저장될 확률이 높아짐
  • 레지스터: CPU 내에 존재하는 크기가 매우 작은 메모리 → 이 메모리에 저장된 데이터를 대상으로 하는 연산은 매우 빠름
  • 전역변수는 레지스터의 추가할 수 없다.

'C' 카테고리의 다른 글

포인터 변수  (0) 2025.03.12
배열의 이해와 배열의 선언 및 초기화 방법  (0) 2025.03.12
조건에 따른 흐름의 분기  (0) 2025.03.12
반복 실행을 명령하는 반복문  (0) 2025.03.12
printf, scanf  (3) 2025.03.12

조건적 실행과 흐름의 분기

흐름의 분기가 필요한 이유

프로그램의 흐름을 원하는 형태로 컨트롤할 수 있어야 하기 떄문에

if문을 이용한 조건적 실행

if(num1>num2)  // num1이 num2보다 크다면 아래의 중괄호를 실행한다.
{
   printf("num1이 num2보다 큽니다. \n");
   printf("%d > %d \n", num1, num2);
}
 
#include <stdio.h>

int main(void)
{
    int opt;
    double num1, num2;
    double result;

    printf("1.덧셈 2.뺄셈 3.곱셈 4.나눗셈 \n");
    printf("선택: ");
    scanf("%d", &opt);
    printf("두 개의 실수 입력: ");
    scanf("%lf %lf", &num1, &num2);

    if(opt==1)
        result = num1 + num2;
    if(opt==2)
        result = num1 - num2;
    if(opt==3)
        result = num1 * num2;
    if(opt==4)
        result = num1 / num2;
    printf("결과: %f \n", result);
    return 0;
}

/* 결과
1.덧셈 2.뺄셈 3.곱셈 4.나눗셈 
선택: 3
두 개의 실수 입력: 2.14 5.12
결과: 10.956800 
*/
  • 위 코드의 문제점: 어떠한 숫자가 입력되는 모든 조건검사(비교연산) 실행

If ~ else문을 이용한 흐름의 분기

  • else는 독립적으로 사용되는 것이 아니라 키워드 if와 더불어 하나의 문장을 구성하는 형태로 사용

'C' 카테고리의 다른 글

배열의 이해와 배열의 선언 및 초기화 방법  (0) 2025.03.12
변수의 존재기간과 접근범위  (0) 2025.03.12
반복 실행을 명령하는 반복문  (0) 2025.03.12
printf, scanf  (3) 2025.03.12
C 언어 자료형  (0) 2025.03.12

while문에 의한 문장의 반복

반복문이란 무엇인가

  • C언어에서 제공하는 3 가지의 반복문
    • while, do~while, for

while문은 반복을 명령하는 문장이다.

while(num<3) // 반복의 조건은 num<3
{
   printf("Hello world! \n");
   num++;
}
 
#include <stdio.h>

int main(void)
{
    int num=0;

    while(num<5)
    {
        printf("Hello world! %d \n", num);
        num++;  // 만약 이를 주석 처리하면 Hello world! 0이 무한대로 출력 되면서 무한 루프에 빠지게 된다.
    }
    return 0;
}

// 결과
Hello world! 0 
Hello world! 1 
Hello world! 2 
Hello world! 3 
Hello world! 4
  • 반복문 구성에 있어서 중요한 것은 반복의 조건을 무너뜨리기 위한 최소한의 연산
  • 반복문도 들여쓰기 해서 사용
  • 반복의 대상이 하나의 문장이라면 중괄호는 생략 가능
#include <stdio.h>

int main(void)
{
    int dan=0, num=1;
    printf("몇 단? ");
    scanf("%d", &dan);

    while(num<10)
    {
        printf("%d x %d = %d \n", dan, num, dan*num);
        num++;
    }
    return 0;
}

// 결과
몇 단? 7
7 x 1 = 7 
7 x 2 = 14 
7 x 3 = 21 
7 x 4 = 28 
7 x 5 = 35 
7 x 6 = 42 
7 x 7 = 49 
7 x 8 = 56 
7 x 9 = 63

while문의 중첩

#include <stdio.h>

int main(void)
{
    int cur=2;
    int is=0;

    while(cur<10)  // 2단부터 9단까지 반봅
    {
        is=1;  // 새로운 단의 시작을 위해서
        while(is<10)  // 각 단의 1부터 9의 곱을 표현
        {
            printf("%d x %d = %d \n", cur, is, cur*is);
            is++;
        }
        cur++;  // 다음 단으로 넘어가기 위한 증가
    }
    return 0;
}

// 결과
2 x 1 = 2 
2 x 2 = 4 
2 x 3 = 6 
2 x 4 = 8 
2 x 5 = 10 
2 x 6 = 12 
2 x 7 = 14 
2 x 8 = 16 
2 x 9 = 18 
3 x 1 = 3 
3 x 2 = 6 
3 x 3 = 9 
3 x 4 = 12 
3 x 5 = 15 
3 x 6 = 18 
3 x 7 = 21 
3 x 8 = 24 
3 x 9 = 27 
4 x 1 = 4 
4 x 2 = 8 
4 x 3 = 12 
4 x 4 = 16 
4 x 5 = 20 
4 x 6 = 24 
4 x 7 = 28 
4 x 8 = 32 
4 x 9 = 36 
5 x 1 = 5 
5 x 2 = 10 
5 x 3 = 15 
5 x 4 = 20 
5 x 5 = 25 
5 x 6 = 30 
5 x 7 = 35 
5 x 8 = 40 
5 x 9 = 45 
6 x 1 = 6 
6 x 2 = 12 
6 x 3 = 18 
6 x 4 = 24 
6 x 5 = 30 
6 x 6 = 36 
6 x 7 = 42 
6 x 8 = 48 
6 x 9 = 54 
7 x 1 = 7 
7 x 2 = 14 
7 x 3 = 21 
7 x 4 = 28 
7 x 5 = 35 
7 x 6 = 42 
7 x 7 = 49 
7 x 8 = 56 
7 x 9 = 63 
8 x 1 = 8 
8 x 2 = 16 
8 x 3 = 24 
8 x 4 = 32 
8 x 5 = 40 
8 x 6 = 48 
8 x 7 = 56 
8 x 8 = 64 
8 x 9 = 72 
9 x 1 = 9 
9 x 2 = 18 
9 x 3 = 27 
9 x 4 = 36 
9 x 5 = 45 
9 x 6 = 54 
9 x 7 = 63 
9 x 8 = 72 
9 x 9 = 81

do~while문에 의한 문장의 반복

  • while문과의 차이점: 반복을 검사하는 시점
    • while문과는 반복 조건의 검사위치가 다르며, 이로 인해서 반복 영역을 최소한 1회 이상 실행한다는 점이 유일한 차이점
do  // 일단 실행!
{
   printf("Hello world! \n");
   num++;
}  while(num<3);  // 반복 여부 확인!

do~while문이 자연스러운 상황

  • 반복 영역이 무조건 한 번 이상 실행되어야 하는 상황
#include <stdio.h>

int main(void)
{
    int total=0, num=0;
    do
    {
        printf("정수를 입력해주세요.(종료를 원하시면 0): ");
        scanf("%d", &num);
        total+=num;
        printf("현재까지 더한 값: %d \n", total);
    } while (num);
    printf("최종합: %d \n", total);
    return 0;
}

// 결과
정수를 입력해주세요.(종료를 원하시면 0): 10
현재까지 더한 값: 10 
정수를 입력해주세요.(종료를 원하시면 0): 5
현재까지 더한 값: 15 
정수를 입력해주세요.(종료를 원하시면 0): 28
현재까지 더한 값: 43 
정수를 입력해주세요.(종료를 원하시면 0): 449
현재까지 더한 값: 492 
정수를 입력해주세요.(종료를 원하시면 0): 1372
현재까지 더한 값: 1864 
정수를 입력해주세요.(종료를 원하시면 0): 0    
현재까지 더한 값: 1864 
최종합: 1864

for문에 의한 문장의 반복

for문의 구조와 이해

  • 필수요소 1 = 초기식 - 반복을 위한 변수의 선언 및 초기화에 사용
  • 필수요소 2 = 조건식 - 반복의 조건을 검사하는 목적으로 선언됨
  • 필수요소 3 = 증감식 - 반복의 조건을 ‘거짓'으로 만드는 증가 및 감소 연산
for( 초기식 ; 조건식 ; 증감식 )
{
   // 반복의 대상이 되는 문장들
}
  • 반복의 횟수가 딱 정해진 경우엔 for문이 최선

'C' 카테고리의 다른 글

변수의 존재기간과 접근범위  (0) 2025.03.12
조건에 따른 흐름의 분기  (0) 2025.03.12
printf, scanf  (3) 2025.03.12
C 언어 자료형  (0) 2025.03.12
자료형 및 Byte 개념  (0) 2025.03.12

printf 함수 이야기

특수문자의 출력이 필요한 이유

  • 문자열에 포함이 되는 특수문자는 작은 따옴표로 묶어서 독립된 문자상수로도 존재할 수 있다.

⁠char ch='\n';⁠

  • 큰 따옴표는 문자열의 시작과 끝으로 해석이 되니, 큰 따옴표 자체의 출력을 원하는 경우에는 큰 따옴표 앞에 \ 문자를 붙이기로 함

⁠printf("앞집 강아지가 말했다. \"멍~! 멍~!\" 정말 귀엽다.");⁠

printf 함수의 서식지정

  • printf의 f는 formatted(서식이 지정된)을 의미 즉, 서식이 지정된 형태의 출력
  • 출력양식이 만들어진 상태에서 출력을 진행한다

“제 나이는 10진수로 12살, 16진수로 C살입니다.”

⁠"제 나이는 10진수로 %d살, 16진수로 %X살입니다." // 대문자 X면 알파벳 대문자, 소문자 x면 알파벳 소문자⁠

서식 문자의 종류와 그 의미

  • %d = char, short, int
  • %ld = long
  • %lld = long long
  • %u = unsigned int(부호 없는 10진수 정수)
  • %o = unsigned int (부호 없는 8진수 정수) 8진수를 8진수답게 출력하려면 %#o
  • %x, %X = unsigned int(부호 없는 16진수 정수) 16진수를 16진수답게 출력하려면 %#x
  • %f = float, double
  • %Lf\= long double
  • %e, %E = float, double(e 또는 E 방식의 부동소수점 실수)
  • %g, %G = float, double(값에 따라 %f와 %e 사이에서 선택)
  • %c = char, short, int(값에 대응하는 문자)
  • %s = char *(문자열)
  • %p = void *(포인터의 주소 값)

필드 폭을 지정하여 정돈된 출력 보이기

  • 출력의 형태는 기본적으로 오른쪽 정렬이다!
  • %8d = 필드 폭을 8칸 확보하고, 오른쪽 정렬해서 출력을 진행한다.
  • %-8d = 필드 폭을 8칸 확보하고, 왼쪽 정렬해서 출력을 진행한다.
#include <stdio.h>

int main(void)
{
    printf("%-8s %14s %8s \n", "이  름", "전공학과", "학년");
    printf("%-8s %14s %5d \n", "김동수", "전자공학", 3);
    printf("%-8s %14s %5d \n", "이을수", "캄퓨터공학", 2);
    printf("%-8s %14s %5d \n", "한선영", "미술교육학", 4);
    return 0;
}
 
// 결과
이  름   전공학과   학년 
김동수   전자공학     3 
이을수 캄퓨터공학     2 
한선영 미술교육학     4

scanf 함수

정수 기반의 입력형태 정의

  • scanf 함수는 printf 함수의 상대적인 기능
    • 어떻게 받아들일 거니?
    • 어디에 저장할까?
  • %d = 10진수 정수의 형태로 데이터를 입력 받는다.
  • %o = 8진수 양의 정수의 형태로 데이터를 입력 받는다.
  • %x = 16진수 양의 정수의 형태로 데이터를 입력 받는다.
#include <stdio.h>

int main(void)
{
    int num1, num2, num3;
    printf("세 개의 정수 입력: ");
    scanf("%d %o %x", &num1, &num2, &num3);

    printf("입력된 정수 10진수 출력: ");
    printf("%d %d %d \n", num1, num2, num3);
    return 0;
}

// 결과
세 개의 정수 입력: 12 12 12 // 똑같은 정수 12를 입력해도, 실제 저장되는 값에는 차이가 있다.
입력된 정수 10진수 출력: 12 10 18

실수 기반의 입력형태 정의

  • printf에서는 %f, %e, %g의 의미가 각각 달랐지만, scanf 함수에서는 ‘float형 데이터를 입력 받겠다' 라는 동일한 의미를 담고 있다.
  • %lf = double
  • %Lf = long double
#include <stdio.h>

int main(void)
{
    float num1;
    double num2;
    long double num3;

    printf("실수 입력1(e 표기법으로): ");
    scanf("%f", &num1);
    printf("입력된 실수 %f \n", num1);

    printf("실수 입력2(e 표기법으로): ");
    scanf("%lf", &num2);
    printf("입력된 실수 %f \n", num2);

    printf("실수 입력3(e 표기법으로): ");
    scanf("%Lf", &num3);
    printf("입력된 실수 %Lf \n", num3);
    return 0;
}

// 결과
실수 입력1(e 표기법으로): 1.1e-3
입력된 실수 0.001100 
실수 입력2(e 표기법으로): 0.1e+2
입력된 실수 10.000000 
실수 입력3(e 표기법으로): 0.17e-4
입력된 실수 0.000017
  • 위 결과를 바탕으로 알 수 있는 점
    • 실수의 입력과정에서 e 표기법을 사용해도 된다.
    • float, double, long double의 데이터 출력에 사용되는 서식문자는 각각 %f, %f, %Lf이다.
    • float, double, long double의 데이터 입력에 사용되는 서식문자는 각각 %f, %lf, %Lf이다.
  • 서식문자 %s가 문자열의 입력에 사용된다.

'C' 카테고리의 다른 글

변수의 존재기간과 접근범위  (0) 2025.03.12
조건에 따른 흐름의 분기  (0) 2025.03.12
반복 실행을 명령하는 반복문  (0) 2025.03.12
C 언어 자료형  (0) 2025.03.12
자료형 및 Byte 개념  (0) 2025.03.12

자료형(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

'C' 카테고리의 다른 글

변수의 존재기간과 접근범위  (0) 2025.03.12
조건에 따른 흐름의 분기  (0) 2025.03.12
반복 실행을 명령하는 반복문  (0) 2025.03.12
printf, scanf  (3) 2025.03.12
자료형 및 Byte 개념  (0) 2025.03.12
int main()
{
    // 자료형 (크기 단위, byte - 메모리 단위) Data Type
    // 정수형: char(1), short(2), int(4), long(4), long long(8)
    // 실수형: float(4), double(8)

    int i = 0;
    // i 라는 정수형을 선언하고 i의 크기는 4 byte이다.
    unsigned char c = 0;
    // unsigned = 양수의 정수만 표현

    c = 0;
    c = 256; // 오류
    // 오류가 난 이유: 1 byte는 8 bit로 총 256가지의 경우의 수를 가짐,
    // unsigned를 사용해 양수의 정수만을 가지도록 정한 char는 1 byte의 크기를 가지므로 0 ~ 255의 수를 가질 수 있는데,
    // 256을 대입했으므로 오류가 발생

    return 0;
}

// 1 byte = 8 bit
// bit = 더 이상 쪼갤 수 없는 단위, 0과 1로만 이루어 짐 True or False

 

int main()
{
    // 자료형 (크기 단위, byte - 메모리 단위) Data Type
    // 정수형: char(1), short(2), int(4), long(4), long long(8)
    // 실수형: float(4), double(8)

    int i = 0;
    // i 라는 정수형을 선언하고 i의 크기는 4 byte이다.
    unsigned char c = 0;
    // unsigned = 양수의 정수만 표현
    // 256 가지 -> 0 ~ 255
    c = 0;
    c = 255;

    char c1 = 0;
    // 양수와 음수를 모두 표현(signed)
    // 256 가지 -> -128 ~ 0 ~ 127
    c1 = -1;
    // 음의 정수 찾기(2의 보수법)
    // 대응되는 양수의 부호를 반전 후, 1을 더한다.
    // ex) 0 0 0 0 0 0 1 0 = 2 / -2를 찾는다면
    // 1 1 1 1 1 1 1 0 = -2 
    return 0;
}

// 1 byte = 8 bit
// bit = 더 이상 쪼갤 수 없는 단위, 0과 1로만 이루어 짐 True or False

'C' 카테고리의 다른 글

변수의 존재기간과 접근범위  (0) 2025.03.12
조건에 따른 흐름의 분기  (0) 2025.03.12
반복 실행을 명령하는 반복문  (0) 2025.03.12
printf, scanf  (3) 2025.03.12
C 언어 자료형  (0) 2025.03.12

+ Recent posts