Chapter 16. 디버깅

 QuickWatch

QuickWatch 를 이용해서 Watch부분에 특정 변수의 값을 입력할 경우 그 변수의 값이 변하게 된다.

 

ASSERT() 와 VERIFY()

비주얼 C++ 개발 도구를 사용하는 경우 사용하는 디버깅 함수이다.

MFC응용프로그램 릴리즈 모드 에서는  ASSERT문이 주석처리가 된다.

따라서 함수 호출의 성공 여부를 확인하기 위해 ASSERT 사용

 사용 중인 경우에는 VERIFY 사용

 

  1. #define ASSERT(e) ((e) ? (void)0 : _assert(_FILE_, _LINE_, #e))

표현식 e가 참이면 0 실행, 거짓일 경우 화면에 파일 이름과 줄 번호를 출력

 

  1. char *buf;
  2. VERIFY( buf = (char*)calloc( 20, sizeof(char ) );
  3. strcpy( buf, "Hello World");
  4. free( buf );

 

일반적인 C프로그램에서는 assert() 함수를 사용한다.

  1.  #include <assert.h>

     

     void PrintAge( int num )
     {

    assert( num > 0 );

    printf("My Age : %d", num );

    }

num이 0과 같거나 작은 값이 들어오면 프로그램 실행을 중지하고 메시지를 출력한다.

Assertion failed : num > 0, file d:\test\test.c line 17

 

 

이 글은 스프링노트에서 작성되었습니다.

'책 정리 > 좋은 프로그래밍 습관' 카테고리의 다른 글

Chapter 15. 전처리기  (0) 2009.09.04
Chapter 14. 공용체  (0) 2009.09.04
Chapter 13. 구조체  (0) 2009.09.04
Chapter 12. 함수 포인터  (0) 2009.09.04
Chapter 11. 포인터  (0) 2009.09.04

설정

트랙백

댓글

Chapter 15. 전처리기

 전처리기

전처리기는 각 소스에 추가되어 있는 헤더파일을 실제 소스를 복사하는 작업을 한다.

그런 이후에 컴파일을 한다.

헤더파일

헤더파일은 주로 함수의 프로토타입의 선언 및 새로운 데이터형, 다른 헤더의 파일을 추가 할떄 사용한다.

헤더파일에는 전역변수 는 되도록이면 사용하지 않도록 한다. 헤더파일은 다른 소스파일에서도

참조를 하기 때문에 오류가 일어나기 쉽다.

P.S : 여러 다른 헤더파일을 포함하는 하나의 헤더파일을 만들어 사용하게 되면 사용할 때는 편하겠지만

메모리가 낭비 된다.

 

#ifdef 문 ( #ifndef )
  1. #define DEBUG
  2.  
  3. void main()
    1. printf("전처리기\n");
  4. #ifdef DEBUG 
    1. printf("DEBUG 식별자가 정의되어 있습니다.\n");
  5. #else
    1. printf("DEBUG 식별자가 정의되어 있지 않습니다.\n");
  6. #endif
  7. }

 

매크로 함수

컴파일러나 실행되는 운영체제의 입장에서 함수를 처리하는 것은 큰 작업이다.

그래서 이러한 단점을 해결하기 위해 간단한 함수 같은 경우는 매크로 함수를 정의하여 사용을 합니다.

  1. #define EXPOENTIAL( num ) (num)*(num)
  2. int doubleNum = EXPOENTIAL( 5 );

이 선언은 전처리기에 의해서 

  1. int doubleNum = (5)*(5);

와 같이 처리가 되어 컴파일이 실행됩니다.

 

매크로 함수를 두줄 이상 사용하자!
  1. #define MAX(a,b)\

    if( a > b )\

    printf("%d",a);\

    else \

    printf("%d",b);

5줄의 매크로 함수가 쓰여 있는데 이를 하나의 매크로 함수로 인식시키기 위해서 각 함수의 각 줄

뒤에 '\'문자를 붙여 넣어주게 되면 전처리기는 이를 보고 연속된 줄로 인식을 한다.

이 글은 스프링노트에서 작성되었습니다.

'책 정리 > 좋은 프로그래밍 습관' 카테고리의 다른 글

Chapter 16. 디버깅  (0) 2009.09.04
Chapter 14. 공용체  (0) 2009.09.04
Chapter 13. 구조체  (0) 2009.09.04
Chapter 12. 함수 포인터  (0) 2009.09.04
Chapter 11. 포인터  (0) 2009.09.04

설정

트랙백

댓글

Chapter 14. 공용체

공용체를 주로 메모리 절약 효과로 많이 알고 있지만

이러한 장점도 있지만 같은 메모리 공간을 여러 가지 자료형으로

사용함으로써 데이터형 변환이 쉽게되는 장점으로 인해 많이 사용한다.

즉, 한개의 메모리를 두개 이상의 자료형으로 정의 하여 사용 할 수 있다는 것을 의미 한다.

