문자열 함수 중에 strcmp 함수가 있다..

이 함수는 a, b 문자열이 같은지 판단해 준다.

그래서 strcmp(a,b) ;
라고 넣었을 때..
1보다 크면, a 가 더 길고, 0이면 같음, - 이면 b가 더 길다 (반대일 수도 있으니 틀렸으면 확인부탁드립니다.)

그래서

if(!strcmp(a, b))
{
}

라는 방법으로 a, b와 같은지 판단할 수 있다.

여기에서 하나 더 + 된 함수가 바로 strncmp 인데..

매개변수가 하나 더 들어간다.

strncmp(a,b, int) ;

이렇게 int 수치를 넣어서 몇번쨰 까지 같은 것인지 판단할 수 있다.

리턴 값은 같다...

그러니 if 문을 쓸 때는 strcmp와 같이 쓰면되고,

일단 중간에 들어가는 부분을 판단하려면, 현재로써는 복사해서 사용하고 있는데,

혹시 다른 함수가 있다면, 다음에 보고 올리도록 하겠다.
Posted by 바람처럼..
|

[C, C++] 문자열 관련 함수 ( strlen, strcpy, strcat, strcmp )

지난 번에 메모리 관련 함수 들에 이어서 이번엔 문자열 관련 함수를 알아보자.

메모리 관련 포스팅 바로 가기
 
먼저 strlen 이다.. 말그대로 str , length 길이 라는 뜻이다.

return 형은 int 이다.

쓰는 방법은

char* str = "abcde" ;

int nlength = strlen(str ) ;

이렇게 쓰고 출력해보면 5라는 값이 나온다.

다음은 strcpy 이다.

이 것은 지난번 memcpy 처럼 문자열을 복사하는 함수이다.

char* src = "abcde" ;
char dst[20] = { 0, } ;
 
strcpy( dst, src ) ; 

이렇게 쓰면 abcde가 dst에 복사가 된다.

strcat은 문자를 합치는? 붙이는? 함수이다.

사용방법은

char dst[20] = "abcde" ;
char* src= "fghij"  ;

strcat(dst, src ) ;

처럼 하면 abcdefghij 가 쭉 붙은 문자열이 된다.

dst + src 라고 보면 된다.

strcmp는 비교 함수로 A 와 B 가 같은지 본다.

사용 방법은..

 char* dst = "abcde" ;
 char* src = "abcde"  ;

 int nResult = strcmp(dst, src ) ;

처럼 쓰면 된다..

strcmp(A, B ) ;

라고 봤을 때 A가 크면 1을 리턴하고 B가 더 크면 -1, 두개가 같다면 0을 리턴

한다.

0은 if 문을 만나면 false로 인식되므로,

if(!strcmp(dst, src ) )

같은 문으로 써도 되고,

switch(strcmp(dst, src))
{
        case -1:
              break ; 

        case 0:
              break ;

        case 1:
             break ;
}

이렇게 사용해도 된다.





Posted by 바람처럼..
|
[C,C++] memset, memcpy 함수 사용법!

mem- 이라는 접두사가 붙은 함수는 메모리 관련 함수라는 의미이다.

memset은 메모리를 초기화 하는 함수이고, memcpy는 메모리를 복사하는 함

수이다.

얼마전 sprintf() 로 512크기의 char배열의 값을 받아서 넣은 적이 있다..

그런데, 500크기일때 까지는 제대로 값이 들어와서 새로운 배열에 값이 잘 써졌

는데, 512가 되니... 이상하게 값이 짤리고, 날라가고 쓰레기 값이 들어왔다..

그래서 알아보니 크기가 큰 배열인 경우에 sprintf를 사용하면, 이렇게 값이 제

대로 안들어오는 경우가 종종 있다고 한다..

그래서 사용한 방법이 memcpy 이다.

그러니 정상적으로 복사가 되었다..

일단 먼저 memset 부터 알아보자..

void *  __cdecl memset(_Out_opt_bytecapcount_(_Size) void * _Dst, _In_ int _Val, _In_ size_t _Size);

이 것이 memset의 함수 원형이다.

1번 파라미터는 값을 복사할 곳이고, 2번 파라미터는 초기화할 값, 마지막은 얼

마만큼의 메모리를 초기화 할 것인지 하는 크기이다.

단, char 값이 아니라면, 0, -1로만 초기화 하는 것이 좋다.

(다른 값은 쓰레기 값이 들어가는 경우가 많다. )
---------------------------------------------------------------------
수정사항... 다른 분의 지적이 있으셔서 확인해보니.. 그 말이 맞아 수정합니다.

먼저.. 쓰레기 값이 들어가는 것이 아니라.. 1바이트 기준으로 값이 들어가기 때문에 char를 제외한 다른 1바이트가 넘는 (예를 들면 인트라면..) 변수에 값을 넣으면 그 바이트 수 만큼 모두 1 숫자로 초기화를 합니다.

int를 예로 들어보면 4바이트 모두를 1로 초기화 하기때문에 메모리가 각바이트가 모두 1로 초기화 되어있습니다. 원래 4바이트가 0000 이라면 0001 이 되어야 출력시 1로 표시되는데 1111이 되기 때문에 출력을 해보면 원하는 값이 들어 가지 않네요...

----------------------------------------------------------------------

 


위의 출력 창은 1로 memset 한 경우인데.. 다른 값이 들어가 있는 것을 확인

할 수 있다.

int test1[5] ;

memset( test1, 0, 5 * sizeof(int) ) ;

이렇게 사용하면되는데,  int 형의 크기가 5인 배열에 값을 0으로 초기화 하는

것이다.

다음은 memcpy 이다.

void *  __cdecl memcpy(_Out_opt_bytecapcount_(_Size) void * _Dst, _In_opt_bytecount_(_Size) const void * _Src, _In_ size_t _Size);

memcpy의 함수 원형이다.

첫번째 파라미터는, 역시 복사될 메모리 주소고, 다음은 복사할 메모리 주소,

마지막은, 복사할 사이즈다.

사용법은

int test1[5], test2[5] ;

memset( test1, 0, 5 * sizeof(int) ) ;
memset( test2, -1, 5 * sizeof(int) ) ;

memcpy( test1, test2, 5 * sizeof(int) ) ;

이러고 test1의 값을 차례로 출력하면 모두 -1로 변해 있는 것을 알 수 있다.


출력 결과 이다.

요즘은 잘 사용하지 않고 있다가, 이번에 sprintf 문제 때문에 다시 알아보게 되

