STUDY

c언어 개념 정리

Lim임 2025. 11. 6. 16:49

C 언어 프로그래밍 핵심 정리

1. 연산자

  • 산술: +, -, *, /, % (정수 나눗셈은 소수부 버림)
  • 대입: =, +=, -=, *=, /=, %=, <<=, >>=, &=, ^=, |=
  • 증감: ++x, x++ (전위/후위 평가 시점 차이)
  • 비교: ==, !=, <, <=, >, >= (결과는 정수 0/1)
  • 논리: &&, ||, ! (단락 평가)
  • 비트: &, |, ^, ~, <<, >>
  • 조건(삼항): cond ? a : b
  • 주소/간접: &(주소), *(역참조)
  • 크기: sizeof(표현식|타입) (컴파일 타임)
  • 우선순위(높음→낮음) 개요:
    • 단항(증감, 부호, !, ~, 캐스트, sizeof, &, *)
    • * / %+ - → 시프트 → 비교 → 등가 → 비트 AND → 비트 XOR → 비트 OR → 논리 AND → 논리 OR → 삼항 → 대입 → 콤마

2. 분기문

  • if
    • 형태: if (조건) 문장;
  • if–else
    • 형태: if (조건) 문장1; else 문장2;
  • if–else if–else
    • 위에서부터 첫 참인 분기만 실행
if (x > 0) {
    puts("pos");
} else if (x == 0) {
    puts("zero");
} else {
    puts("neg");
}

3. 반복문

while

  • 형태: while (조건) { 본문 }
  • 조건이 처음부터 거짓이면 0회 실행

이중 while(중첩)

int i = 0;
while (i < 3) {
    int j = 0;
    while (j < 2) {
        printf("%d,%d\n", i, j);
        j++;
    }
    i++;
}

무한 루프

  • while (1) { ... } 또는 for (;;) { ... }
  • 종료 경로(조건, break, return)를 반드시 설계
for (;;) {
    int c = getchar();
    if (c == EOF) break;
}

for문

  • 형태: for (초기식; 조건; 증감식) { 본문 }
  • 초기식/증감식 생략 가능. 조건 생략 시 참으로 간주.
for (int i = 0; i < n; i++) {
    // ...
}

break & continue

  • break: 가장 안쪽 반복문 또는 switch를 즉시 탈출
  • continue: 현재 반복의 나머지를 건너뛰고 다음 반복으로
    • for: 증감식 실행 후 조건 검사
    • while/do-while: 조건 검사로 이동

4. 함수

  • 선언/정의/호출
    int add(int a, int b);        // 선언(프로토타입)
    int add(int a, int b) {       // 정의
      return a + b;
    }
    

int r = add(2, 3); // 호출

- 반환값이 없으면 `void`
- 인자 전달은 값에 의한 복사만 존재
- 지역 변수 수명: 블록 종료 시 소멸
- 필요 시 헤더로 프로토타입 분리

---

## 5. 변수의 범위와 static
- 범위(scope)
  - 블록 범위: `{}` 내부에서만 유효
  - 파일 범위: 함수 밖에서 선언 → 해당 번역 단위에서 유효
- 수명(storage duration)
  - 자동(auto): 블록 진입 시 생성, 종료 시 소멸
  - 정적(static): 프로그램 시작~종료까지 존속
- 링크(linkage)
  - 외부 링크: 파일 간 참조 가능(전역 변수/함수 기본)
  - 내부 링크: `static` 전역 → 해당 소스 파일 내에서만 참조
- static의 용도
  - static 지역 변수: 호출 간 값 유지
  - static 전역: 심볼 가시성을 파일로 제한

