레이블이 C인 게시물을 표시합니다. 모든 게시물 표시
레이블이 C인 게시물을 표시합니다. 모든 게시물 표시

2015년 5월 21일 목요일

[Grind Away] 여러 명령이 포함된 매크로 함수는 do while을 사용하 자!

C · 2015/05/21

아래 코드를 보자 1 #include <stdio.h> 2 3 #define SWAP(x, y, t) { \

4  (t) = (x); \
5  (x) = (y); \

6  (y) = (t); }

7 8 int main(void){ 9 10 int a=10; 11 int b=20; 12 int tmp; 13 14 printf("a : %d\n", a); // 10 15 printf("b : %d\n", b); // 20 16 17 SWAP(a, b, tmp); 18 19 printf("a : %d\n", a); // 20 20 printf("b : %d\n", b); // 10 21 22 return 0; 23 } 24 cs SWAP함수에서 총 3개의 명령문을 실행한다

(물론 ','를 이용하여 하나의 명령문으로 해결할 수도 있으며 비트연산자를 통해 한줄안에 처리할 수 있지만 예를들기 위해 3줄로 작성했다.) 물론 잘 실행 되는 것을 확인할 수 있다. 하지만 아래와 같이 코드를 작성했다면 약간 결과가 다를 것이다.

1 2 #include <stdio.h> 3 4 #define SWAP(x, y, t) { \ 5 (t) = (x); \ 6 (x) = (y); \ 7 (y) = (t); } 8 9 int main(void){ 10 11 int a=10; 12 int b=20; 13 int tmp; 14 15 if (1) 16 SWAP(a, b, tmp); 17 else 18 a=0; 19 20 return 0; 21 } 22 cs 위와 같이 코드를 짜면 에러가 발생한다.

위 코드는 예를 위해 만든 크게 의미는 없는 코드이지만 위와 같은 구조는 우리가 흔히 쓰는 방식이다.

16번째 줄에서 문제가 발생하는데 SWAP함수를 호출하면서 ';' 이 뒤에 붙었기 때문이다.

그러므로 else문이 제대로 동작하지 못한다. (if 문의 영역에서 세미콜론으로 끝나버렸기 때문) 위와 같은 문제를 해결하기 위한 방법으로 여러 줄의 매크로 함수를 작성할 때는 do while문을 쓴다.

아래 코드를 보자 1 2 #include <stdio.h> 3 4 #define SWAP(x, y, t) do{ \ 5 (t) = (x); \ 6 (x) = (y); \ 7 (y) = (t); } while(0) 8 9 int main(void){ 10 11 int a=10; 12 int b=20; 13 int tmp; 14 15 if (1) 16 SWAP(a, b, tmp); 17 else 18 a=0; 19 20 return 0; 21 } 22 cs 모두 동일하지만 SWAP 함수를 선언하는 부분을 do { } while(0) 으로 싸고있다.

위 코드는 에러가 발생하지 않고 정상적으로 잘 동작할 것이다.

16번째 줄에서 SWAP를 호출하며 ';' 를 뒤에 붙였지만 do { } while(0) 뒤에 세미콜론이 붙은 형태로 치환되면서 아무런 문제없이 else문으로 넘어갈 것이다.

여러 줄을 사용하는 매크로 함수에서 중괄호를 이용하여 여러 명령문을 묶어주면 if else 문에서 위에서와 같은 문제가 발 생할 수 있으므로 중괄호 대신 do while 문을 이용해서 여러 명령문을 묶어주자는 의미이다.

do while문은 반복문으로 동작하기 때문에 우리는 한번만 실행시키면 되므로 do { } while(0) 으로 작성을 해서 한번 실 행하고 바로 탈출할 수 있도록 처리했다.

여러 명령어를 매크로 함수에 포함시킬 경우 꼭 do while문으로 묶어서 사용하자!

#C언어 #시스템프로그래밍 #임베디드 #개발자

[Grind Away] free시킨 포인터 변수에는 NULL로 초기화 해주자! 댕글 링 포인터(Dangling Pointer)

C · 2015/05/21

아래 코드를 보자.

1
  #include <stdio.h>
2
  #include <stdlib.h>
3

4
  int main(void){
5
  int *p = (int*)malloc(sizeof(int));
6

7
  *p = 10;
8
  printf("%d\n", *p); // 10
9

10 free(p); 11 *p = 20; 12 return 0; 13 } 14 15 16 Colored by Color Scripter cs 이상한 점이 보이는가?

free(p) free(p)를 통해 동적할당된 메모리 공간을 해제시키고 나서 *p = 20; 과 같이 없어진 공간을 또 사용하고 있다.

이와 같이 free시켜 해제된 메모리 공간을 가리키고 있는 포인터 변수를 보고 댕글링 포인터(Dangling Pointer) 라고 한다.

위와 같이 사용한다면 당장 눈에 보이는 에러가 발생하지는 않지만 프로그램이 동작하는 도중 free한 위치에 새로 동적할 당이 이루어져 중요한 정보가 저장되어 버린다면 심각한 문제가 발생할 수 있다.

그렇기 때문에 위와 같은 문제를 해결하기 위해 습관적으로 free이후 해당 포인터 변수에 NULL값을 넣어주는 것이 좋다.

만약 귀찮다면 아래와 같이 매크로 함수를 작성하여 사용하는 것도 좋은 방법이다.

#define FREE(x) do { free(x); x=NULL; } while(0) 1 2 ... 3 FREE(p); 4 ... 5 Colored by Color Scripter cs 위와 같이 free후 NULL 값을 넣어주는 매크로 함수 FREE를 작성하여 사용하면 더 편리하게 댕글링 포인터를 예방할 수 있다.

(만약 위 매크로 함수에 do while문을 사용하는 이유가 궁금 하면 아래 게시글을 확인하라) 여러 명령이 포함된 매크로 함수는 do while을 사용하자!

아래 코드를 보자123456789101112131415161718192021222324#include <stdio.h> #define SWAP(x, y, t) { \ ...

blog.naver.com

#C언어 #시스템프로그래밍 #임베디드 #개발자 #포인터