었지만, 속도상의 이득도 많다고 한다.

긴 크기의 배열이나, 값은 이렇게 메모리 자체를 복사하여 쓰는 것이 훨씬 이득

이라고 하니, 앞으로 코딩할 때 많이 고려해 봐야할 것 같다.

[C,C++] memset, memcpy 함수 사용법!


Posted by 바람처럼..
|

[C,C++] 더블버퍼링..

더블 버퍼링이라는 개념은 흔히 게임과 관련되거나, 실시간으로 화면 처리가

필요할 떄 사용된다..

쉽게 설명하면, 그림이나 도형 하나 하나를 그릴 때 보여지는 화면에 바로바로

그려버리면, 흔히 얘기하는 깜빡이는 현상이 생긴다.

그 것을 방지 하기 위해서는 더블 버퍼링을 사용하는데 말 그대로 버퍼가 2개

(더블) 이라는 의미이다.

즉, 화면에 보여지는 버퍼 하나와 화면에 보이지는 않지만 실제로 그림이 찍히

는 백버퍼 2개의 버퍼가 존재하는데 일단 백버퍼에 모든 그림을 그리고, 마지막

에 화면 버퍼에 백 버퍼를 복사하는 방식이다.

(물론, 2개의 버퍼를 클리핑 하면서 사용할 수도 있다. 개념적으로는 같은 방식

이다.)

개념자체도 어렵지 않은 만큼 소스도 어렵지 않다...

아래의 소스는 mfc에서 테스트 했지만, hdc를 사용하기 때문에, c++환경의 api

든 mfc든 모두 사용할 수 있을 것이다.

HDC backMemDC ;
 
backMemDC = CreateCompatibleDC(pDC->GetSafeHdc());

위와 같이 백버퍼를 하나 선언한다... 물론 기본적으로 프론트 버퍼도 있어야

하는데, mfc에서 지원하는 pDC에서 hdc를 받아온다.

그 후에..

RECT rect ;
GetClientRect(&rect) ;


HBITMAP MemBmp;
MemBmp = CreateCompatibleBitmap(pDC->GetSafeHdc(),rect.right,rect.bottom);

SelectObject(backMemDC,MemBmp);

화면의 크기를 얻기 위해 rect를 선언하였고,

비트맵을 하나 만들고, 2개를 연결 시킨다...

오랜만에.. 더블버퍼링에 대해서 개념만 가지고 그냥 코딩했더니.....

저 비트맵 부분을 빼먹었었다.. 아무런 오류없이 컴파일이 끝났지만,

실제 화면에는 아무것도 찍히지 않았다 ;;

그래서 검색해보니 저 비트맵을 누군가 도화지라고 표현해놓았는데..

그 것을 보고 비트맵을 추가했더니, 역시나 제대로 나온다...

즉, 더블버퍼링에 필요한 것은 백버퍼와 그 곳에 그림이 그려질 도화지 역할을

하는 비트맵이 필요했다..

이제 저 이후에,

MoveToEx(backMemDC, 100, 100, NULL ) ;
LineTo(backMemDC, 300, 300) ;

이런식으로 선을 긋든, 원, 사각형을 그리고, 마지막으로...

BitBlt(pDC->GetSafeHdc(),0,0, rect.right, rect.bottom, backMemDC, 0,0, SRCCOPY);

으로 화면을 백버퍼에 있던 내용을 프론트로 복사하면 된다...

DeleteDC(backMemDC);
DeleteObject(MemBmp);

그리고 잊지말고, 해제도 꼭 하기!

[C,C++] 더블버퍼링..[C,C++] 더블버퍼링..[C,C++] 더블버퍼링..




Posted by 바람처럼..
|

 1] 함수 오버로딩의 이해

확장자가  .c로 끝나는 C 언어로 작성된 프로그램에서는 다음과 같은 함수의

정의가 허용되지 않았다.

int function(void)
{
        return 0;
}

int function(int a, int b)
{
         return a+b;
}

위의 소스는 함수의 이름이 같기 때문에 컴파일 타임에 오류를 발생시킨다. 아

니 c 에서는 오류를 발생 시켰다. 하지만 C++로 넘어오면서 부터 달라졌다. c++

은 호출하고자 하는 함수를 찾을 떄 함수의 이름뿐 아니라 매개 변수의 정보까

지도 동시에 참조한다. 따라서 c++은 이름이 같고 매개 변수의 타입 혹은 개수

가 다른 함수들의 정의를 허용한다. 그리고 이를 가리켜 함수 오버로딩

(function overloading) 이라 한다.

2] 함수 오버로딩의 조건 

c++은 함수의 이름이 같아도 매개 변수의 타입 및 개수가 다르면 문제되지 않으

며, 이를 가리켜 " 함수가 오버로딩 되었다. " 라고 표현한다고 하였다. 다음은

대표적인 함수 오버로딩의 예이다.  

int function1(int n){.....}

int function2(char c) {.......}

위의 두 함수도 오버로딩 되었다. 함수의 이름이 같지만 매개 변수의 자료형이

다르기 때문이다.

int function(int v){.....}

int function(int v1, int v2){.......}

위의 두 함수도 오버로딩 되었다. 함수의 이름과 매개 변수의 자료형은 같지만

자료형의 개수가 다르기 때문이다.

즉, 함수 오버로딩의 기본 조건은 다음과 같다.

"함수의 이름은 같지만 매개 변수의 타입이나 개수가 달라야 한다. "

그 이외에도 함수가 오버로딩 되기 위한 조건이 하나 더 있는데 이에 대해서는

다음 기회에 언급하겠다.

3] 오해하기 쉬운 함수 오버로딩

함수 오버로딩을 처음 접하게 되면 두 개의 함수를 눈으로만 보고 잘못 판단하

는 경우가 종종있다. 예를 하나 들어 보겠다. 다음의 함수들은 오버로딩 조건을
충족하는가, 아니면 충족하지 못하고 컴파일 시 오류를 발생시키겠는가? 눈 여

겨 볼  부분은 함수의 리턴 타입이다.

 #include <iostream>

 void function(void)
{
        std::cout << "function(void  call " << std::endl;
}

int function(void)
{
        std::cout << "function(char c) call " << std::endl;
        return 1;
}

int main(void)
{
        function();
        return 0;
}

물론 위에 정의되어 있는 두 개의 function 함수는 이름은 같지만, 리턴 타입이

다르다. 그러나 리턴 타입만 가지고는 함수가 오버로딩되었다고 말할 수 없다.

