Notice
Recent Posts
Recent Comments
Link
«   2026/02   »
1 2 3 4 5 6 7
8 9 10 11 12 13 14
15 16 17 18 19 20 21
22 23 24 25 26 27 28
Tags
more
Archives
Today
Total
관리 메뉴

KNK Chap.6 (6.5~Q&A) 본문

C

KNK Chap.6 (6.5~Q&A)

Daryl 2022. 12. 19. 20:55

6.5 null문

 

구문은 무형null의 형태를 띨 수 있음. 즉 세미콜론을 제외하고 아무 기호도 없는 구문임.

예를 들어 아래의 코드를 보면

i = 0; ; j = 1;

이 줄에는 3개의 구문이 있음. i 할당문, null 구문, j 할당문.

어디서 많이 본 모양같지 않음? 맞음. 본문이 비어있는 루프에 null문이 쓰임.

예를 들어 6.4에서 배웠던 소수 찾기 루프를 다시 보면

for (d = 2; d < n; d++) {
	if ( n % d == 0) {
    	break;
    }
}

 여기서 n % d == 0 조건문을 제어식으로 옮기면 아래와 같이 루프 본문이 비게 되는데

for (d = 2; d < n && n % d != 0; d++) {
/* 비어있는 루프의 본문 */;
}

null문을 for문 바로 밑에 새 줄에다가 적었음. 같은 줄에 적어도 무방함.

근데 for문의 본문을 쉽게 파악하게 만들기 위해서 새 줄에 표시해주는 것임.

루프가 돌 때마다 조건 d < n이 먼저 검사됨. 거짓이면 루프 종료되고, 참이면 다음 조건 검사됨.

→ d < n 이 참이라면 n % d != 0 또한 참이어야 함. n의 나눗수를 찾았기 때문임.

 

[!!!] 실수로 if, while, for문의 괄호 이후에 세미콜론을 적어주면 null문이 생성됨.

그럼 해당 문법은 실행되지 않음. 예를 들어 아래와 같은 경우들임.

 

○ 이렇게 if문에서 괄호 이후에 세미콜론이 나오면 if문의 본문이 if문의 제어식 결과값과 상관없어짐.

if (d == 0); /*** WRONG ***/
printf("Error: Division by zero\n");

그러나 printf 함수의 호출은 if문의 본문 구문이 아니라서 d가 0과 같든 다르든 실행됨.

 

○ while문의 경우 아래와 같이 무한루프가 될 수 있음

i = 10;
while (i > 0); /*** WRONG ***/
{
	printf("T minus %d and counting\n", i);
    --i;
}

또는 아래와 같이 실행되어야 하는 구문이 한번만 실행되고 루프가 종료될 수 있음

i = 11;
while (--i > 0); /*** WRONG ***/
	printf("T minus %d and counting\n", i);

실행하면 T minus 0 and counting 이라고 출력됨

 

○ for문 또한 루프가 딱 한번 실행되고 끝날 수 있음

for (i = 10; i > 0; --i); /*** WRONG ***/
printf("T minus %d and counting\n", i);

이 코드도 실행하면 T minus 0 and counting 이라고 출력됨

 

→ 그래서 null문이라도 빈 중괄호를 사용하는게 가독성, 통일성을 높임

 

Q&A

 

Q: 6.1에서 나온 루프를 좀 더 짧게 만들어도 되지 않나? 가령 >0을 빼도 작동은 똑같이 하는듯.

while (i > 0) {
	printf("T minus %d and counting\n", --i);
}

이 코드를

while (i) {
	printf("T minus %d and counting\n", --i);
}

이렇게 바꿔도 되지 않느냔 말임

 

A: 그렇게 하면 단점이 생김.

1. 가독성이 떨어짐. 원래는 i > 0이란 제어식만 봐도 어떤 루프인지 감이 오는데,

저렇게 적으면 i를 통해 숫자를 증가시키면서 수를 세는지, 감소시키면서 세는지 바로 알 수 없음.

2. i가 음수가 되어도 바로 종료되지 않음. 원래 코드는 바로 종료됨.

 

Q: 6.3에서 언급을 미뤘던, for문이 while문으로 치환되지 않는 경우는?


A: for문의 루프에 continue문이 있는 경우. 예를 들어 아래의 코드처럼

n = 0;
sum = 0;
while (n < 10) {
	scanf("%d", &i);
    if (i == 0) {
    	continue;
    }
    sum += i;
    ++n;
}

여기서 보면 i가 0일 때 n은 증가되지 않음. 근데 이걸 for문으로 비슷하게 짜보면

sum = 0;
for (n = 0; n < 10; ++n) {
	scanf("%d", &i);
    if (i == 0) {
    	continue;
    }
    sum += i;
}

이 코드는 i가 0일 때도 n을 증가시킴.

 


Q: while (1)과 for(;;) 중 어떤 무한루프를 쓰는 것이 더 나은가?

 

A: 사실 현대 컴파일러 기준에서는 둘의 성능 차이가 없음. 

옛날 컴파일러에서는 while문의 1 조건을 매번 검사해서 효율성 때문에 for (;;) 선호가 더 많았음.

 


Q: continue문은 웬만하면 실무에서 쓰지 말라고 하던데 사실인가?

 

A: 잘 안 쓰긴 함. 근데 while문에서는 써도 무방함.

예를 들어 입력값을 받는 루프 작성 중에 입력값이 유효값이면 특정 처리가 되게 하고 싶다 치자.

이 유효값 판별 코드가 복잡할 경우, continue문은 유용함. 예를 들어 아래 코드처럼.

for (;;) {
	read data;
    if (data fails first test) {
    	continue;
    }
    if (data fails second test) {
    	continue;
    }
    .
    .
    .
    if (data fails last test) {
    	continue;
    }
    process data;
}



Q: goto문은 왜 안 좋은가? [루프에서 벗어나기]


A: goto문 자체가 나쁘고 좋은게 아니고, goto문보다 더 나은 방법이 있으니까 그걸 쓰라는 것임.

왜냐면 goto문은 가독성이 떨어짐. 뒤로도 가고 앞으로도 갈 수 있어서 소위 "스파게티 코드"가 됨.

goto문은 코드의 특정 부분이 여러 일을 할 수 있게 만들어놔서 수정도 까다로움.

그러니까 웬만하면 더 편한 문법을 추천함.

 

 

Q: null문은 루프 본문 비우는 것 말고도 용도가 또 있는가?


A: 실무에선 딱 하나 있음. 복합문 마지막에 라벨 넣을 때 null문 넣어주는 경우.

라벨은 반드시 뒤에 구문이 따라와야 하기 때문임. 예를 들어 아래의 코드처럼.

{
	...
    goto end_of_stmt;
    ...
    end_of_stmt: ;
}

 

Q: null문 말고도 빈 루프를 만들 수 있는가? [null문]


A: continue를 사용하거나

for (d = 2; d < n && n % d != 0; ++d) {
	continue;
}

빈 복합문을 사용해도 됨

for (d =2; d < n && n % d != 0; ++d) {
}

 

 

 

 

 

 

 

 

'C' 카테고리의 다른 글

KNK 공부 중단  (0) 2023.02.07
KNK Chap.7 (7.1)  (1) 2022.12.19
KNK Chap.6 (6.4)  (0) 2022.12.16
KNK Chap.6 (6.3)  (0) 2022.12.16
KNK Chap.6 (6.2)  (0) 2022.12.16
Comments