19 – 값을 변경할 수 없는 변수

변수인데도 불구하고 값을 변경할 수 없는 변수가 있다. 선언할 때에만 값을 지정하고 그 이후에는 값을 바꾸지 못하게 하는데, const를 선언할 때 앞에 붙여주면 된다.

const int a = 10;

이렇게 하면 a값은 10으로 고정되어 바꿀 수 없다. 일부러 바꾸려고 하면 오류가 날 것이다. 컴파일러가 오류를 내기 때문에 오류를 직접 예시로 보여주기로 한다.

%e1%84%89%e1%85%b3%e1%84%8f%e1%85%b3%e1%84%85%e1%85%b5%e1%86%ab%e1%84%89%e1%85%a3%e1%86%ba-2017-02-08-%e1%84%8b%e1%85%a9%e1%84%92%e1%85%ae-5-02-22

18 – 데이터형의 이름 바꾸기

데이터 형의 이름이 너무 긴 경우이거나 특정하게 지정하고 싶을 경우에는 typedef를 사용해 데이터형의 이름을 별도로 만들 수 있다. 구조는 다음과 같다.

typedef [기존 데이터형] [새로 지정할 데이터형 이름];

예를 들어, unsigned int를 줄여서 u_int라고 만들고 싶으면 다음과 같이 만든다.

typedef unsigned int u_int;

그리고 실제 사용은 u_int를 이용하여 똑같이 선언한다.;

u_int data = 10;

typedef의 경우에는 주로 함수 바깥에 선언을 하여 사용을 한다. 또한 구조체와 같은 복잡한 자료구조를 다루고 할 때 많이 쓰이고 해서 구조체 설명할 때 좀 더 내용이 자세히 들어갈 것이다만, 실제로 사용하는 모습이 어떤지는 기본 구조를 예시로 작성하였다.

17 – 변수 (문자열형)

문자를 나열한 문자열을 저장하는 변수로, char형을 배열(연속된 저장공간. 배열에 대해서는 나중에 천천히 보도록 하겠음.)을 이용하여 문자열형을 저장한다. 배열에 대해서는 아래와 같이 여러개의 문자 변수가 연속으로 있는 상황이다. 여기에 “abc”를 저장하면, 아래와 같이 저장된다.

각각의 변수는 str[0] ~ str[3] 이런 순으로 들어있다. 이것까지 확인할 수 있는 예시를 만들어봤다.

분자열 변수도 선언과 동시에 초기화할 수 있다. 같은 예시를 동시에 초기화하는 것을 보여주는 예시를 다음과 같이 만들어봤다.

위에 있던 예제에서는 각 문자를 변수에 일일이 저장하였었다. 근데 수많은 문자열을 저렇게 일일이 할 수는 없기 때문에 문자열을 별도로 다루는 함수들이 존대한다. strcpy 함수를 이용하면 문자열을 배열에 한번에 저장할 수 있는데, strcpy(s, t) 함수는 문자열 t를 s에 복사하는 함수이다. string.h 헤더 파일에 정의되어 있기 때문에 헤더를 하나 더 추가해준다. 역시 아래 예시를 보면 알 수 있다.

문자열을 다룰 수 있는 함수들은 여러모로 있기 때문에 별도로 문서를 다뤄야 한다.

16 – 변수 (문자형)

하나의 문자를 저장하기 위한 데이터형으로 메모리 크기가 1바이트인 char형 변수를 이용한다.

상수 편에서도 이야기하였듯 모든 문자에는 대응되는 정수값이 있다. 즉, char형 변수에 저장할 수 있는 것은 문자 그대로뿐만 아니라 문자에 대응하는 숫자 또한 저장될 수 있다는 것이다. 이것을 같이 확인하기 위해서 예시를 작성하였다.

15 – 변수 (부동소수점)

부동소수점형은 실수이다. float, double, long double 이 셋을 주로 이용한다. 이들 데이터형으로 표현할 수 있는 값의 범위도 확인해야 한다. 그리고 부동소수점에 대해서는 컴퓨터 구조, 마이크로아키텍쳐 이론에서 볼 수 있듯이 오차를 가지고 있다.

데이터형 / 바이트 폭 / 표현 범위 / 상수 표현

float / 4 / 약 10^-38 ~ 10^38 / 7.7F

double / 8 / 약 10^-308 ~ 10^308 / 7.7

long double / ? / ? / 7.7L

이런 부동소수점을 사용하는 것은 예시를 통해서 확인해본다.