결국 컴파일러는 " 난 네가 뭘 원하는지 몰라 (Ambiguous) " 라는 메시지를 출

력하게 된다. 즉, 리턴 타입만 달라서는 함수가 오버로딩되지 않는다.

 

'프로그래밍 > C,C++' 카테고리의 다른 글

[C,C++] memset, memcpy 함수 사용법!  (6) 2011.10.11
[C,C++] 더블버퍼링..  (0) 2011.10.05
[C,C++] 디폴트(DeFault) 매개 변수  (0) 2011.09.14
[C,C++] 이름공간(namespace)  (0) 2011.09.14
[C,C++] 인-라인(in-line) 함수  (0) 2011.09.14
Posted by 바람처럼..
|
디폴트(Default)란 컴퓨터 공학에서 " 기본적인 " 이라는 의미를 지닌다. 매개

변수가 무엇인지는 알고 있을 것이다. 그렇다면 기본적인 매개 변수라는 뜻이

된다.

1] 디폴트 매개 변수의 의미

함수를 다음과 같은 형태로 정의하는 것이 가능하다 .

int function(int a = 0);
{
      return a+1;
}

여기서 매개 변수를 선언하는 부분을 보면 a는 0으로 설정되어 있다. 이것이 바

로 디폴트 매개 변수이다. 그렇다면 이것이 지니는 의미는 무엇일까? 의외로 간

단하다. " 만약에 function이라는 이름의 함수를 호출하면서 인자를 전달하지

않으면 0이 들어 온 것으로 간주를 하겠다 " 는 뜻이다. 말 그대로 디폴트(기본

적으로 설정해 놓은) 매개 변수다.

2] 다양한 형태의 디폴트 매개 변수 설정

이번에는 디폴트 매개 변수의 다양한 형태를 예제를 통해서 살펴 보기로 하자.

다음에 소개하는 것은 직육면체의 넓이를 구하는 프로그램이다.

#include < iostream> 

int BoxVolume(int length, int width = 1, int height = 1); 

int main()
{
       std::cout << " [3,3,3]  :    " << BoxVolume(3,3,3) << std::endl;

       std::cout << " [5,5,def]  :    " << BoxVolume(5,5) << std::endl;

       std::cout << " [7,def,def]  :    " << BoxVolume(7) << std::endl;

       return 0;

int BoxVolume(int length, int width, int height)
{
        return length*width*height;
}

함수 BoxVolume이 아랫쪽에 정의되어 있고, 위쪽에 선언되어 있다. 이러한 형

태의 구성은 이미 C 언어를 통해서 학습한 것이다. 여기서 눈 여겨 볼 부분은

함수의 선언이다. 총 세 개의 매개 변수를 인자로 전달 받는데, 두 번째, 세 번

째 인자에만 디폴트 매개 변수를 설정해 놓았다.

 한가지 주의할 것은 이렇게 함수의 선언이 함수의 정의 이전에 존재하는 경우

디폴트 매개 변수는 선언 부분에 놓여져야 한다는 것이다.  

3] 디폴트 매개 변수와 함수의 오버로딩 

디폴트 매개 변수와 함수 오버로딩을 동시에 잘못 정의하는 경우가 있다. 다음

예제를 보자. 그리고 문제점을 지적해 보자.

#include <iostream>

int function(int a = 0)
{
        return a+1;

int function(void)
{
        return 10;
}

int main(void)
{
        std::cout << function(10) << std::endl;

        return   0;

위의 예제를 컴파일 해 보면 컴파일도 잘 되고 실행도 잘 된다. 왜냐하면 3번쨰

줄에 정의된 함수 function과 7번째 줄에 정의된 함수 function과의 관계는 오버

로딩 관계이고 main 내에서는 int형 데이터 하나를 인자로 전달 받는 함수, 즉

위쪽 함수를 호출하였으므로 문제될 것이 전혀 없다. 그러나 잠재적인 문제를

지니고 있다. 위의 예제에서 main 함수를 다음과 같이 변경한다면 어떻게 될

까?

int main(void)
{
     std::cout << function() << std::endl;

     return   0;
}

드디어 잠재적인 문제가 터지고 말았다. 위의 function 함수를 호출하면서 인자

를 전달하지 않고 있다. 그렇다면 어떤 함수를 호출 하겠는가? 문제를 위에서

정의한 두 함수 모두 호출 가능하다는데 있다. 컴파일러는 두 개의 함수 중에서
무엇을 호출해야 할 것인지를 결정 짓지를 못한다. 따라서 에러를 발생시켜 버

린다. 그러므로 이러한 형식의 함수 정의는 반드시 피해야 한다.


'프로그래밍 > C,C++' 카테고리의 다른 글

[C,C++] 더블버퍼링..  (0) 2011.10.05
[C,C++] 함수 오버로딩(Function Overloading)  (0) 2011.09.15
[C,C++] 이름공간(namespace)  (0) 2011.09.14
[C,C++] 인-라인(in-line) 함수  (0) 2011.09.14
[C,C++] 가변 인자란 ...  (0) 2011.08.28
Posted by 바람처럼..
|
이름 공간이란 다소 생소한 개념이다. C 언어에는 존재하지 않는 개념이기 때

문이다. 그러나 어려운 개념은 아니다. 이름공간이란 이름을 지니는 공간이라

는 뜻이다. 말 그대로 특정영역(공간)에 이름을 붙여주기 위한 문법적 요소이

다.

1] 등장 배경

 프로그램이 대형화되어 가면서 등장하기 시작한 문제는 이름의 충돌이다 .예

를 들어서 은행 관리 시스템을 개발하는데 있어서 세 개의 회사가 참여를 한다.
각 회사의 이름은 A, B, C 이다. 이들은 규모가 큰 관계로 일을 독립적으로 진

행하기로 하였다. 그러기 위해서는 구현해야 할 부분도 적절히 나눴다. 이제 6

개월 뒤 다시 모여서 하나의 프로젝트를 완성하기로 약속을 한다.

 6개월이라는 시간이 흘렀다. 이제 각각의 회사가 구현한 모듈을 하나로 묶고

부족한 부분을 완성 할 때가 되었다. 그런데 문제가 생기고 말았다. A라는 회사

에서 정의한 함수의 이름과 B라는 회사에서 정의한 함수의 이름이 같은 것이

아닌가! 이름 충돌이 나지 않도록 미리 약속이라도 할 것을 그랬다는 후회가 든

다. 이제는 전쟁이다! 이름하나 바꾸는 것이 어디 쉬운 일인가? A  회사의 팀장

과 B 회사의 팀장이 서로 싸우기 시작한다. 물론 싸움의 요는 이거다. " 저희가

무지 바쁘거든요? 당신네 회사에서 양보를 조금 해 주셔야 하게습니다." 그런데
문제는 산 넘어 산이다. C 라는 회사에서는 자신들이 맡은 부분을 구현하는 과

정에서 다른 회사에서 구현해 놓은 함수들을 사용했는데, 이 함수들의 이름이

회사A, B에서 구현해 놓은 함수의 이름과 또 충돌이 나는 것이 아닌가? 결국 이
프로젝트는 실패로 돌아가고 말았다.

이러한 문제를 해결하기 위해서 이름공간(namespace) 이라는 문법이 C++ 표

준에 새롭게 포함되었다.

2] 기본 원리

 한 집에 철수 라는 이름을 지니는 사람이 두 명 살고 있다면 이는 문제가 된다.
