자료형, C의 bool, enum, 연산자, sizeof, size_t, for, switch

markyang92·2023년 1월 30일
0

C

목록 보기
2/7
post-thumbnail
  • unsigned / signed를 생략하면 '부호 있음 (signed)'이 기본
    • 예외: char
      • C표준에서 정의하지 않았음
      • 컴파일러마다 다름
        • clang에서 찍어보면 char = signed
        • 내 컴퓨터의 gcc-11.3.0 에선 char = unsigned

char

  • 최소 8bit인 정수형
  • 어떤 컴파일러를 사용하냐에 따라, 8,9,16 bit 일 수 있음

<limit.h> CHAR_BIT

  • 현재 사용하는 컴파일러에서 char가 몇 비트인지 알 수 있음
  • C기준 표준에서 CHAR_BIT는 이 컴퓨터에서 가장 작은 자료형
    • 즉, CHAR_BIT8bit이면, 이 컴퓨터의 1Byte = 8bit

<limit.h> CHAR_MIN

  • <limit.h> 헤더파일에서, CHAR_MIN를 보면, 부호 식별자가 없은 charsinged ? unsigned ? 알 수 있다.

short

  • 최소 >= 16bit && char 크기 이상의 정수형

int

  • 표준: 최소 >= 16bit && short 크기 이상인 정수형
  • 그냥 정수(integer)의 의미
  • CPU가 자기에게 가장 적합하다고 생각하는 기본 데이터 크기: word
    • word = 레지스터 크기

  • 그 이후, 32bit, 64bit가 나옴
    • 32bit 컴퓨터 부터, int의 크기는 32bit
    • 64bit 컴퓨터...는 64bit? .. 그래도 32bit로 머묾
      • 원칙적으로 말하면 C 표준을 어긴 것
  • 그냥 32bit로 머물고 있다.
  • unsigned int : 0 ~ 4294697295
  • signed int : -2147483648 ~ 2147483647

int signed_int = -1024;
unsigned int unsigned_int1 = 394;
unsigned int unsigned_int2 = 2147483648; <---- 경고 나옴 signed int 범위 벗어남 (unsigned int 로 해도)
unsigned int unsigned_int3 = 2147483648u; <---- 경고 없음, 대문자 U 도 가능
  • literal
    • 'u' 혹은 'U' : unsigned 수를 표현하는 접미사
    • 안 붙이면 경고 발생

long

  • long: 최소 32bit && int 이상의 크기 (....)
    • 그래서 보통 32bit
    • 포팅 안전한 범위: -2147483647 ~ 2147483647
  • 그럼 최소 64bit 정수형은?
    • C89에는 없음

long signed_long = -200000000l;      <--- 대문자 L도 가능
unsigned long unsigned_long1 = 2147483647;
unsigned long unsigned_long2 = 2147483648; <---- 경고 나옴 signed long 범위 벗어남 (unsigned long 로 해도)
unsigned long unsigned_long3 = 2147483648ul; <---- 경고 없음
  • literal
    • l || L : long을 의미하는 접미사
    • u || U : 부호 없는(unsigned) 수를 표현하는 접미사
    • 두 접미사를 같이 쓸 수 있음 (unsigned long)이라는 의미가 됨
2147483648UL
2147483648lu
2147483648LU
2147483648ul

지금까지 자료형 정리 (C89)

type최소보통
char최소 8bit보통 8bit
short최소 16bit보통 16bit
int최소 16bit보통 32bit
long최소 32bit보통 32bit

float

float num = 3.14f; <--- F도 가능
float num = 3.0f;
float num = 3.f;
  • float IEEE 754 single(32bit)
  • double IEEE 754 double(64bit)
  • 하지만, C는 CPU가 IEEE 754를 지원하는 실수 계산 장치를 장착하기 전부터 쓰임
  • 표준: float은 IEEE 754가 아닐 수 있음
    • C89: 컴파일러 구현에 따라 다름
  • unsigned

double

double num = 3.4;
  • CPU가 계산에 사용하는 기본 데이터 크기
  • float 이상의 크기면 됨
  • 컴파일러 구현에 따라 다름

long double

long double num = 3.14;
  • double보다 정밀도가 높음
  • double 이상의 크기면 됨
  • gcc의 경우 double 보다큼

명심할 교훈

  • Embedded System에서는 매뉴얼에서 자료형의 크기를 확인 후 사용할 것
  • Porting 용 코드
    • 포팅이 보장되는 범위 값만 사용할 것
    • float, double은 플랫폼 사이에 값이 정확히 일치하지 않을 수 있음
  • 그냥 int 쓰자

C 의 bool

  • C89 : 없음
  • C99 : 이상한 형태로 들어옴
  • 그냥 0이면 false
  • != 0이면 true

enum

  • int와 섞어서 사용 가능 (명시적인 캐스팅 없이도)
    • int -> enum
    • enum -> int
    • enum -> enum
  • C에서 열거형은 그냥 정수에 별명 붙이는 수준


연산자

우선순위연산자
1++ -- 후위 증감
() 함수 호출
[] 배열 첨자
. 구조체, 공용체 멤버 접근자
-> 구조체, 공용체 멤버 접근자(포인터)
2++ -- 전위 증감 연산자
+ - 단항 연산자
! 논리 부정 연산자
~ bit 부정 연산자
(자료형) 자료형 캐스팅
* 역 참조(혹은 간접참조)
& 주소
sizeof 피연산자의 크기를 알려주는 연산자
3* / % 곱하기, 나눗셈 (몫), 나눗셈(나머지)
4+ - 덧셈 뺄셈
5<< >> 왼쪽/오른쪽 비트 이동 연산자
6< <= 비교연산자
> >= 비교연산자
7== != 비교 연산자
8& 비트 AND 연산자
9^ 비트 XOR 연산자
10| 비트 OR 연산자
11&& 논리 AND 연산자
12|| 논리 OR 연산자
13?: 삼항 연산자 (연산자 결합법칙 <- )
14=, +=, -=, *=, /=, %=, <<=, >>=, &=, ^=, \=
15,

