카테고리 없음

[C89] C언어 기본 문법

Chunghyun Lee 2023. 1. 15. 09:00

목차

1. 헬로월드

2. C언어의 기본 문법

2-1. 다양한 것

2-2. 스택 메모리

 

헬로월드

#include

#include의 동작 방법

C의 #include는 헤더 파일(*.h)을 열어서 그 내용을 복붙

 

main(void) 함수

C 코드를 빌드해서 나온 실행파일(.exe 또는 .out)을 실행하면 자동으로 실행(프로그램의 진입점)

반드시 int 반환 -> return 0; /* 프로그램에 문제가 없었다는 뜻 */

 

프로그램 종료 코드 확인하기

- echo %errorlevel%(윈도우 CMD 기준)

- $ echo $?(Shell)

 

C언어의 기본 문법

기본 자료형

signed가 기본(char는 예외)

unsigned는 사용하려면 명시해줘야함

 

char 

최소 8비트

1바이트 = CHAR_BIT(char 크기)

ASCII 문자(0~127인 숫자) 표현 충분

기본이 signed/unsigned인지 컴파일러 구현에 따라 달라짐

이유?

ASCII는 부호 상관없이 표현 가능

단, 8비트 정수형으로 쓸 때는 signed나 unsigned 넣어주는 게 좋음

포팅에 문제 없는 범위

short

최소 16비트 && sizeof(char) <= sizeof(short)

안전 범위

크기: 16비트

범위:

- 부호 없는 경우: 0 ~ 65535

- 부호 있는 경우: -32768 ~ 32767

 

int

최소 16비트 && sizeof(short) <= sizeof(short)

왜 최소 16비트?

int는 그냥 '정수'라는 의미

CPU가 딱 아는 크기 = 워드 크기

예전에는 16비트 CPU가 흔했음 그래서 최소 16비트

32비트 컴퓨터가 나오면서 int 크기는 32비트가 됨

안전 범위

크기: 32비트

범위:

- 부호 없는 경우: 0 ~ 4294967295

- 부호 있는 경우: -2147483648 ~ 2147483647

 

리터럴

부호 있는 수의 최댓값보다 큰 값을 unsigned int에 대입할 경우 U를 붙여야함

 

long

포팅 안전 범위: -2147483648 ~ 2147483647

int와 같음

 

float

32비트

double

64비트

long double

 

크기는 컴파일러마다 다른데 대충 위의 크기 안전

셋다 unsigned형 없음 -> 접미사 u 안씀

 

리터럴 UL

 

bool

없음

0이면 false, 0이 아니면 true

 

enum

int와 섞어서 사용 가능

int -> enum, enum -> int, enum -> 또 다른 enum

C에서 열거형은 그냥 정수에 별명 붙이는 수준

 

enum color { COLOR_BLACK, COLOR_WHITE, /* 생략 */ };
enum day { DAY_MONDAY, DAY_THESDAY, /* 생략 */ };

enum day hump_day = DAY_WEDNESDAY;
enum color favorite_color = hump_day /* 컴파일 됨 */

 

sizeof()

함수 아님 연산자임(피연산자의 크기를 바이트로 반환)

- 컴파일 도중 찾음(컴파일 할 때 모르는 크기는 못찾음)

- size_t 반환(보통 unsigned int)

 

비트패턴 -1 반환

signed int -1 = unsigned int 4294967295

size_t get_students_index(const char* name)
{
    if(!/*조건*/) {
        return (size_t)-1;
    }
    
    return 올바른_인덱스;
}

 

switch/case 문

- case에 정수형(int, char, enum)만 가능

- break 빼먹으면 -> fall-through

주의 사항

fall-through 의도한 거면

/* intentional fallthrough */ 주석 달아주기

 

함수

- C의 함수는 기본적으로 모두 전역 함수

- 오버로딩 안됨

- 함수 선언 -> 링크: 선언 없으면 C89 컴파일러는 int 반환한다고 가정

 

평가순서

- 한 줄에 있는 피연산자들은 기본적으로 평가 순서 보장 X

예외

- &&

- ||

- 삼항 연산자

- ;

 

파일 범위

- 블록, 매개변수 목록에 안 속하고 파일 안에 있는 것

- 스택X, 데이터 섹션에 들어감

 

 

goto

베스트 프랙티스

- 아래쪽으로만 점프

- 내포된 루프에서 빠져나올 때

- 한 함수 안에 있는 여러 개의 조건문이 공통된 코드를 실행해야 할 때

 

배열

스택 메모리

- 함수의 지역 변수 등을 임시적으로 저장하는 공간

- 스택 메모리의 크기는 프로그램 빌드 시에 결정

- 스택 메모리의 위치는 실행 시에 결정

- 기본 자료형을 함수 매개변수로 전달하면 스택에 복사본을 만듦 -> 이게 바로 값형

- new로 만든 데이터는 힘 메모리에 할당

 

배열을 매개변수로 전달할 때는 셀제 모든 요소를 스택에 넣지 않음

배열의 시작 위치(주소)를 넣어줌

 

매개변수에 배열의 길이를 명시해 주면?

 

void process(int nums[5])
{
    size_t i;
    for(i = 0; i < 5; ++i) {
        nums[i] *= 2;
    }
}

 

- 이건 그냥 프로그래머의 가독성을 위한 것

- 컴파일 하면 void process(int nums[])와 동일

 

그러면 함수에서 배열의 요소에 접근하려면 길이를 알아야하는데 이건 어찌앎?

- 다음처럼 배열의 길이 n을 매개 변수로 받아야함

 

void process(size_t n, int nums[])
{
    size_t i;
    for(i = 0; i < n; ++i) {
        nums[i] *= 2;
    }
}

 

배열 초기화

- C는 배열 요소의 값 초기화 안해줌 -> 그전에 그 메모리에 남아있던 값 그대로 사용(쓰레기 값)

- 직접 초기화 해야함

 

int nums[10] = { 0, };

 

버퍼 오버플로도 조심

 

다차원 배열

1차원 vs 2차원 vs 3차원 (메모리)

메모리상에선 똑같음