C언어 변수 타입 출력 - Ceon-eo byeonsu taib chullyeog

*C언어 변수타입

// 문제 : 변수를 만들고 3.14를 넣은 후 출력해보세요.(가장 메모리를 효율적으로 사용해주세요.)
#include "stdio.h"
   
int main(void) {
  int i = 3.14;
  
  printf("1st 시도 => i : %d\n", i); // 실패 => i 에는 오직 정수만 들어간다.
  
  float f = 3.14;
  
  printf("2nd 시도 => f : %d\n", f); // 실패 => `%d`는 데이터를 `int 로 해석하겠다.`라는 뜻 입니다.

  printf("3nd 시도 => f : %f\n", f);
  
  return 0;
}



// 문제 : 변수를 만들고 200을 넣은 후 출력해보세요.(가장 메모리를 효율적으로 사용해주세요.)
#include "stdio.h"

int main(void) {
  unsigned char i = 200;
  
  printf("i : %d\n", i);
  return 0;
}



// 문제 : 변수를 만들고 21억을 넣은 후 출력해보세요.(가장 메모리를 효율적으로 사용해주세요.)
#include "stdio.h"

int main(void) {
  int s = 2100000000;

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



// 문제 : 변수를 만들고 22억을 넣은 후 출력해보세요.(가장 메모리를 효율적으로 사용해주세요.)
#include "stdio.h"

int main(void) {
  int s = 2200000000;

  printf("1st 시도 => s : %d\n", s); // 실패, %d는 int로 취급된다. int는약 -21억부터 +21억까지 표현가능 하다.

  unsigned int k = 2200000000;

  printf("2st 시도 => k : %u\n", k);

  int q = 2200000000;

  printf("3st 시도 => q : %ld\n", q);
  
  return 0;
}



// 문제 : 변수를 만들고 400억을 넣은 후 출력해보세요.(가장 메모리를 효율적으로 사용해주세요.)
#include "stdio.h"

int main(void) {
  long s = 40000000000;
  
  printf("s : %ld", s);
  
  return 0;
}

*C언어 변수 크기 확인 ( sizeof(변수명) )

* 변수 크기 확인 (sizeof)
// 문제 : char와 unsigned char의 공간크기를 각각 출력해주세요.
// 힌트 : sizeof(변수) or sizeof(타입)
// 힌트 : sizeof 함수는 해당 매개변수의 공간크기를 반환합니다.
#include <stdio.h>

int main(void) {
  printf("char의 크기 : %lu\n", sizeof(char));
  printf("unsigned char의 크기 : %lu\n", sizeof(unsigned char));

  char c;
  unsigned char uc;

  printf("c의 크기 : %lu\n", sizeof(c));
  printf("uc의 크기 : %lu\n", sizeof(uc));

  return 0;
}

*모든 변수 타입의 크기 (바이트)

- 1 byte = 8 bit

// 문제 : C언어에 있는 모든 기본타입변수의 크기를 출력해주세요.

#include <stdio.h>

int main(void) {
    // 정수 계열
  char c; // 1바이트(돌 8개)
  short s; // 2바이트(돌 16개)
  int i; // 4바이트(돌 32개)
  long l; // 8바이트(돌 64개)
  
  // 실수 계열
  float f; // 4바이트(돌 32개)
  double d; // 8바이트(돌 64개)

  printf("char c변수의 크기 : %lu 바이트\n", sizeof(c));
  printf("short s변수의 크기 : %lu 바이트\n", sizeof(s));
  printf("int i 변수의 크기 : %lu 바이트\n", sizeof(i));
  printf("long l 변수의 크기 : %lu 바이트\n", sizeof(l));
  printf("float f 변수의 크기 : %lu 바이트\n", sizeof(f));
  printf("double d 변수의 크기 : %lu 바이트\n", sizeof(d));
  
  return 0;
}

*C언어 포인터

// 문제 : 변수 i의 값을 해킹해주세요.
// 조건 : i의 값을 직접 바꾸는 것은 안됩니다.
// 조건 : `i = 50;` 은 안됩니다.
#include <stdio.h>

int main(void) {
  int i = 30;

  // p는 i의 실제주소값을 가리킨다.
  int* p = &i;

  // p안에 들어있는 값을 메모리 상의 좌표값으로 인식하고 그 주소대로 찾아간다.(그러면 변수 i가 나온다.)
  *p = 50; // `i = 50;` 과 완벽히 같은 의미이다.

  printf("i : %d\n", i);
  // 출력 => i : 50

  return 0;
}



// 문제 : 변수 c의 값을 해킹해주세요.
// 조건 : c의 값을 직접 바꾸는 것은 안됩니다.
// 조건 : `c = 220;` 은 안됩니다.
#include <stdio.h>

int main(void) {
  unsigned char c = 200;

  unsigned char* p = &c;
  *p = 220;

  printf("c : %d\n", c);
  // 출력 => c : 220

  return 0;
}

프로그래밍 언어를 통틀어 변수는 매우 중요한 개념이다. 

변수(variable)란 프로그램에서 일시적으로 데이터를 저장하는 공간으로, 프로그래의 성능과 코드의 재사용성에 중요한 역할을 한다.

 변수를 사용하는 이유 

아래의 두 코드를 비교해 보자.

// 가로와 세로를 받아 사각형의 면적을 출력하는 프로그램

... //width와 height를 scanf로 받음

printf("면적은 %d", width*height);

...

width와 height를 받아 출력문에서 계산하여 바로 보여줄 수 있다.

// 가로와 세로를 받아 사각형의 면적을 출력하는 프로그램

... //width와 height를 scanf로 받음

int area;

area = width*height;

printf("면적은 %d", area);

...

이는 area 변수를 할당하여 면적을 구해준 뒤 출력문에서 area를 출력한다.

코드의 길이로 보면 위의 코드가 더 간결해서 더 효율적인 코드로 보일 수 있지만, 아래의 코드가 더 권장된다. 이유는 아래의 상황들로 이해할 수 있을 것이다.

만약 해당 면적의 2배에 해당하는 면적도 구해달라는 요청이 올 수도 있다. 또는 1/2에 해당하는 면적도 구해달라고 할수도 있다. 그 때 마다 출력문을 바꾸어 주어야 한다.

또는 주석 없이 아무것도 모르는 개발자가 저 코드를 맞이하게 될 수도 있다. area라는 변수 명 없이 width*height를 보고 면적을 구하는 것이구나! 를 직관적으로 알기 힘들 수 있다.(지금은 간단한 코드이지만 복잡할 수록 변수명이 없다면 코드를 이해할 수 없게 된다.)

그렇지만 이런 변수를 남용해서는 안된다. 프로그램의 성능관리를 위해 변수의 자료형을 구분하는 것은 필수적이다.

변수의 자료형

변수는 다양한 값을 보관하는 하나의 박스라고 생각하면 된다. 값을 변경할 수 없는 상수는 뚜껑이 닫힌 상자라고 생각하면 되겠다.

그런데 모든 값을 하나의 모양과 사이즈의 상자에 넣으면 다양한 문제가 발생할 것이다.

모양이 안맞거나 사이즈가 너무 작아 값을 넣을 수 없거나, 사이즈가 너무 커서 값을 보관하고도 낭비되는 공간이 많을 수 있는 것이다. 

그래서 변수에 자료형을 두어 구분한다. 상자의 모양과 사이즈를 지정해주는 과정이라고 생각하면 된다.

자료형은 크게 3가지가 있다.

숫자(정수), 숫자(실수), 문자. 사실은 문자형도 정수형에 포함된다.

C언어 변수 타입 출력 - Ceon-eo byeonsu taib chullyeog

범위를 초과하여 값을 저장하려고 하면 예상치 못한 값, 즉 쓰레기값이 저장된다.

구분 크기(byte) 범위
정수형 char 1 -128 ~ 127
short 2 -32768 ~ 32767
int 4 -2,147,483,648 ~ 2,147,483,647
long 4 -2,147,483,648 ~ 2,147,483,647
long long 8 -9,223,372,036,854,775,808 ~ 9,223,372,036,854,775,807
실수형 float 4 (3.4 X 10-38) ~ (3.4 X 1038)
double 8 (1.7 X 10-308) ~ (1.7 X 10308)
long double 8 (1.7 X 10-308) ~ (1.7 X 10308)

위의 표 보다는 아래의 그림이 더 외우기 쉬울 것 같다.

C언어 변수 타입 출력 - Ceon-eo byeonsu taib chullyeog

정수형

소수점 없는 수를 담는 타입이다. 그 중 가장 많이 사용하는 타입은  int형으로, 최대 2147483647 까지 값을 담을 수 있다. 운영체제마다 다르지만 보편적인 64bit의 경우 4바이트로 처리한다.

실수형

소수점이나 지수가 있는 수를 담는 타입이다. 예전 코드나 글을 확인하면 float 형이 많이 쓰이는 것을 확인할 수 있지만. 최근 추세는  double형임을 알아두면 좋겠다.

문자형

말 그대로 숫자가 아닌 문자 값을 담는 타입이다. " ''와 같은 따옴표를 사용하여 표현해도 되고, 아스키코드(ASCII)값을 사용하여 값을 지정해도 된다. 위에서 문자형도 정수형에 포함된 이유는, 사실 C는  char 자체를 아스키코드 숫자(정수)값으로 처리하고 있기 때문이다.

예를들어 다음 코드를 보자.

int num = 1;
char character = '1';

둘다 1이지만, 이 둘을 모두 숫자형으로 출력했을 때에는 num은 1 , character는 49로 출력될 것이다. 문자 1의 ASCII 코드 값이 49이기 때문이다.

반대로 이 둘을 모두 문자형으로 출력했을 때에는 num은 SOH가 출력될 것이다. ASCII 1은 Start of Header 문자형을 뜻하기 때문이다.

 서식 지정자 

서식지정자는 해당 변수를 출력할 때 출력 형식을 지정해준다.

예를 들어 int 타입 변수를 출력한다면 %d를 사용하는 식이다.

C언어 변수 타입 출력 - Ceon-eo byeonsu taib chullyeog

이렇게 int 형인 grade%d로 출력해주고, char가 여러개인 문자열 형인 name%s로 출력해준다. 이 때, 해당 변수의 주소값을 알려줘야 그 주소에 있는 값 1과 world를 출력해주므로 변수명 앞에 &를 붙여줘야 한다.

C언어 변수 타입 출력 - Ceon-eo byeonsu taib chullyeog

종종 쓰이는 서식 지정자들만 표로 정리해보았다.

float 형이라고 꼭 %f로만 출력해야하는 것은 아니다. float 형을 int형 서식 지정자인 %d로 출력하면 소숫점이 잘린 채 출력될 것이다.

또한 어떤 변수를 %p로 출력하면 그 변수의 주소가 출력될 것이다.

변수를 잘 관리하는 것은 개발자의 기본적인 임무이다. 아주 기초적인 내용이면서도 그렇기에 대충 사용할 수도 있는 부분이니, 한번 잘 배워두면 좋다고 생각한다.

C언어 , C++ , 서식 지정자 , 출력 형태 , 변수 , 자료형 , type , 타입 , 변수의 개념 , 상수의 개념 , 자료형의 개념 , data type , 쉽게 풀어쓴 c언어 Express 제 4장