&&, ||는 평가 순서를 강제함

  • 논리 연산자 &&, ||의 경우 왼쪽 연산자를 먼저 실행
    • 왼쪽 피연산자의 평가만으로 오른쪽 피연산자를 평가 안 할 수 있음
      • hp++|| mp++
        • 왼쪽 피연산자가 이면, 오른쪽 연산자 평가 안함
      • exp++&& atk++
        • 왼쪽 피연산자가 거짓이면, 오른쪽 연산자 평가 안함

sizeof()

  • 피연산자의 크기를 Byte 로 반환 해주는 연산자. 함수 아님
char ch = 'a';
int num = 100;
char char_array[30];

size_t size_char = sizeof(ch); /* 1 */
size_t size_int = sizeof(num); /* 4 */
size_t size_float = sizeof(float); /* 4 */
size_t size_array = sizeof(char_array); /* 30 */
  • 배열의 경우, 함수 인자로 받을 경우 다른 결과가 나온다.

배열의 요소 크기를 찾자.

  • 방법 1
const size_t num_vals = sizeof(values) / sizeof(values[0]);
  • 방법 2
/* 함수 밖에서*/
#define ARRAY_LENGTH(arr) (sizeof(arr) / sizeof(arr[0]))


/* 매크로 함수 사용*/
const size_t num_vals = ARRAY_LENGTH(values);


배열 사이즈 함수로 구할때 주의

  • sizeof() 가 매개변수로 들어온 배열의 총 바우트 수를 반환할 수 있으려면
    • 그 배열의 모든 요소가 스택에 다 복사되어 전달되어야 함
int func(int num, int data[]);

int main(void)
{
	int score; /* 10 */
    int values[3]; /* { 2, 3, 4} */
    do_func(score, values);
}

  • 함수는 호출자가 누구든 간에 딱 정해진 수와 크기의 매개변수가 들어온다는 가정으로 동작
  • 함수가 먼저 결정되고 호출자는 그 함수를 호출할 뿐
  • 즉, 함수는 호출자가 뭐하는지 모른다.
  • 함수의 스택 사이즈는 언제가 결정되어 있다.

이렇게 넘겨주자.

void func(size_t n, int data[])
{
	size_t i;
    for(i=0; i<n; i++){
    	data[i] = data[i]++;
}

size_t

  • size_t: 부호 없는 정수형의 상수, 즉 실제 데이터형은 아님
    • _t: typedef를 했다는 힌트
    • typedef는 다른 자료형에 별칭을 붙이는 것

vcruntime.h

#ifdef  WIN64
	typedef unsigned    int64 size_t;  <--- 64bit 운영체제일 경우 unsigned __int64 (64bit)
    typedef __int64     ptrdiff_t;
    typedef __int64     intptr_t;
#else
    typedef unsigned int      size_t;  <-- 그외 운영체제일 경우 unsigned int (32bit)
....
  • C89 표준은 size_t의 크기를 딱히 명시하지 않음
  • 다행히, C99 표준에서 확실히 최소 16비트를 요구함
  • 보통은 unsigned int 사용
typedef unsigned int size_t;

size_t의 용도

  • 어떤 것의 크기를 나타내기 위해 사용
  • 좋은 예: 반복문이나 배열에 접근할 때 사용
int int_array[30];
size_t i;

for (i = 0; i < 30; ++i) {
    int_array[i] = i;
}

for (size_t = 0; i<30; ++i) {
	int_array[i] = (int)i;
}
size_t checker(const char* name){
    if(!조건){
    	return (size_t)-1;
    }
    return 0;
}

switch/case

  • C는 정수형(int, char, enum)만 가능
const char* name = "Banana";
switch (name) {
case "Apple": <-- 오류!
}
  • case 안에서 break가 없다면?
    • switch문을 곧바로 탈출하지 않고 그 아래 있는 코드 실행
    • 보통 다른 case, default 레이블에 있는 코드
    • 다른 곳에서 breakswitch 블록의 끝에 도착하면 탈출
  • 이렇게 계속 아래에 있는 코드를 실행하는 것을 fall-through 라고 함
enum fruit { FRUIT_APPLE, FRUIT_MANGO };
enum fruit fruit = FRUIT_APPLE;

switch (fruit) {
case FRUIT_APPLE:
	printf("Breakfast\n");      <--- 실행 후
    /* internal fallthrough */  <--- 의도적 break;를 사용하지 않은 경우 옆 주석을 꼭 붙이자!
case FRUIT_MANGO:
	printf("Lunch\n");          <--- fallthrough로 아래 실행
    break;
default:
	printf("Unknown food\n");
    break;
}    

for

  • std=89 는 아래처럼 하면 컴파일 오류
int sum=0;

for(size_t i=0; i<10; ++i){
    sum+=i;
}

gcc -std=89 -W -Wall -pedantic-errors main.c -o main



printf()

변수타입서식 지정자
int%d
unsigned int%u
long%ld
unsigned long%lu
long long%lld
unsigned long long%llu
size_t%zu
ssize_t%zd
profile
pllpokko@alumni.kaist.ac.kr

0개의 댓글