주로 임베디드분야에서 많이 이용되고 있다.

 

  1. typedef union _BYTE{ 
    1. unsigned char byte;
    2. struct _bit{
      1. unsigned char B1: 1;
      2. unsigned char B2: 1;
      3. unsigned char B3: 1;
      4. unsigned char B4: 1;
      5. unsigned char B5: 1;
      6. unsigned char B6: 1;
      7. unsigned char B7: 1;
      8. unsigned char B8: 1;
    3. } bit;
  2. } BYTE;

 

여기서 BYTE byteUnion; 에서 byteUnion.byte = 10; 을 하게되었을때

공용체 안에 bit구조체를 사용하여 byte변수에 저장된 10의 각 비트값을

확인해 볼수 있다.

 

PS : 구조체와 같이 메모리 할당을 하므로 통신이나 기타 크기를 구하는 함수를 사용할 때

실수를 하지 않기 위해서 "패킹"을 해주도록 한다!!

이 글은 스프링노트에서 작성되었습니다.

'책 정리 > 좋은 프로그래밍 습관' 카테고리의 다른 글

Chapter 16. 디버깅  (0) 2009.09.04
Chapter 15. 전처리기  (0) 2009.09.04
Chapter 13. 구조체  (0) 2009.09.04
Chapter 12. 함수 포인터  (0) 2009.09.04
Chapter 11. 포인터  (0) 2009.09.04

설정

트랙백

댓글

Chapter 13. 구조체

1.  typedef 를 사용해서 간편하게 선언을 하도록 하자.

 

2. 구조체는 선언을 하고 반드시 초기화를 하고 사용한다.

 

3. 구조체 포인터에 메모리를 할당해 줄 경우  구조체 내의 메모리 할당 된 부분 부터 해제를 하고

 구조체 포인터의 메모리를 할당한다.

 

4. 구조체를 패킹한다!! 
  1. typedef struct NODE
    1. unsigned char A;
    2. unsigned char B;
    3. unsigned long C;
  2.  } DATA;
  3.  
  4. printf("DATA 의 크기는 %d 바이트다.", sizeof( DATA ) );

 

구조체의 크기는 1 + 1 + 4 해서 6바이트가 되어야 하지만 실제로 8바이트이다.

왜냐하면 32비트 시스템 들은 4바이트 정렬을 하기 떄문에 4바이트 단위로 정렬을 한다.

그래서 6바이트보다 큰 수 가운데 4로 나누어 떨어지는 가장 작은 수 인 8이 실행 결과로 나온다.

 

그러므로 구조체의 패킹 방법을 사용한다.

  1.  typedef struct NODE
    {
  2. unsigned char A;
  3. unsigned char B;
  4. unsigned long C;
  5. }  _attribute_ ((packed)) DATA;

 

 

 

 

 

이 글은 스프링노트에서 작성되었습니다.

'책 정리 > 좋은 프로그래밍 습관' 카테고리의 다른 글

Chapter 15. 전처리기  (0) 2009.09.04
Chapter 14. 공용체  (0) 2009.09.04
Chapter 12. 함수 포인터  (0) 2009.09.04
Chapter 11. 포인터  (0) 2009.09.04
Chapter 10. 연산자  (0) 2009.09.04

설정

트랙백

댓글

Chapter 12. 함수 포인터

함수 포인터를 이용하면 프로그램의 유지보수가 간편해 지고, 실행하는 부분의 코드가 간편해 진다.

 

 예

  1. int (* f)(char *);
  2. puts("요건 그냥 puts()함수다.\n"); 
  3.  
  4. f = puts;
  5. f("요건 함수 포인터 f()를 사용한 함수다.\n");

 

함수포인터를 이용한 계산기 프로그램

 

  1. #include <stdio.h>
    #include <string.h>
    #include <stdlib.h>
  2. int Add(int, int );
    int Minus(int, int );
    int Multiply( int, int );
    int Divide(int, int );
    int CheckOp( char );
    int (* Calc[4])(int, int) = { Add, Minus, Multiply, Divide };
  3. void main()
    {
     int iLeft, iRight;
     int ret;
     char op;
  4.  puts("사칙 연산 계산기 입니다.\n");
     puts("첫번째 인수 = " );
     scanf("%d", &iLeft );
     fflush( stdin );
  5.  puts("두번째 인수 = ");
     scanf("%d", &iRight );
     fflush( stdin );
  6.  puts("연산자 = ");
     scanf("%c", &op);
      
     ret = Calc[CheckOp( op )]( iLeft, iRight );
  7.  printf("계산 결과 : %d\n", ret );
  8.  system("pause");
    }
  9. int Add( int left, int right )
    {
     return left + right;
    }
  10. int Minus( int left, int right )
    {
     return left + right;
    }
  11. int Multiply( int left, int right )
    {
     return left*right;
    }
  12. int Divide( int left, int right )
    {
     return left/right;
    }
  13. int CheckOp( char op )
    {
     switch( op )
     {
     case '+':
      return 0;
      
     case '-':
      return 1;
  14.  case '*':
      return 2;
  15.  case '/':
      return 3;
     }
  16.  return -1;
    }

