블로그 이미지

가변 인자 매크로

2014. 5. 10. 16:03
매크로 함수에서 가변인자를 쓸수가 있다.

... 와  __VA_ARGS__ 를 사용할 수 있다.

#define TRACE(...) printf(__VA_ARGS__) 와 같이 선언할 수 있다.

사용 예는 아래와 같다.


TRACE("menu","follow", Type");

TRACE("menu","follow");






블로그 이미지

do while(0) 문을 쓰는 이유.

2014. 5. 10. 15:07

그냥 매크로 여러줄을 선언할 것을 왜 do while(0) 문 안에 넣어서 지정하는 것일까? 

그 이유는 간단히 설명하면 아래와 같다.


'다중 구문의 매크로함수 전체가 도중에 멈추지 않고 실행되게 하기 위해서이다.'


무슨 말이냐 하면 아래의 코드를 보면 이해 할 것이다.


1. 정의된 매크로

#define FOO(x) \

printf("arg is %s\n", x);\

do_something_useful(x);


2. 사용 예

if(blah == 2)

FOO(blah);


3. 실제 내용

if(blah == 2)

printf("arg is %s\n", blah);

do_something_useful(blah);


4. 수정된 매크로

#define FOO(x) do {\

printf("arg is %s\n", x);\

do_something_useful(x);

while(0)


5. 수정된 매크로가 적용된 결과

if(blah == 2)

do{

printf("arg is %s\n", blah);

do_something_useful(blah);

}while(0);




블로그 이미지

#if 1 또는 #if 0을 쓰는 이유

2014. 5. 9. 22:48

#if 1은 어차피 실행 되는데 왜 굳이 저렇게 쓰는가 하는 의문이 있다.

그 이유는 2가지가 있다.


1. 불필요한 코드를 전처리기 단계에서 제거하여 컴파일 되는 코드 용량을 감소 시킨다.


2.  코드 흐름 중간에서 테스트 해보고자 하는 함수를  /*     */ 문으로 주석 처리 할 경우, 

주석을 제거하고 다시 잎히는 과정이 굉장히 번거롭다. 




블로그 이미지

#define 뒤에 \를 붙이는 경우, 다중 줄로 #define을 선언하는 경우

2014. 5. 9. 22:24

#define 을 한 줄에 다 쓸수 없을 때

\ 문자를 이용하여 다중 줄로 선언할 수 있다.

단, 다중 줄로 선언할 경우 마지막 줄 에는 \ 문자를 붙이지 않는다.


#define SWAP(A, B) \

do {\

temp = A;\

B = A;\

A = temp;\

}while(0) 




블로그 이미지

[VS2010] C#에 C++로 만든 DLL 파일 추가하기

2013. 5. 7. 18:15

[출처] http://marufloor.tistory.com/79


1. 'DLL'을 Project에 추가

[프로젝트] - [추가] - [참조추가] 를 사용


2. 문제점

1 ) DLL를 참조추가할 때 아래와 같은 오류 발생

"'zzz.dll'에 대한 참조를 추가할 수 없습니다. 파일이 액세스 가능한지, 어셈블리 또는 COM 구성 요소가 올바른지 확인하십시오."


1-1) 해결책

C++ Project에 [프로젝트 속성] - [C/C++] - [일반] - 공용 언어 런타임 지원을 "공영 언어 런타임 지원 (/clr)" 로 설정




2 ) 빌드할때 아래와 같은 오류 발생

/zi' and '/clr' command-line options are incompatible


2-1) 해결책

플랫폼 구성을 [속성] - [구성관리자] - 구성을 "Release"로 변경 후 확인 - 디버그 정보 형식을 "프로그램 데이터베이스 (/Zi)" 로 설정


1), 2) 설정 후 화면은 아래와 같다. 





3) 빌드할때 다음과 같은 에러 추가 발생

/EHs /clr 명령줄 옵션이 호환되지 않습니다.


3-1) 해결책

/EHs 를 제거한다. 

[프로젝트] - [속성] - [구성속성] - [C/C++] - [코드생성] - C++ 예외 처리 가능을 "아니요" 로 설정


참조 : http://www.devpia.com/MAEUL/Contents/Detail.aspx?BoardID=17&MAEULNo=8&no=58238&ref=58238



3. 위와 같은 에러는 다음과 같은 MSDN을 참조하면 된다.

/clr 제한 : http://msdn.microsoft.com/ko-kr/library/ffkc918h(v=vs.80).aspx

/clr를 사용할 때는 다음과 같은 컴파일러 옵션이 지원되지 않습니다.


