변수

AleXtep·2023년 3월 10일

C 언어

목록 보기
3/3

Notion link : https://melon-taker-d3e.notion.site/3-1-90e463fb742f4326a8388aa75030a64c

변수 선언

  • l-value, r-value

정수 데이터 타입

  • Range of data types
자료형범위
booltrue 또는 false
char-128 ~ 127
short-32,768 ~ 32,767
int-2,147,483,648 ~ 2,147,483,647
long long-9,223,372,036,854,775,808 ~ 9,223,372,036,854,775,807
float1.2 x 10^-38 ~ 3.4 x 10^38
double2.2 x 10^-308 ~ 1.8 x 10^308
  • 컴파일러는 처리를 위해 0에서 127 사이 (ASCII 코드)의 정수로 문자를 변환합니다. ch1 = 'A'이면 값 65가 ch1에 저장됩니다. 출력 형식은 변환 문자 (%d, %c)에 의해 결정됩니다.

sizeof 연산자

sizeof 연산자는 변수 또는 데이터 유형의 크기를 바이트 단위로 결정하는 데 사용됩니다. 이는 int, double, float, char와 같은 기본 데이터 유형뿐만 아니라 구조체와 클래스와 같은 사용자 정의 데이터 유형과 함께 사용할 수 있습니다.

다음 예제 코드는 구조체와 sizeof 연산자를 사용하여 구조체의 크기와 멤버 변수의 크기를 계산합니다.

#include <stdio.h>

struct person {
    char name[50];
    int age;
    float height;
};

int main() {
    struct person p1;
    printf("The size of the person struct is %d bytes\\\\\\\\n", sizeof(struct person));
    printf("The size of the name member variable is %d bytes\\\\\\\\n", sizeof(p1.name));
    printf("The size of the age member variable is %d bytes\\\\\\\\n", sizeof(p1.age));
    printf("The size of the height member variable is %d bytes\\\\\\\\n", sizeof(p1.height));
    return 0;
}

위 코드를 실행하면 다음 출력이 표시됩니다.

The size of the person struct is 58 bytes
The size of the name member variable is 50 bytes
The size of the age member variable is 4 bytes
The size of the height member variable is 4 bytes

위 코드에서 person 구조체는 58 바이트 크기이며 name 멤버 변수는 50 바이트이며 ageheight 멤버 변수는 각각 4 바이트 크기입니다.

sizeof 연산자의 구문은 다음과 같습니다.

sizeof(type);

여기서 type은 유효한 데이터 유형 또는 변수가 될 수 있습니다.

예를 들어 정수 변수의 크기를 바이트 단위로 찾으려면 다음 문을 사용할 수 있습니다.

printf("The size of an integer variable is %d bytes", sizeof(int));

이는 대부분의 현대적인 시스템에서 정수 변수의 크기를 일반적으로 4 바이트로 출력합니다.

sizeof 연산자는 부호 없는 정수형 size_t의 값으로 반환됨에 유의하세요.

size_t 유형은 부호 없는 정수를 저장하는 데 사용되는 데이터 유형입니다. 이는 sizeof 연산자와 같은 목적으로 사용됩니다. size_t는 시스템에 따라 크기가 다르며 일반적으로 unsigned int와 동등합니다. 데이터 유형의 크기가 양수인 경우에 사용하기 적합합니다.

Unsigned integer datatype

  • 한정된 데이터 크기에서 양수만 저장하면 두배넓게 사용가능 → unsigned를 사용
#include <stdio.h>

int main() {
    unsigned int a = 4294967295;
    int b = -1;
    printf("unsigned a = %u, signed b = %d\\\\n", a, b);
    printf("unsigned a = %d, signed b = %d\\\\n", a, b);
    return 0;
}

Output:

unsigned a = 4294967295, signed b = -1
unsigned a = -1, signed b = -1

이 코드는 unsigned intint 자료형을 사용하여 변수 ab를 선언합니다. a에는 4294967295를 할당하고, b에는 -1을 할당합니다. 첫 번째 printf 문은 ab%u%d 변환 문자와 함께 출력합니다. 두 번째 printf 문은 ab를 둘 다 %d 변환 문자와 함께 출력하고 있습니다.

%u를 사용하여 unsigned int 변수를 출력할 때는 부호 없는 값으로 출력됩니다. 이는 %d를 사용하여 출력할 때와는 달리 값의 부호가 없기 때문입니다. 따라서 첫 번째 printf 문은 a의 값을 올바르게 출력합니다. 그러나 b는 부호 있는 변수이므로 -1을 출력합니다.

두 번째 printf 문에서 %d 변환 문자를 사용하여 a를 출력하면, 부호있는 int 변수로 간주되어 값이 부호화됩니다. a의 값이 4294967295이므로 이것은 부호화 된 int 값의 최대 값 2147483647보다 큽니다. 이는 정수 오버플로우를 일으키고, 이것이 부호화된 값 -1로 해석되어 출력된 이유입니다.

실수 자료형

  • 데이터 구현방법이 정수와 다름
  • float, double, long double 로 구별