이 글은 스프링노트에서 작성되었습니다.

'책 정리 > 좋은 프로그래밍 습관' 카테고리의 다른 글

Chapter 14. 공용체  (0) 2009.09.04
Chapter 13. 구조체  (0) 2009.09.04
Chapter 11. 포인터  (0) 2009.09.04
Chapter 10. 연산자  (0) 2009.09.04
Chapter 09. typedef 와 enum  (0) 2009.09.04

설정

트랙백

댓글

Chapter 11. 포인터

1. 포인터는 선언하자마자 NULL 로 초기화를 한다.

 

2. 메모리 할당과 해제시에 메모리 할당 하는 함수를 따로 만든다.

 

3. 함수는 함수의 반환 값을 확인하여 정상적으로 함수가 실행되었는지 항상 확인한다.

결과 값이 아니라 함수의 정상적인 실행 여부를 반환해서 확인한다.

처음 함수 시작시 포인터값 존재하는지 여부 확인.

  1. if( src ) 
    1. return TRUE;
  2. }
  3. else
    {
    1. return FALSE;
  4. }

 

4. sizeof 와 strlen 의 혼동

sizeof는 자료형의 크기를 구하는 함수, strlen은 문자열의 길이를 구해주는 함수

 

5. free 함수

   할당 된 메모리를 초과하거나, malloc할때의 메모리 주소와 free할때의 메모리 주소가 다를 경우

 

 

 

 

 

 

 

 

 

 

 

 

이 글은 스프링노트에서 작성되었습니다.

'책 정리 > 좋은 프로그래밍 습관' 카테고리의 다른 글

Chapter 13. 구조체  (0) 2009.09.04
Chapter 12. 함수 포인터  (0) 2009.09.04
Chapter 10. 연산자  (0) 2009.09.04
Chapter 09. typedef 와 enum  (0) 2009.09.04
Chapter 08. 함수 튜닝의 좋은 습관 세가지  (0) 2009.09.04

설정

트랙백

댓글

Chapter 10. 연산자

^ ( XOR )

 두 비트가 다른 경우에는 1, 같은 경우에는 0 을 돌려준다.

비트값을 보수 취함. 1 -> 0 , 0 -> 1

 

!

0 인지 아닌지만 구분. TRUE, FALSE 만을 변경해준다. ~ 와 잘못 혼동 하지 말것

 

이 글은 스프링노트에서 작성되었습니다.

설정

트랙백

댓글

Chapter 09. typedef 와 enum

  1.  enum Week {Sun, Mon, Tue, Wed, Thu, Fri, Sat};
  2.  enum Week day;
  3. day 에 숫자 저장 및 enum형 값과 비교.

 

  1.  typedef enum _Week { Sun, Mon, Tue, Wed, Thu, Fri, Sat} Week;
  2. enum _Week 자료형을 Week라는 이름으로 사용한다.

이 글은 스프링노트에서 작성되었습니다.

설정

트랙백

댓글

Chapter 08. 함수 튜닝의 좋은 습관 세가지

 함수의 매개변수를 이용하여 연산하지 마라

함수의 매개변수가 포인터 변수 일 경우 그 변수를 가지고 직접 주소 계산을 하지말고,

임시 변수를 두어 주소값을 주어 계산을 하라. 

당장에는 별 문제가 없을 수가 있지만 한번 실수를 하게 되면 실수를 잡는데 굉장히 힘이 든다.

포인터 변수가 매개변수일 경우 항상 처음에 NULL값인지 확인을 하라.

 

함수의 반환값을 이용하라

함수의 반환 값을 결과 값을 받는 용도 이외에 함수가 정상적으로 실행 되었는지

판단 하는데에도 사용하라.

 

Plus : 디버깅이 되지 않을 경우
  1. printf("[%s] [%s] [%d]\n", _FILE_, _FUNCTION_, _LINE_); 을 사용하라
  2. [f:\test1\main.c] [main] [23]

main.c  파일에서 main함수에서 23행

디버깅 기능이 없는 리눅스에서 코딩시에 이런 구문을 삽입하여 디버깅을 좀 더 효율 적으로 하자 .

 

이 글은 스프링노트에서 작성되었습니다.

'책 정리 > 좋은 프로그래밍 습관' 카테고리의 다른 글

Chapter 10. 연산자  (0) 2009.09.04
Chapter 09. typedef 와 enum  (0) 2009.09.04
Chapter 07. 인수와 매개변수  (0) 2009.09.04
Chapter 06. 메모리 주소 출력  (0) 2009.09.04
Chapter 05. static  (0) 2009.09.04

설정

트랙백

댓글

Chapter 07. 인수와 매개변수

인수(argument)

함수 밖에서 함수를 호출 할 때 사용하는 변수 Squre( num );

 

매개변수(parameter)

함수 외부에서 호출 한 값이 함수 내부에서 사용되는 변수 int Squre( int x ){};

이 글은 스프링노트에서 작성되었습니다.

설정

트랙백

댓글