블로그 이미지

[C언어] 최대값 구하기 함수

2012. 8. 6. 05:24


최대값 구하기 함수

 int Find_Max(int Array[], int length)
{ 
    int MAX = Array[0]; 
    int i; 
    for(i=1; i<length; i++) 
    { 
        if(Array[i]>Array[i-1]) 
        { 
            MAX = Array[i]; 
        } 
    } 
    return MAX; 
}



블로그 이미지

[C언어] 링크드 리스트로 구현한 int 저장형 스택 예제

2012. 8. 6. 03:50


LinkedListStack.h

 
#ifndef LINKEDLIST_STACK_H 
#define LINKEDLIST_STACK_H 

#include <stdio.h> 
#include <string.h> 
#include <stdlib.h> 

typedef struct tagNode 
{ 
    int Data; 
    struct tagNode * NextNode; 
} Node; 

typedef struct tagLinkedListStack
{ 
    Node * List; 
    Node * Top; 
} LinkedListStack; 

void LLS_CreateStack (LinkedListStack ** Stack); 
void LLS_DestroyStack (LinkedListStack * Stack); 

Node* LLS_CreateNode (int * Data); 
void LLS_DestroyNode( Node* _Node ); 

void LLS_Push (LinkedListStack* Stack, Node* NewNode); 
Node * LLS_Pop(LinkedListStack* Stack); 

Node * LLS_Top( LinkedListStack* Stack); 
int LLS_GetSize( LinkedListStack* Stack); 
int LLS_IsEmpty( LinkedListStack* Stack); 

#endif


LinkedListStack.c 

 

#include "LinkedListStack.h" 

void LLS_CreateStack( LinkedListStack** Stack) 
{ 
    /* 스택을 자유 저장소에 생성 */ 
    (*Stack) = (LinkedListStack*)malloc(sizeof (LinkedListStack));
    (*Stack)->List = NULL; 
    (*Stack)->Top = NULL; 
} 

void LLS_DestroyStack(LinkedListStack* Stack) 
{ 
    while( !LLS_IsEmpty(Stack) ) 
    { 
        Node * Popped = LLS_Pop( Stack ); 
        LLS_DestroyNode(Popped); 
    } 

    /* 스택을 자유 저장소에서 해제 */ 
    free(Stack); 
} 

Node * LLS_CreateNode (int * NewData) 
{ 
    Node * NewNode = (Node*)malloc(sizeof(Node)); 
     
    NewNode->Data = *NewData; /* 데이터를 저장한다. */ 

    NewNode->NextNode = NULL;    /* 다음 노드에 대한 포인터는 NULL로 초기화한다. */ 

    return NewNode; /* 노드의 주소를 반환한다. */ 
} 

void LLS_DestroyNode( Node* _Node ) 
{ 
    free(_Node); 
} 

void LLS_Push( LinkedListStack* Stack, Node* NewNode ) 
{ 
    if( Stack->List == NULL) 
    { 
        Stack->List = NewNode; 
    } 
    else 
    { 
        /* 최상위 노드를 찾아 NewNode를 연결한다 (쌓는다).        */ 
        Node * OldTop = Stack->List; 
        while( OldTop->NextNode != NULL) 
        { 
            OldTop = OldTop->NextNode; 
        } 

        OldTop->NextNode = NewNode; 
    } 

    /* 스택의 Top 필드에 새 노드의 주소를 등록한다. */ 
    Stack->Top = NewNode; 
} 

Node* LLS_Pop( LinkedListStack* Stack) 
{ 
    /* LLS_Pop() 함수가 반환할 최상위 노드 */ 
    Node* TopNode = Stack->Top; 

    if( Stack->List == Stack->Top) 
    { 
        Stack->List = NULL; 
        Stack->Top = NULL; 
    } 
    else 
    { 
        /* 새로운 최상위 노드를 스택의 Top 필드에 등록한다. */ 
        Node* CurrentTop = Stack->List; 
        while( CurrentTop != NULL && CurrentTop->NextNode != Stack->Top) 
        { 
            CurrentTop = CurrentTop->NextNode; 
        } 
        Stack->Top = CurrentTop; 
        CurrentTop->NextNode = NULL; 
    } 

    return TopNode; 
} 

Node * LLS_Top( LinkedListStack* Stack) 
{ 
    return Stack->Top; 
} 

int LLS_GetSize ( LinkedListStack* Stack) 
{ 
    int Count = 0; 
    Node * Current = Stack->List; 

    while( Current != NULL)
    { 
        Current = Current->NextNode; 
        Count++; 
    } 

    return Count; 
} 