14 – 변수 (고정소수점)

고정소수점형은 정수를 의미하는 것으로, int, short int, long int, unsigned int 등이 있고 표현할 수 있는 값의 범위는 시스템에 따라 차이가 있지만 리눅스 시스템에서는 다음과 같다고 보면 된다. 바이트 폭의 경우에는 해당 데이터형의 변수를 선언할 때 배정되는 메모리의 크기를 말한다.

데이터형 / 바이트 폭 / 포현 범위 / 상수 표현

int / 4 / -2147483648 ~ 2147483648

short int / 2 / -32768 ~ 32767 / 77

long int / 4 / -2147483648 ~ 2147483647 / 77L

unsigned int / 4 / 0 ~ 4294967295 / 77U

이러한 데이터 형의 크기는 sizeof 연산자를 이용해 적접 확인할 수 있는데, 아래 프로그램처럼 구현해서 확인할 수 있다.

도중에 생긴 warning의 경우에는 sizeof가 출력하는 long unsigned int를 그대로 int로 받아서 그러는 건데, 문제는 없다.

이런 데이터 형의 크기는 왜 알아야 하냐면, 데이터 형의 크기에 따라 입력 및 출력할 수 있는 영역이 정해지고, 이를 고려하지 않으면 문제가 발생한다. 문제가 발생하는 프로그램의 예제를 다음과 같이 짜 보았다. int형의 표현할 수 있는 범위를 넘어선 연산을 진행해보도록 하겠다. 연산 결과로는 3000000000이 나와야 하지만, int형의 표현 범위를 넘어섰기 때문에 엉뚱한 결과가 나왔다. 이렇게 변수의 범위값을 넘어가는 상황을 오버플로우라고 하는데, 이상한 값을 출력하고 한다.

컴파일 했을 때, 오류에 overflow in expression이라고 나와있는데, 이것이 오버플로우가 된다는 경고이다. 실행은 되는데 실제로 실행하면 이상한 값을 내는 것이다.

그리고 변수를 선언할 때 값을 변수에 넣어서도 할 수 있다.

13 – 변수 (데이터형)

변수를 선언하는 방식은 앞에 글에서 봤듯이 데이터형과 함께 선언을 한다.

데이터형 변수이름;

데이터형은 변수에 저장된 값의 형태를 결정하는 것이다. 그래서 해당 데이터형으로 선언하면 변수는 그 데이터형에 종속된 크기를 가지게 된다. 앞에서 봤던 예제에 있던 result의 경우에는 정수형 숫자가 들어갈 수 있도록 되어있다. 다른 형태가 들어가면 경고 혹은 오류를 발생할 것이다.

그리고 변수는 여럿을 동시에 선언할 수 있다. 아래와 같이 선언하면 세 개의 변수를 동시에 선언하는 것과 같다.

float f1, f2, f3;

12 – 변수

일반적인 프로그램에서는 데이터를 입력받아야 하는데, 입력받은 데이터를 저장할 공간이 필요하다. 또한 간단한 수치 계산을 하는 프로그램에서도 연산 결과를 저장할 공간이 필요하다. 이러한 공간을 변수라고 한다.

변수는 프로그램이 실행되는 동안 데이터를 저장할 수 있는 영역으로, 메모리에 생성된다. 그리고 이 영역에 저장된 내용은 변수 이름을 이용해 사용할 수 있다. 변수를 이용한 간단한 프로그램은 아래와 같다. result하는 int형 변수를 선언하였고, 이 변수에 계산된 결과를 저장하여 printf로 출력중이다.

변수는 이름을 지정해야 하는데, 변수 이름은 만들 때에는 규칙에 따라서 만들어야 한다.

  • 사용할 수 있는 문자는 영문 대/소문자, 수치 문자, 밑줄(_)의 63개 문자다.

사용할 수 없는 문자는 다음과 같다.

  • 첫 번째 문잔는 영문자이거나 밑줄(_)이어야 한다. 수치 문자로 시작할 수 없다.
  • 예약어를 변수 이름으로 사용할 수 없다.

이러한 규칙에 따라 변수 이름으로 사용 불가능한 경우를 살펴보자.

  • kyuling@mail: 사용할 수 없는 문자 (@)
  • 2017year: 수치 문자로 시작
  • -test: -로 시작
  • int: 예약어이므로 사용 불가

마지막으로, 변수 이름은 대소문자를 구분한다. 그래서 test, TEST, Test 이 셋은 서로 다른 변수가 된다.