" 철수야!" 라고 부르면, 어떤 철수를 말하는지 구분 지을 수 없기 때문이다. 그

러나 서로 살고 있는 집이 다르다면 문제될 것이 없다. 201호에 사는 철수와

202호에 사는 철수는 구분 지을 수 있기 때문이다.  이것이 이름 공간의 기본 원

리이다.  다음 예제는 앞에서 이야기한 문제점을 간략화해서 코드로 옮겨 놓은

것이다. A와B라는 이름의 회사가 구현한 프로그램 모듈을 하나의 완성된 프로

그램으로 옮기는 과정에서 이름 충돌이라는 문제가 발생하였다.

 #include <iostream>

 void function(void)
{
      std::cout << "A.com에서 정의한 함수 " << std::endl;
}

void function(void)
{
      std::cout << "B.com에서 정의한 함수 " << std::endl;
}

 int main(void)
{
       function();
       return  0;
}

 위의 예제에는 A.com 이라는 회사에서 정의한 함수와 , B.com 이라는 회사에

서 정의한 함수의 이름이 같다. 따라서 컴파일 시 문제를 일으킬 것이다. 둘다

필요한 기능의 함수라서 어느것 하나를 뺄 수도 없는 상황이다. (물론 그렇다고
가정만 하자) 

다음 예제에서는 이름 공간을 정의해서 문제를 해결하고 있다. 일단 위의 예제

와 어느 부분이 달라졌는지 비교해 보자.

#include <iostream>

namespace A_COM
{
       void function(void)
       {
               std::cout << "A.com에서 정의한 함수 " << std::endl;
       }
}

namespace B_COM
{
        void function(void)
       {
                std::cout << "B.com에서 정의한 함수 " << std::endl;
        }
}

int main(void)
{

      A_COM:: function();

      B_COM:: function();

       return  0;
}

 위의 예제를 보면 namespace 라는 키워드가 등장한다. 이는 이름 공간을 구

성하겠다는 의미다. 즉 "namespace A_COM " 이라는 선언은 A_COM이라는

이름의 공간을 구성하겠다는 의미가 되며, 이름공간의 범위는 이어서 등장하는
중괄호를 통해서 지정된다. 조금 더 쉽게 이야기를 하면, " 특정 영역(공간)의

범위를 지정하고 이름을 붙여준 것" 이다. 이름 공간이 다르면 같은 이름의 변

수나 함수의 선언이 허용 된다. 하지만 한가지 주의할 것은 이름 공간 내에 선

언되어 있는 변수나 함수에 접근하는 방법이다. 다음과 같은 선언이 필요하다.

A_COM::function(); 

위 코드에서 :: 연산자를 가리켜 " 범위 지정 연산자(scope resolution

operator) " 라 한다. 즉 이름공간의 범위를 지정할 때 사용하는 것이다. 따라서

위 그림과 같은 선언은 다음과 같은 의미를 지니게 된다. 

" A_COM 이라는 이름 공간안에 선언되어 있는 function 함수를 호출하라"

 이렇듯 이름 공간 안에 선언되어 있는 변수나 함수에 접근하기 위해서는 범위

지정 연산자를 사용해서 선언되어 있는 이름공간을 지정해 줘야한다.

참고) 위의 예제들에서는 하나의 이름공간 안에 하나의 선언 및 정의만을 담고

있지만 실제로는 둘 이상의 선언 및 정의를 담을 수 있고 또 그것이 더 일반적

이다.

3] std::cout, std::cin, std::endl

 지금까지 입력 및 출력을 하고자 하는 경우에는 std::cout 과 std::cin을 사용해
왔다. 이것의 정체는 아직 모르지만 사용법만은 알고 있다. 그런데 이제는 조금
이해가 될 것이다. :: 연산자가 어떠한 의미를 지니는지 이해 했기 때문이다.

std::cout은 무슨 의미인가? std라는 이름공간 안에 존재하는 cout을 참조하겠

다는 의미이다. 물론 우리는 아직 cout의 정체를 모르고 있다. 마찬가지로

std::cin은 std라는 이름 공간 안에 존재하는 cin을 참조하겠다는 의미로 사용

된다. 아마도 다음과 같은 가정을 할 수 있을 것이다. 헤더파일 iostream에 선

언되어 있는 cout, cin, 그리고 endl은 std 라는 이름공간 안에 선언되어 있다는
결론을 내릴 수있다. 이름 충돌을 막기 위해서 c++표준에서 제공하는 다양한 함

수나 변수들을 이름공간 std 안에 선언 및 정의 했기 떄문이다.

4]using

이제 cout, cin 그리고 endl을 참조할 때 마다  " std:: " 을 앞에다 붙여줘야 하

는 이유에 대해서 알게 되었다. 그리고 이 일이 여간 귀찮은 것이 아니라는 생

각도 들기 시작한다. 오히려 접근하고자 하는 이름공간에 대한 선언이 불 필요

한 과거의 표준이 더 맘에 끌리기도 한다. 하지만 걱정하지 말자. 추가적인 선

언 하나만으로도 여러분의 이러한 불만사항을 해소할 수 있으니 말이다.

Posted by 바람처럼..
|

in-line 함수의 의미부터 파악해 보자. in은 ' 내부 '를 의미하고, line은 ' 프로그

램 라인 ' 을 의미하는 거이다. 즉 의역 해보면 " in-line 함수" 란 프로그램 라인
안으로 들어가버린 함수라는 의미를 지닌다.  