```c
void counter(void) {
    static int c = 0; // 최초 1회 초기화
    printf("%d\n", ++c);
}

6. 배열

배열을 사용해야 하는 이유

  • 동일 타입의 연속 메모리를 인덱스로 관리
  • 캐시 지역성 확보로 효율적 접근
  • 고정 크기 데이터 집합에 적합

선언, 초기화

int a[5];                 // 자동 영역: 초기화 안 하면 indeterminate
static int b[5];          // 정적 영역: 0으로 초기화
int c[5] = {1, 2, 3};     // 나머지는 0
char s1[] = "abc";        // {'a','b','c','\0'}
char s2[5] = {'h','i','\0'}; // 문자열로 사용 가능

문자열과 null 문자('\0')의 필요성

  • C의 문자열은 null-종단 방식
  • 문자열 함수(strlen, printf("%s"), strcpy 등)는 '\0'까지 처리
  • 누락 시 버퍼 경계 초과 접근(UB) 발생

다차원 배열

int m[2][3] = { {1,2,3}, {4,5,6} }; // 행 우선(row-major)

제약

  • 배열 간 대입 불가: a = b; (불가)
  • 함수 인자로 전달 시 첫 원소 주소로 decay

7. 포인터

  • 정의: 특정 타입 객체의 주소를 저장하는 변수
    ```c
    int x = 10;
    int *p = &x; // 주소 보관
  • p = 20; // 역참조로 x 변경
    ```
  • 포인터 산술: p+1은 다음 요소 주소(요소 크기만큼 이동)
  • void*: 임의 포인터. 역참조 전 적절한 타입으로 변환 필요
  • NULL: 유효하지 않은 주소 표현
  • 주의: 경계 밖 접근, 해제 후 사용(dangling), 이중 해제, 잘못된 캐스팅 등은 정의되지 않은 동작

8. JavaScript에서의 “포인터”

  • 포인터 언어 기능 없음
  • 원시 타입(Number, String, Boolean 등): 값 복사
  • 객체/배열/함수: 변수에는 “참조 값”이 저장되며, 대입 시 참조 값이 복사됨
  • 함수 인자도 값 복사. 객체의 “참조 값”이 복사되므로, 매개변수를 통해 객체 내부를 바꾸면 원본이 변함. 단, 매개변수에 새 객체를 대입해도 바깥 변수는 변하지 않음
function f(o) { o.x = 1; o = { x: 2 }; }
const a = { x: 0 };
f(a);
// a.x === 1, a가 새 객체로 바뀌지는 않음

9. 배열과 포인터(C)

  • 배열 이름의 decay: 대부분의 식에서 배열명 → 첫 요소에 대한 포인터
    • 예외: sizeof(배열), &배열, 문자열 리터럴 초기화 등
  • 인덱싱: a[i] == *(a + i)
  • 차이점
    • 배열: 고정 크기, 메모리를 자체 소유, sizeof(a)는 전체 바이트
    • 포인터: 주소만 보유, sizeof(p)는 포인터 크기
int a[10];
int *p = a;      // &a[0]와 동일
sizeof(a);       // 예: 40 (int가 4바이트일 때)
sizeof(p);       // 예: 8  (64비트 포인터)

10. 값에 의한 복사와 “참조 효과”

  • C는 값에 의한 복사만 제공
  • 원본 수정 필요 시 포인터 인자를 사용하여 간접 변경
void swap_by_value(int a, int b) { int t=a; a=b; b=t; } // 실패
void swap_by_ptr(int *a, int *b) { int t=*a; *a=*b; *b=t; } // 성공

int x=1, y=2;
swap_by_value(x, y);    // x,y 변화 없음
swap_by_ptr(&x, &y);    // x=2, y=1

함수 포인터(필요 시)

int add(int a, int b) { return a + b; }
int (*fp)(int, int) = add;
int r = fp(2, 3);

11. 실수 방지 요점

  • 입력 처리 시 버퍼 크기 엄수(fgets 권장)
  • 동적 메모리 malloc/free 쌍 관리, 소유권 명확화
  • 논리 연산의 단락 평가 고려(부작용 함수 호출 배치 주의)
  • 비교와 대입 혼동 금지(== vs =)

중요포인트

포인터
배열의 첫번째 값의 주소가 배열의주소값임

참조에 의한 복사가 짱쎈복사다