자료형크기 (byte)
float4
double8
long double16

다음은 유효숫자를 파악하는 코드입니다.

#include <stdio.h>

int main() {
    float f = 12345.67890123456789;
    double d = 12345.67890123456789;

    printf("float 유효숫자: %.20f\\n", f);
    printf("double 유효숫자: %.20lf\\n", d);

    return 0;
}

출력값:

float 유효숫자: 12345.67871093750000000
double 유효숫자: 12345.67890123456789000

초기값과 출력값이 다른 이유는 float과 double이 표현할 수 있는 범위와 정밀도가 다르기 때문입니다. float은 4바이트(32비트)이며, double은 8바이트(64비트)입니다. float은 약 7자리의 유효숫자를 가지며, double은 약 16자리의 유효숫자를 가집니다. 따라서 float에서는 12345.67890123456789라는 값을 정확하게 표현할 수 없으므로 근사치인 12345.67871093750000000으로 출력됩니다. 반면 double은 12345.67890123456789라는 값을 정확하게 표현할 수 있으므로, 초기값과 출력값이 같습니다..

IEEE 754 부동소수점 방식으로 표현했을 경우, 23자리까지 유효 비트이며, 2의 23승은 10의 7승과 유사하기 때문에 십진수 경우 7자리까지 유효 숫자입니다.

#include <stdio.h>

int main() {
    double d = 0.1;

    printf("double 저장값: %.20lf\\n", d);

    return 0;
}

위 코드를 실행하면 다음과 같은 출력이 나타납니다.

double 저장값: 0.10000000000000000555

float과 double 부동소수점 방식으로 12345.67890123456789을 표현하면 다음과 같습니다.

자료형부호비트지수비트가수비트
float01000001100111100000011010001110
double0100000000100011110000001101000111001011000111110101110000100111
  • 그래서 정수형을 기본으로 사용 실수형은 필요한 경우만 사용
  • 실수형에서 유효숫자가 많은 double형을 기본으로 사용
  • 그러나 유효숫자 내의 수도 2진수 변환시 무한소수로 변환되면 오차 발생

문자열 저장

  • 문자열은 char형을 배열형태로 만들어 저장
char 배열명[문자열길이+1]=문자열;
  • 문자열을 저장할 때는 배열의 마지막에 null 문자(\\0)를 추가해야 합니다. 이는 문자열의 끝을 표시하는 특별한 문자입니다. null 문자를 빠뜨리면 문자열을 처리하는 함수가 제대로 동작하지 않을 수 있습니다. 예를 들어, 다음 코드에서는 문자열 str을 출력할 때 null 문자를 빠뜨렸기 때문에 예상치 못한 결과를 출력합니다.
    #include <stdio.h>
    
    int main() {
        char str[5] = "hello";
        printf("%s", str);
        return 0;
    }
    
    출력값:
    hellorv▒
    
    위 코드에서 str 배열의 크기는 5이므로, 문자열 "hello"와 null 문자(\0)를 모두 저장할 수 있는 크기입니다. 그러나 null 문자(\0)를 생략하고 문자열을 출력하면 예상치 못한 결과가 출력됩니다. 따라서 문자열을 저장할 때는 null 문자(\0)를 반드시 추가해야 합니다.
    char str[6] = "hello";
    
    위 코드에서는 문자열 "hello"와 null 문자(\\0)를 모두 저장할 수 있도록 배열의 크기를 6으로 지정하였습니다.
  • char 배열에 문자열 저장하고 출력
#include <stdio.h>

int main() {
    char str[6] = "hello";
    printf("%s", str);
    return 0;
}

Output:

hello

문자열에 새로운 문자 저장

C 언어에서 새로운 문자열을 배열에 저장하는 방법은 memcpy()strcpy() 함수를 사용하는 것입니다.

memcpy()

memcpy() 함수는 메모리 영역을 복사하는 데 사용됩니다. 아래 예시는 memcpy() 함수를 사용하여 문자열을 배열에 복사하는 코드입니다.

#include <stdio.h>
#include <string.h>

int main() {
    char src[] = "Hello, world!";
    char dest[20];

    memcpy(dest, src, strlen(src) + 1);

    printf("src: %s\\\\\\\\\\\\\\\\n", src);
    printf("dest: %s\\\\\\\\\\\\\\\\n", dest);

    return 0;
}

src 배열에 문자열 "Hello, world!"를 저장하고, dest 배열에 src 배열의 내용을 memcpy() 함수를 사용하여 복사합니다. strlen() 함수는 문자열의 길이를 반환하며, + 1은 NULL 문자를 포함하기 위한 것입니다.

strcpy()

strcpy() 함수는 문자열을 복사하는 데 사용됩니다. 아래 예시는 strcpy() 함수를 사용하여 문자열을 배열에 복사하는 코드입니다.

#include <stdio.h>
#include <string.h>