1] 매크로 함수의 정의와 장점

 우리는 C 언어를 공부하면서 매크로에 대해서 알게 되었다. 여기서는 이에 관

련해서 잠깐 복습을 하기로 하자. 매크로를 이용하면 다양한 일을 할 수 있는

데 그 중에서도 가장 대표적인 일은 함수를 만드는 일이다. 다음은 매크로를 이

용해서 함수를 정의하고 이를 호출하는 형태를 보여준다.  일반적인 순서에 의

해서 전처리, 컴파일, 링크 과정을 거쳐서 실행 파일이 생성될 것이다.  

 #include <iostream>

#define SQUARE(X)   ((X)*(X))

 int main(void)
{

       std::cout << SQUARE(5) << std::endl;

       return 0;
}

 그럼 위의 코드는 전처리 과정을 거치면서 어떻게 변하게 되는가? 다음 코드는
전처리 과정에 의해서 변경된 코드를 보여준다.

 #include <iostream>

 int main(void)
{

       std::cout << ((5)*(5)) << std::endl;

       return 0;
}

  위의 두 코드를 통해서 알 수 있는 사실은 무엇인가? 그것은 함수를 매크로로

정의하면 전처리기에 의해서 함수 호출 문장이 함수의 몸체 부분으로 완전히

대치돼 버린다는 것이다. 그렇다면 이를 통해서 얻게 되는 이점은 무엇인가? 함

수 호출 과정이 사라졌기 때문에 성능상의 이점을 맛볼 수 있다.( 함수 호출은

스택 메모리 공간의 할당도 요구하며 시간도 많이 요구된다.)

  위의 예제와 같이 함수 호출 문장이 함수의 몸체부분으로 완전히 대치되 버리

는 현상을 가리켜 " 함수가 inline화되었다." 라고 표현한다.

 참고) 매크로 함수에 대해서는 장점뿐만 아니라 단점도 알고 있어야 한다. 단

점은 함수의 구현이 까다롭고 디버깅하기 어려우며, 구현하고자 하는 함수의

크기가 크다면 프로그램의 크기가 커지게 된다는 것이다. 보자 자세한 사항은

C 언어 관련 서적을 참조하기 바란다.

 2] C++ 기반 함수의 in-line 화

 앞에서 매크로를 이용해서 함수를 in-line화 하였다. 이처럼 매크로를 이용해

서 C++의 함수도 in-line화 할 수 있다. 그러나 보다 쉬운 방법이 있다. 다음 예

제 코드는 앞에서 본 예제를 C++ 스타일로 in-line화 하고 있다.

#include <iostream>

inline int SQUARE(int x)
{
         return x*x;
}

int main(void)
{
       std::cout << SQUARE(5) << std::endl;

       return 0;
}

 함수를 정의하는 과정에서 키워드 inline을 붙여준 것을 제외한다면 일반적인

함수와 다를 바가 없다. 그렇다면 여기서 붙여준 키워드 inline은 무엇을 의미하

는 것일까? 이는 함수 SQUARE를 inline화 하라는 의미이다.

 정리하자! C++에서는 성능 향상을 목적으로 함수를 inline화 하기 위해서 매크

로를 사용할 필요가 없다. 다만 inline이라는 키워드만 붙여주면 되는 것이다.

얼마나 간편하고 좋은가?

 참고) 매크로를 이용한 함수의 in-line화는 전처리기에 의해서 처리되지만, 키

워드 inline을 이용한 함수의 in-line화는 컴파일러에 의해서 처리된다. 또한 컴

파일러에 따라서는 inline 선언이 오히려 성능 향샹에 해가 된다고 판단될 경우,
그냥 무시해 버리기도 한다.

'프로그래밍 > C,C++' 카테고리의 다른 글

[C,C++] 디폴트(DeFault) 매개 변수  (0) 2011.09.14
[C,C++] 이름공간(namespace)  (0) 2011.09.14
[C,C++] 가변 인자란 ...  (0) 2011.08.28
[C,C++] getchar() 의 문제점..  (2) 2011.08.28
[C,C++] scanf 와 fgets  (0) 2011.08.27
Posted by 바람처럼..
|


가변 인자란.. 쉽게 생각하면, 인자(파라미터) 값이 변한다는 의미이다..

정확히는 인자의 개수가 변한다는 뜻이다...

같은 함수명이라도,, 파라미터를 2개, 3개,.. 이렇게 쓸 수 있다는 것이다.

그렇다면 함수 오버로딩이 아닌가 생각할 수도 있다..

하지만 그 것과는 엄연히 다르다..

흔히 우리가 쓰는 printf()를 떠올리면 이해하기가 쉽다...

printf("%d %s ",  int , char ) ;

라고 보면 똑같이 printf() 이지만.. 뒤의 파라미터들이.. 2개일 수도.. 3개일수도

아니면 더 클 수도 있다...

이럴때 쓰는 것이 가변인자이다...

가변 인자를 사용 하려면.. 일단.. 함수의 원형을 정의하면된다..

가변 인자를 이용해서.. 입력된 숫자들의 총합을 구하는 함수를 만들어 보자..

int add ( int, ... ) ;

이렇게 선언을 한다... 앞의 int만 유일하게 고정 인자고,.. 뒤의 ... 으로 뒤에는

몇개의 숫자가 오든 상관없다 ( 앞의 int를 count로 쓸 것이니 함수를 사용할 때는.. 신경을 써야한다..)

그리고 가변 인자를 쓰기 위해서는 헤더파일..

#include <stdarg.h>

를 추가한다...

그리고 가변 인자를 위한 3개의 매크로가 있다..

va_start(va_list list) ;
va_arg(va_list list, type) ;
va_end(va_list list );

이다...

va_start는 list를 초기화 한다.. 그 의미는 포인터를 list의 맨 처음을

가리키도록 하는 것이다...

이 함수를 쓰지 않으면, va_arg를 통해서 모든 인자를 다 쓰면, 처음으로 되돌

릴 수 없게된다...

va_arg는 고정 인자를 제외한 나머지 인자들을 얻기 위해 사용되며, 보통은

for()문을 이용해서 처리한다...

type위치에는 int, char 같이 가변 인자의 자료형을 넣어준다...

va_end는 가변 인자의 사용을 끝낼 때 사용하지만, 보통은 사용 안해도 무방하다..

그럼 동작이 가능한 함수를 만들어 보자...

위의 사진의 int add(int count, ...) 함수의 내부를 보면..