int LLS_IsEmpty( LinkedListStack* Stack) 
{ 
    return (Stack->List == NULL); 
}


 Test_LinkedListStack.c
 

int main(void)
{
	int i=0;
	int Count =0;
	Node* Popped;

	LinkedListStack* Stack;
	LLS_CreateStack(&Stack);

	LLS_Push(Stack,LLS_CreateNode("abc"));
	LLS_Push(Stack,LLS_CreateNode("def"));
	LLS_Push(Stack,LLS_CreateNode("efg"));
	LLS_Push(Stack,LLS_CreateNode("hij"));

	Count = LLS_GetSize(Stack);
	printf("Size : %d, Top : %s\n\n",Count,LLS_Top(Stack)->Data);

	for(i=0; i<count; {="" ?,popped-="" %s,="" printf(?popped:="" popped="LLS_Pop(Stack);" break;="" if(lls_isempty(stack))="" i++)="">Data);
		}
		else
		{
			printf("Stack is Empty.\n");
		}
	}
	LLS_DestroyStack(Stack);
	getchar();
	return 0;
}



'뇌를 자극하는 알고리즘' 의 스택 부분을 그대로 복사하여 int형에 맞게 수정한 것입니다.




블로그 이미지

[C언어] malloc 으로 2차원 동적 배열을 할당하는 방법

2012. 7. 19. 23:48

malloc 으로 1차원 배열을 할당하는건 쉽다.

int input;

scanf("%d", &input);

이 있고, input받은 숫자를 크기로 가지는 array 배열을 만들 때

int *array = (int *)malloc(sizeof(int)*input);

로 넣으면 된다.

하지만 2차원 배열을 생성하려면 조금 생각해야한다.

input*input 크기를 가지는 2차원 array 배열을 만들려면 방법을 모르는사람(나같은경우...)은 이렇게 생각할 수 있다.

int **array = (int **)malloc(sizeof(int)*input*input);

컴파일러는 친절하게 에러를 표시한다 :D

그럼 어떻게 생성해야할까?

포인터를 두번쓰는건 맞다. 만들려는 배열이 2차원이니 대표주소를 가르키기 위해선 포인터를 2개 써야한다.

하지만 포인터를 두번 쓰는것만으로는 2차원배열을 모두 할당할 수는 없다.

이럴때는 2차원배열에 대해서 한번 malloc 으로 동적생성해주고 생성된 배열에 대해서 malloc으로 배열을 한번 더 생성해주면 된다.

이말이 무슨말이냐...

int **array = (int**)malloc(sizeof(int *)*input);

로 한번 생성해주고 input이 3이라고 가정하면 int형 배열 *array[0], *array[1], *array[2] 이렇게 3개가 생성된다.

이 각각의 배열에 대해서 또 malloc을 지정해주면 동적 할당이 되는것이다. 즉

array[0] = (int *)malloc(sizeof(int)*input);

array[1] = (int *)malloc(sizeof(int)*input);

array[2] = (int *)malloc(sizeof(int)*input);

=

for(int i=0; i<input; i++)

array[i] = (int *)malloc(sizeof(int)*input);

를 넣어주면 되는것이다.

여기서 sizeof(int *) 의 의미를 물어볼 수 있는데..

이렇게 일차적으로 동적배열을 할당해주기는 하지만 사실 두번째 동적배열을 할당할 때 크기를 몇으로 가지는지 컴파일러가 알 수 없기 때문에 일단 포인터형으로 크기를 지정해놓았다. 즉 int **array = (int**)malloc(sizeof(int *)*input); 이것만 지정해서는 array의 배열 크기를 알 수 없다는 뜻이다.

2차원배열 생성 코드를 정리해놓으면

int input, i;

scanf("%d", &input);

int **array = (int**)malloc(sizeof(int *)*input);

for(i=0; i<input; i++)

array[i] = (int *)malloc(sizeof(int)*input);

생성된 array[input][input] 을 사용

for(i=0; i<input; i++)

free(array[i]);
free(array);

이렇게 된다.

동적배열을 1차원간격으로 나누어서 정의하였으니 free도 나누어서 해주어야 한다.

  1. 2014.03.31 23:21  address  modify / delete  reply

    감사합니다. 왜 에러 뜨나 했는데 이런 심오한 뜻이 있었네요!

  2. 학생 2015.10.13 19:39  address  modify / delete  reply

    배우고 갑니다 구글 검색해도 엉뚱한거 많이뜨는게 여긴 유익한글이네요