int main() {
    char src[] = "Hello, world!";
    char dest[20];

    strcpy(dest, src);

    printf("src: %s\\\\\\\\\\\\\\\\n", src);
    printf("dest: %s\\\\\\\\\\\\\\\\n", dest);

    return 0;
}

src 배열에 문자열 "Hello, world!"를 저장하고, dest 배열에 src 배열의 내용을 strcpy() 함수를 사용하여 복사합니다.

결과 비교

memcpy()strcpy() 함수 모두 src 배열의 내용을 dest 배열에 복사합니다. 하지만 둘의 차이점은 NULL 문자 처리에 있습니다. memcpy() 함수는 NULL 문자를 복사하지 않습니다. 따라서 복사된 문자열이 정확한 문자열인지 확인하려면 NULL 문자를 수동으로 추가해야 합니다. 반면 strcpy() 함수는 NULL 문자를 복사하므로 추가 작업이 필요하지 않습니다.

문자열을 저장할 때 null 문자(\\\\\\\\0)를 생략하면 문자열을 처리하는 함수가 제대로 동작하지 않을 수 있습니다. 예를 들어, 다음 코드에서는 문자열 str을 출력할 때 null 문자를 빠뜨렸기 때문에 예상치 못한 결과를 출력합니다.

#include <stdio.h>

int main() {
    char str[5] = "hello";
    printf("%s", str);
    return 0;
}

출력값:

hellorv▒

str 배열의 크기는 5이므로, 문자열 "hello"와 null 문자(\\0)를 모두 저장할 수 있는 크기입니다. 그러나 null 문자(\\0)를 생략하고 문자열을 출력하면 예상치 못한 결과가 출력됩니다. 따라서 문자열을 저장할 때는 null 문자(\\0)를 반드시 추가해야 합니다.

const를 사용한 변수

  • const 키워드를 사용하여 상수를 선언할 수 있습니다. 상수는 한 번 정해지면 값을 변경할 수 없습니다.
    const int a = 100;
    
  • const 키워드를 사용하여 변수를 선언하면, 해당 변수는 읽기 전용이 됩니다. 따라서 값을 변경하려고 하면 컴파일러가 오류를 발생시킵니다.
    const int a = 100;
    a = 200; // 컴파일 오류 발생
    
  • const 키워드를 사용하여 함수 매개변수를 선언하면, 해당 매개변수에 전달되는 값이 변경되지 않도록 보장할 수 있습니다.
    void print(const char* str) {
        printf("%s", str);
    }
    
    int main() {
        char* s = "hello";
        print(s);
        return 0;
    }
    
  • const 변수를 초기화하는 방법에는 두 가지가 있습니다.
    1. 첫번째 방법은 변수를 선언하면서 값을 할당하는 것입니다.

      const int a = 100;
      
    2. 두 번째 방법은 변수를 선언하고, 나중에 값을 할당하는 것입니다. 이때는 const 키워드 앞에 extern 키워드를 사용하여 선언합니다.

      // const.h
      extern const int a;
      
      // const.c
      #include "const.h"
      const int a = 100;
      
      // main.c
      #include "const.h"
      int main() {
          printf("%d", a);
          return 0;
      }
      

      const 키워드를 사용하면, 변수의 값을 변경할 수 없다는 것을 명시적으로 나타낼 수 있습니다. 이는 코드의 가독성을 높이고, 프로그램의 안정성을 높입니다.

      다음은 const 변수를 사용하여 간단한 소스 코드 예시입니다. 변수 aconst로 선언하고, a 값을 출력하는 코드입니다.

      #include <stdio.h>
      
      int main() {
          const int a = 100;
          printf("%d", a);
          return 0;
      }
      

      출력 결과:

      100
      

예약어와 식별자

  • 예약어 : 컴파일러와 사용방법이 약속된 단어
  • 식별자 : 필요에 따라 만들어 사용하는 단어

정수형과 실수형 데이터형의 종류, 크기, 값의 저장 범위, 출력 및 변환 문자에 대한 표입니다.

데이터형종류크기 (바이트)값의 저장 범위변환문자
char부호 있는 정수형1-128 ~ 127%c %d
unsigned char부호 없는 정수형10 ~ 255%u
short부호 있는 정수형2-32,768 ~ 32,767%d
unsigned short부호 없는 정수형20 ~ 65,535%u
int부호 있는 정수형4-2,147,483,648 ~ 2,147,483,647%d
unsigned int부호 없는 정수형40 ~ 4,294,967,295%u
long부호 있는 정수형4-2,147,483,648 ~ 2,147,483,647%ld
unsigned long부호 없는 정수형40 ~ 4,294,967,295%lu
long long부호 있는 정수형8-9,223,372,036,854,775,808 ~ 9,223,372,036,854,775,807%lld
unsigned long long부호 없는 정수형80 ~ 18,446,744,073,709,551,615%llu
float실수형41.2E-38 ~ 3.4E+38%f
double실수형82.2E-308 ~ 1.8E+308%lf
long double실수형123.4E-4932 ~ 1.1E+4932%Lf
profile
Full-Stack Developer

0개의 댓글