va_* 매크로를 이용하여서 리스트를 초기화, 값을 받고, 종료 시킨다..

그리고 실행시킨 결과 값이다....

어떤가.. 가변 인자를 잘쓰면, 좀 더 깔끔한 코드를 작성할 수 있지 않을까?

하지만, 가장 큰 주의사항들을 정리하면..

꼭, 1개 이상의 고정 인자가 있어야 한다는 점이다.....

위 사진 처럼.. int add(int count, ...)  의 int count가 고정 인자 이다..

이 것을 없얘고 int add(...) 이렇게 쓰면 에러를 일으킨다..

printf()에서 첫 인자가 꼭 "%d", "%d %s" 인 이유가 바로 여기있다..

위처럼 %* 가 있어야.. 뒤에 가변 인자가 몇개인지.. 알 수 있기

때문이다...

'프로그래밍 > C,C++' 카테고리의 다른 글

[C,C++] 이름공간(namespace)  (0) 2011.09.14
[C,C++] 인-라인(in-line) 함수  (0) 2011.09.14
[C,C++] getchar() 의 문제점..  (2) 2011.08.28
[C,C++] scanf 와 fgets  (0) 2011.08.27
[C,C++] sprintf 사용하기...  (2) 2011.08.23
Posted by 바람처럼..
|

char를 입력받을 때 흔히 쓸 수 있는 것이 getchar() 이다..

하지만 getchar()는 쓸 때 한가지 명심할 것이 있다...

getchar() 함수를 써서 값을 입력받은 후, 엔터를 치면 함수가 진행된다...

그 때 개행 문자 하나도 같이 버퍼에 쌓이게 된다...

그 후 getchar()가 실행되어서 버퍼에서 입력된 값을 받은 후..

또 다시 1번 더 getchar()를 실행해 버린다...

예를 들면.. 지금 입력된 값이 y 인지 n 인지 판단하는데..

y 값이면 y, 나머지는 n로 인식된다고 생각해보자...

y 후에 엔터를 쳤더니,

한번은 y로 인식했는데 자동으로 다음에는 n 를 한번 더 인식한다.

( 반복문일 경우임 )

이유는 처음에는 y를 입력받은 걸로 처리하고, 또 버퍼에 값이 있어서 값을 보

니.. \n 인 것이다. 그래서 y가 아니기 때문에.. n로 인식하는 것이다..

이럴때는 getchar()를 2번 연속으로 적으면 된다..

int a = getchar() ; getchar() ;

이렇게 되면 자동으로 a에는 첫 입력값, 그 후에는 그냥 버퍼에 값을 한번 더 부

를 뿐이다....

하지만 문제가 하나있다..

그냥 값 입력없이 엔터를 쳤을 때다... 그렇게 되면 처음 getchar()에서 개행 문

자로 인식 되지만, 뒤의 getchar()에서 문제를 일으킨다..

그래서 이 것을 모두 해결한 코드는..

if( a == '\n') continue;
else getchar() ;

이렇게 쓰면 된다..

'프로그래밍 > C,C++' 카테고리의 다른 글

[C,C++] 인-라인(in-line) 함수  (0) 2011.09.14
[C,C++] 가변 인자란 ...  (0) 2011.08.28
[C,C++] scanf 와 fgets  (0) 2011.08.27
[C,C++] sprintf 사용하기...  (2) 2011.08.23
[C,C++] 문자열에 대하여...  (0) 2011.08.23
Posted by 바람처럼..
|

문자를 입력받을 때 흔히, scanf나 fgets 를 사용한다...

2가지 이외에도 gets() 라는 함수인데,

이 함수는 치명적인 문제가 있다..

버퍼 오버플로우를 검사하지 않기 때문에, 10의 공간을 할당하고 나서,

12의 값을 넣어도 ( 메모리의 크기 ) 일단은 들어간다..

하지만 나중에 큰 문제를 일으킬 소지가 있다...

그리하여, scanf와 fgets를 사용한다고 치면,

scanf는 숫자, fgets는 문자열을 입력받는 것으로 사용하는 것이 좋다.....

scanf의 가장 큰 단점은 띄어쓰기를 인식 못한다는 점이다...

예를들어.. 이름을 입력하고자

char name[20] ;
scanf("%s", name ) ;

이렇게 입력하고 콘솔창에 test test test ; 이렇게 입력한다면...

출력 결과는..

test 만 나온다...

만약 다 입력 받고 싶으면,

scanf("%s%s%s", name1, name2, name3 ) ;

이런식으로 입력하면 되긴하지만.. 원하는 동작은 아니다...

그리하여 scanf가 편리하긴 하지만.. 숫자를 입력받을 때 정도만 쓰는 것이 좋다...

문자열을 입력받을 때는 fgets를 사용하려면,

fgets(name, 10, stdin ) ;

이런식으로 사용하면된다.. 가운데의 10은 버퍼의 크기이기때문에 자유롭게..

변경하면된다...

하지만 fgets도 문제가 있는데.. fgets는 자동적으로 개행문자가 삽입된다..

개행문자는,, printf같은 것을 사용할 때 다음줄로 넘어가는 \n 이다..

그렇기 때문에..

출력시에는 문제없이 출력된 것 처럼 보이나, 문자열의 크기를 비교한다던지

하면 문제가 발생할 수 있다..

그러니 꼭, 입력된 문자의 길이를 검사하여서, 개행문자를 없애고 그 자리에

/0(NULL) 을 넣어주면된다..

이 것을 코드로 표현하면..

name[strlen(name) - 1 ] = '\0' ;

처럼 넣어줘도 된다...

(단, name의 크기가 유동적이면 힘들고, 딱 배열의 크기에 맞게 설정되었을 때에 쓸 수 있다.. )

'프로그래밍 > C,C++' 카테고리의 다른 글

[C,C++] 가변 인자란 ...  (0) 2011.08.28
[C,C++] getchar() 의 문제점..  (2) 2011.08.28
[C,C++] sprintf 사용하기...  (2) 2011.08.23
[C,C++] 문자열에 대하여...  (0) 2011.08.23
[C,C++] 배열의 초기화..  (0) 2011.08.22
Posted by 바람처럼..
|

코딩을 하다보면, 문자열에..

숫자를 넣어야 할 때가 있다..

그럴 때 유용한 것이 바로 sprintf 이다..

sprintf를 쓰기 위해서는

#include <stdio.h> 가 필요하다...

사용법은...

char buf[256] ;

int a = 9 ;

