[C언어] #2 헷갈리는 문법 및 키워드 정리
모든 변수들은 블럭의 시작에 선언되어야 한다.
함수
C언어는 함수를 사용하기 전에 함수를 선언해줘야 한다. (전방선언)
- 선언되지 않은 함수를 바로 사용하면 컴파일 에러
- 함수 반환형, 이름, 매개변수 자료형을 파일의 제일 위(혹은 헤더파일)에 미리 표기해둔다
한 줄에 있는 피연산자들은 평가순서를 보장하지 않는다
-
함수 매개변수의 평가 순서는 컴파일러마다 다를 수 있다.
/* add(), substract(), divide() 코드 생략*/ int result = add(num1, num2) + substract(num1, num2) * divide(num1, num2);
-
위와 같은 코드에서 어떤 함수가 먼저 실행될지? 알수없다.
-
연산자 우선순위가 높은 함수가 먼저 호출될까? 관계없다.
-
다음 코드의 실행 순서는 어떻게될까?
if (++i || ++j && ++k)
||
,&&
연산자는 시퀀스 포인트 (실행 순서를 보장해주는 포인트)- 연산자 우선순위에 의해 &&조건에 괄호
- if (
++i
||( ++j && ++k)
)
- if (
- ++i 실행
- i = 1
- if (
true
||(++ j && ++k)
)
- short circuit 평가에 의해
true
반환 종료- A or B 일때 A가 true이면 B를 볼 필요없이 true이다.
- 연산자 우선순위에 의해 &&조건에 괄호
-
-
한 함수의 매개변수들이 동일한 변수를 수정할 경우, 결과가 정의되지 않음
- 연산자는 피연산자의 평가 순서를 보장하지 않는다.
- 어떤 연산이 먼저 수행될지 알 수 없고, 동시에 비트를 건드려 값이 깨질 수도 있다.
- 확실한 시퀀스 포인트
;
를 사용해서 명확히 순서를 정의하자.
/* 안 좋은 사용 예 */ int main(void){ int num = 10; num = ++num + num++; printf("num : %d\n", num); } i = ++i + i++; i = i++ + 1; array[i] = i++;
전역 변수
-
전역 변수는 어디서든 접근할 수 있다 (장점이자 단점)
-
스택 메모리에 들어가지 않고 데이터 섹션에 들어간다.
C 메모리 구조
스택 힙 데이터 코드
extern
- 전역 변수를 A 파일에서 선언 후 B파일에서 사용하려고 하면 오류가 발생한다.
- 왜냐하면 소스파일은 각각 따로 컴파일 되기 때문에 컴파일 과정에서 다른 파일에 있는 전역 변수를 알 방법이 없기 때문이다.
- 이럴 때 사용할 수 있는 키워드가 바로
extern
extern
키워드는 다른 파일에 정의된 전역 변수들을 사용할 수 있게 해준다.- B 파일에서 사용하려고 하는 변수 앞에
extern
키워드를 붙여서 선언 하면 A 파일에 있는 전역변수에 접근할 수 있다. - 모든 파일에서 접근가능하도록 하려면 헤더에
extern
변수를 선언해주고 해당 헤더를 include해서 사용하면 된다.
static
- 내 파일에 전역변수를 다른 파일에서 사용 못하도록 하고싶을 때 사용할 수 있는 키워드
extern
키워드 써서 접근하려고 해도 링커 오류 발생- 함수 내에 지역변수로 사용된
static
변수는 함수 내에서만 접근 가능하지만, 함수가 리턴되도 값이 초기화 되지 않는다. static
변수는 스택 메모리에 저장되지 않고 데이터 영역에 저장된다.- 전역 변수 뿐만 아니라 함수 앞에도 사용가능하다
const
상수를 선언할 때 붙이는 키워드로서 변수의 값을 변경할 수 없도록 한다.
-
변경하지 말아야할 변수를 변경하는 오류를 방지할 수 있다.
- 기본적으로 많이 사용해서 값이 의도하지 않게 변하는 것을 방지해주는 것이 좋다.
- 함수의 매개변수에서도 사용이 가능하다.
int calculate_risk(const int id){ int age = db_get_age(id); int amount; /* 코드 생략 */ id += 2; /* 컴파일 오류 */ /* 코드 생략 */ amonut = db_get_deposit_amount(id); return amount; }
goto
코드를 실행 후 특정한 위치로 이동해서 코드를 실행시키고 싶을 때 사용하는 키워드
goto <label_name>;
/* */
<label_name>:
- 반복문, 조건문도 내부적으로는
goto
를 사용하는 코드- 어셈블리어를 까보면 거의 똑같이 동작
- 반복문은 다시 처음으로
goto
- 조건문은 특정 블록을 건너뛰고
goto
- goto는 가독성을 떨어트리기 쉽기 때문에 사용을 주의해야 한다.
- goto가 유용한 경우
- 여러개의 루프를 한번에 탈출하고 싶을 때
- 한 함수 안에 여러 조건문이 공통된 코드를 실행해야 할 때
- 함수를 만들자니 유지보수의 문제, 함수를 안만들자니 코드 중복문제가 있을 때 유용
- 실제 linux, apple 등 많은 프로그램 코드를 보면 goto를 사용하고 있다.
- 동적메모리 할당 후 해제할 때
- 항상 아래쪽으로만 점프하도록 사용하는 것이 좋다.
배열
C언어는 배열요소의 값을 알아서 초기화해주지 않는다. (변수도 마찬가지)
배열의 모든 요소 0으로 초기화하는 best practice
int nums[10] = {0, } /* ,가 있어서 이해가 쉽고 가독성이 좋다. */
다차원 배열
아래의 두 배열은 실제 메모리 상에서 볼 때 똑같은 배열이다. 2차원 배열도 메모리 상에서는 순서대로 저장된다.
/* 2차원배열 */
int buffer[3][2];
int i;
int j;
for (i = 0; i < 3; i++){
for (j = 0; j < 2; j++){
buffer[i][j] = 0;
}
}
/* 1차원 배열 */
int buffer[3 * 2];
int i;
int j;
for (i = 0; i < 3; i++){
for (j = 0; j < 2; j++){
buffer[i * 2 + j] = 0;
}
}
Author And Source
이 문제에 관하여([C언어] #2 헷갈리는 문법 및 키워드 정리), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://velog.io/@ilhoon93/C언어-문법-간단-정리저자 귀속: 원작자 정보가 원작자 URL에 포함되어 있으며 저작권은 원작자 소유입니다.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)