sprintf( buf , " test%d", a ) ;

이렇게 넣으면..

buf 에는 test9 라는 문자열이 저장된다...

응용하면,

char *string = "world" ;
sprintf( buf, "Hello %s %d", string, a ) ;

이렇게 쓰면,

buf에 Hello world 9 라고 저장된다...

또,

char buf[256] ;

for( int i = 0 ; i < 3 ; ++i )
{
sprinf( buf, "test %d", i ) ;
printf( "%s\n", buf ) ;
}

이렇게 쓰면,

test0
test1
test2

이런식으로 출력된다..
Posted by 바람처럼..
|

문자열은 C언어에서는 문자 배열이라고 생각하면 된다...

문자열은 여러가지 특징이 있는데, 그 것을 알아보자...

그전에 상수에 값이 들어가는 것에 대해 한번 알아보자...

a , 'a', "a" 이 3 가지의 상수가 있다고 봤을 때.. 이 것들은 모두 다르다..

a 같은 경우는 그냥 일반적인 상수라고 보면된다...

흔히, int a = 4 ; 에서 4 같이 그냥 숫자를 바로 넣는 형태이다...

'a' 는 하나의 문자 상수이다..

'a' 자체가 저장되기 때문에..

char a = 'a' ; 같이 쓸 수 있다...

그럼 내부 적으로는 char a 안에 아스키코드 형태로 97로 저장된다..

( a를 %d로 출력 하면 97이 나오고, %c로 출력하면 a 가 나오는 식이다.)

그럼 마지막으로 "a" 가 바로.. 문자열 형태이다...

단지 따옴표가 붙었을 뿐이지만.. 그 상태로 char* a ; 에 저장을 시키면..

문자열 형태로 저장된다.. ( 즉, char*가 아니라 char면 에러를 일으킨다. )

문자열 이라는 말은 제일 마지막에 /0 (NULL 문자 ) 가 들어가 있는 형태이다.

문자열을 넣을 때 우리는 ..

char* string = "Hello world" ;

이렇게 값을 넣으면 된다...

이러면 자동적으로 마지막에 널이 들어가 있다.

이 것을 메모리 상에서 보면.. string 이라는 포인터 변수가 잡히고,

그 포인터 변수가 가르키는 주소값이 바로.. Hello 의 H의 위치이다..

이 문자열의 주소 위치는 컴파일러가 알아서 저장한다..

그럼 문자열의 출력 방법을 알아보자...

printf("%s\n", string ) ;

printf( string ) ;

puts( string ) ;

이렇게 여러가지가 있는데... 단순 출력만을 한다면..

그냥 puts가 가장 가볍고 좋다..

또 배열처럼 string + 2 라고 쓰면 string 위치부터 + 2 주소값이 더해져서..

Hello의 첫번째 l 을 가리키게 되며, 그 값부터 널을 만나기 전까지 출력이 된다.

그렇다면

char *string ;

char string[] ;

의 차이점은 무엇일까??

쉽게 생각하면.. 같은 행동을 하고, 출력 하기 위한 방식도 똑같고, 각 변수명이

문자열의 첫 주소를 가진다...

하지만 이 2가지는 엄연히 다르다...

위의 *string 같은 경우는.. 포인터 변수로, 따로 포인터 변수의 4바이트 주소를

가지고, 그 주소에서 문자열의 첫 시작점의 주소를 가리킨다..

하지만 2번째 의 경우는 문자열 배열로써...

그냥 문자열의 첫번째 위치를 바로 가리키고 있다...

이 것이 가장큰 차이점이다..

그래서 string++ 을 하면 문자열의 다음 변수를 가리킬 수 있지만,

아래의 배열일 때 ,

string++을 하면 에러가 난다..

왜냐하면 string 자체는 배열명이기 때문에.. 주소값을 가지고는 있지만..

++ 연산자를 풀어보면, string = string + 1 ; 과 같은데,

배열명에는 값을 넣을 수는 없기 때문이다..

그리고 char* string = "Hello" ; 의 Hello는 문자열 상수라고 보면된다..

상수는 즉, 고유한 하나의 값이다... 1이 1이지 0이 아닌 것처럼...

그래서,

*string = 'A' ;

이렇게 값을 넣으려 그러면.. 에러가 난다...

포인터 변수가 가리키는 첫 주소값의 내용을 바꿀 수 있을 것 같지만,

그 것은 불가능하다..

하지만 반대로

char string[] = "Hello" ;

이런 배열 형태로 저장되어 있다면,

string[0]  = 'A' ; 처럼 쓰는 것은 또 가능하다 ...

문자열... 간단히 쓰고있지만, 내부적으로의 흐름을 알아야...

나중에 헷갈리지 않고 잘 쓸 수 있을 것이다...
Posted by 바람처럼..
|

프로그램을 작성할 때 쓰는 가장 보편적이고, 기본적인 자료구조가..

배열이다...

하지만 배열을 초기화를 제대로 하지 않으면 여러가지 문제가 생긴다..

그래서 초기화를 하는 방법을 소개하겠다...

먼저 1차원 배열이다..

가장 기본적인 형태인..

int intp[3];

이렇게만 쓰고 출력을 해보면 쓰레기 값이 들어가 있다..

이제 초기화를 해줘야 하는데..

가장 단순한 초기화 방법은...

int intp[0] = 0 ;
int intp[1] = 0 ;
int intp[2] = 0 ;

이다.. 하지만.. 이번엔 3개 같은 경우니 가능하지만 더 많아지면..

이렇게 하면 소스 가독성이 떨어진다..

그래서 반복문을 사용해서..

for(int i = 0 ; i < 3; i++ )
      intp[i] = 0 ;

이렇게 쓰면 된다..

하지만 가장 좋은 방법은..

int intp[3] = {0} ;

이렇게 쓰는 것이다.. 단, 이 방법은 선언과 함께 사용해 주어야 한다..

방금 방법은.. 0으로 초기화 하는 방법이였고, 혹시 값을 넣어야 한다면,

다음과 같이 초기화 해주면 된다..

( 이 것도 선언과 함께 사용하여야 한다. )

int intp[3] = { 1, 2, 3 } ;

이런 식으로 말이다.. 하지만..
 
int intp[3] = { 1, 2, 3, 4 } ;

이렇게 4개를 넣으면 어떻게 될까?

머.. 동작은 상관없이 된다.. 마지막 4는 짤리겠지만 말이다...

그런데 혹시 뒤에 4개를 넣은게 맞는 것이고,

앞의 3이 잘못 되었다면... 문제가 생길 것이다..

그럴때를 대비해서..

int intp[] = { 1, 2, 3, 4 } ;

처럼 넣어주면 된다...

2차원 배열도 비슷하다..

int intp [2][3] = { 1, 2, 3, 4, 5, 6 } ;

이렇게 선언하거나,

int intp [2][3] = { {1, 2, 3} , { 4, 5, 6} } ;

이렇게 선언하면 된다..
Posted by 바람처럼..
|

포인터 변수는 다음과 같이 정의할 수 있다..

int *a ;
float *b ;
double *c ;
char *d ;

이렇게 말이다..

그런데 저 포인터 변수들의 크기는 얼마일까??

int 는 4바이트,, double은 8바이트, char는 1바이트 일까??

결론을 말하면.. 모두 4바이트 이다....

포인터 변수는.. 주소값을 저장하는 거지.. 변수의 값을 저장하는 것이

아니기 때문이다...

그렇다면.. 모두 4바이트라면.... 그냥 처음부터..

포인터 변수 자료형을 만들어서 선언하면 되는 것이 아닐까??

예를 들면

point * p ; 같이 말이다....

어차피 모두 4바이트고..

int *a 를 선언했다가.. double 변수의 주소를 받고싶으면...
double d = 1.0f ;
(double *) a = &d ;

처럼 형 변환을 거쳐야 하는 수고도 덜고..

point * p ;
double d = 1.0f ;
p = &d ;

이렇게 쓸 수 있지 않을까???

하지만.. 모든 일에는.. 다 의미가 있는 법..

사실.. 포인터 변수에 형이 필요한 것은.. 포인터 변수 때문이 아니라..

나중에 연산을 하려다 보면 필요한 것이다....

포인터 변수자체는 4바이트 이지만..

나중에 int형 포인터 변수에 int형 주소를 저장하고..

그 int형 포인터가 가리키는 주소의 값을 받아오면..

int형 포인터 변수기 때문에 주소값으로 부터 4바이트의 값을 받아온다...

하지만.. 이것을 하나로 통일해 버리면..

받아올 값이.. int라 4바이트, double이라 8바이트, 머 구조체라서 24바이트 처럼..

컴퓨터가 알아서 가져 올 수 없기 때문에...

우리는 미리 형을 지정해 두어서.. 그 포인터 변수가 어떤 값을 가져올 때..

그 포인터 변수형의 바이트 수 만큼 그 주소에서 읽어 오는 것이다...

그러니 포인터 변수를 사용할 때는 꼭, 받아올 변수의 자료형으로 선언하자!

'프로그래밍 > C,C++' 카테고리의 다른 글

[C,C++] scanf 와 fgets  (0) 2011.08.27
[C,C++] sprintf 사용하기...  (2) 2011.08.23
[C,C++] 문자열에 대하여...  (0) 2011.08.23
[C,C++] 배열의 초기화..  (0) 2011.08.22
[C,C++] C 포인터란 무엇인가..  (0) 2011.08.17
Posted by 바람처럼..
|


포인터,, 언뜻 알고 쓰고 있는 것 같지만, 실제로 사용하다 보면 메모리 릭 문제나, 프로그램을 죽이는 가장 큰 원인이 되는

아주 프로그래머들의 천국과 지옥을 동시에 느낄 수 있게 하는 녀석이다....

편리하지만, 잘못 쓰면 독이 되는 아주 어려운 녀석이다..

오늘은 이 포인터에 대해서 정리를 해볼까 한다...

그렇다면 먼저 포인터란 무엇인가에 대해서 생각해 봐야겠다...

포인터는 한마디로 정의하자면, 메모리의 위치를 표현한 기호라고 생각하면 된다..

int a; 라는 변수를 선언 하였다고 생각해 보자..

a라는 변수가 할당되면서 메모리 주소에는 4바이트 공간이 할당되고, 그 공간의 시작 위치부터 메모리의 주소(번지)를 가지게

된다..

우리가 흔히 a = 4 ; 이런 대입식을 쓰면 a라는 변수에 기록된 메모리 주소에 4를 입력하게된다.. 이런 처리들이 컴파일러와 프

로그램 내에서 알아서 동작을 한다..

이 때 변수 a의 주소값을 가리킬 수 있도록 해주는 것이 바로 포인터 변수이다...

선언할 때 int *a ; 처럼 쓰는 아이들은 포인터 변수이다.. 이것이 중요하다...

*a 와 a 는 다르다..

a가 어떤 내용이 담기는 번지수가 가르키는 공간이라면, *a는 그 번지의 시작점을 가리키는 포인터 변수다....

이렇게 글로 적으면 좀 이해가 안되지만... 계속 머리속에 그려보거나 공책에 그려보면 이해가 될 것이다...

그리고 또 한가지 명심해야 할 것은 포인터 변수에는 주소값만 들어갈 수 있다는 것이다..

int a ;
int *b ;

라고 선언을 했을 때.. 선언 당시에는 int *b를 했지만 그 이후 사용할 때 *b를 쓰면 또 전혀 의도하지 않은 값이 된다..

이때 *는 연산자의 역할을 하기 때문이다...

선언 이외에  *b ; 를 쓰게 되면, *b는 포인터 변수 b가 가리키고 있는 주소의 내용.. 이 된다..

즉,

int *b ;
b = 4 ; << 이 것은 b에 4라는 주소값을 가리키라는 의미이고,

*b = 4 ; << 이것은 현재 어디인지는 모르지만 b가 가리키고있는 공간에 4라는 값을 대입해라.. 라는 뜻이 된다...

일단 이 부분은 넘어가고,

선언된 a, b를 생각했을 때..

b = a ; 라고 적으면 당연히 의도하지 않은 값이 들어간다... 위의 b = 4 와 같은 의미가 되기 때문이다..

이때는

b = &a ; 이렇게 b에 a의 주소값.. 을 넣어줘야 제대로 동작한다...

이렇게 만들게 되면,

a = 4 ; 이렇게 a 에 값을 넣었을 때, *b를 출력해보면 4가 나온다.. 왜냐하면 b가 현재 가리키고 있는 주소는..

a 이기 때문이다..


이렇게 적고 보니, 굳이 왜 쓰는지 이해가 안될 수도 있지만,

참조의 개념에서 보면 정말 꼭 필요한 기능이다..

포인터 헷갈리지 말고 잘 써야할 녀석이다...


Posted by 바람처럼..
|