namespace가 예상외의 복병이였군요! 
강좌가 길어집니다..으윽...
그래도 우리는 계속 갑니다~ 오예~
소스/프로그램은 1-5를 통합하여 올리겠습니다.

 *이 강좌는 C언어를 끝냈다는 가정하에 실시합니다.

┌───────────────┐
---앞으로의 목차---
5. namespace에 대해
2-1. bool형에 대해
2-2. Reference란.
└───────────────┘

<지난 강좌를 살펴보고 와주세요 !! : http://blog.naver.com/owndks98o/120155695209 >

1-5-2. namespace에 대해.
강좌를 계속합니다! 길어질수록 지루해 진다는 것을 잘 아는 제가 억지로 끌고 갈 이유야 없지요 하핫;;

방금전 강좌까지
A101::call();
과 같은 선언문을 보았습니다!
잘 보세요~ 어디서 많이 본 선언문 아닌가요?

네~ 그래요.
std::cout std::endl std::endl
과 같은 것들도 똑같은 형태를 하고 있습니다.

그렇다면 유추해 보죠!
std가 무엇일까요? 맞습니다! 바로, std도 namespace랍니다!

우리는 지금까지 std::cout std::cout std::cout ... 정말 너무나도 길게 써왔습니다.
cout, cin, endl 이렇게 간결하게 쓸수 있다면 얼마나 좋을까요?

그렇다면 꿈과 희망을 가능하게 해주는 C++의 능력을 살펴보죠!

/*
Using.cpp
*/

#include

namespace A101{
void call(){
std::cout<<"101동 leanix! 야 나와!"<
}
}
using A101::call;

int main(){
call();
return 0;
}

어엇? A101::call(); 처럼 길게만 작성해야 했던것을 call();로 짧게 작성함을 볼수 있습니다!

이걸 가능하게 해주는 키워드가 무엇일까요?
바로 using 입니다!!

using은 아래의 뜻을 가집니다.
"앞으로 call()이라는 함수를 호출하면 A101의 call을 호출하라!"

그렇다면 std:: 를 없에봅시다!

/*
Using2.cpp
*/

#include
using std::cout;
using std::endl;

int main(){
cout<<"leanix!"<
return 0;
}

후~ 간단해 졌어요~!!

더욱 간단하게 고쳐볼까요?

/*
Using3.cpp
*/

#include
using namespace std;

int main(){
cout<<"leanix!"<
return 0;
}

위의 using namespcae std; 부분은 std라는 namespace를 다 사용하겠다! 하는 선언입니다.

만약, 전역변수와 namespace의 변수가 같은 이름일 빼에는,
namespace의 변수가 우선되므로,
전역 변수를 사용하려면,
::변수명
처럼 이용해 주시면 된답니다!

이것으로 길었던 namespace에 대한 부분을 마칩니다.
더불어 1단원의 끝이기도 하죠.

다음강(2-1)에서는 bool형에 대해 알아보죠!




예상외군요;; 
inline함수의 활약 때문인지 생각보다 강좌가 많이 짧아진것 같네요.
아마 2단원까지는 오늘안에...후훗.ㅋㅋ;;
고고~!!

*이 강좌는 C언어를 끝냈다는 가정하에 실시합니다.

 ┌───────────────┐
---앞으로의 목차---
5. namespace에 대해
2-1. bool형에 대해
2-2. Reference란.
└───────────────┘

<지난 강좌를 살펴보고 와주세요 !! : http://blog.naver.com/owndks98o/120155692576  >

1-5-1. namespace에 대해
지금껏 C만을 공부해 오신 분들이라면 namespace란것이 굉장히 생소할 것이라 생각합니다.
왜냐하면, namespace란 것은 오로지 C++에만 존재하는 것이기 때문이지요.
그렇다면 namespace, 그 기능을 알아볼까요?

먼저, namespace가 뭔지 알아야 겠죠?

"아파트 101동과 102동에 leanix란 아이가 살고 있습니다. 둘다 이름이 같아서 앙숙이지요.
어느날 아파트 밖에서 한 아이가 이름을 부릅니다.
leanix야~ 놀자~
두 leanix는 동시에 대답을 하였고, 서로서로가 더더욱 기분이 나빠졌습니다."

위와 같은 극단적으로 유치찬란한 이야기로 비유해 봅시다.
여기서 여러분이라면 과연 leanix를 어떻게 불렀을까요?
창의적이신 여러분이라면 과연 어떻게 하실지 궁금하지만, 전 아마 이렇게 불렀을 것입니다.

ㅇㅇㅇ동에 사는 leanix야 놀자~

이러면 누굴 부르는지 바로 알수 있지 않나요? 이것이 바로 namespace의 원리입니다.
즉, namespace란
"특정 영역의 범위를 지정하고 이름을 붙여준것"
으로 정의할수 있습니다.

간단한 예를 통해 확인해 보죠.

#include

void call(){
std::cout<<"101동 leanix! 야 나와!"<
}

void call(){
std::cout<<"102동 leanix! 야 놀자!"<
}

int main(){
call();
return 0;
}

위 예제는 인자값과, 함수명이 동일하기 때문에 함수 오버로딩도 성립하지 않습니다.
따라서 에러를 일으키게 되죠.

어쩌면 함수명을 바꿔주는 것이 가장 현명한 방법일지도 모르지만, 우리는 다른 해결책으로 접근해 봅시다.
바로 namespace의 사용이죠.

/*
namespace.cpp
*/

#include

namespace A101{
void call(){
std::cout<<"101동 leanix! 야 나와!"<
}
}

namespace A102{
void call(){
std::cout<<"102동 leanix! 야 놀자!"<
}
}

int main(){
A101::call();
A102::call();
return 0;
}

위 예제는 자칫 안된다고 오해할 요지가 있습니다.
하지만 함수 오버로딩은 이름공간상에서도 성립하기 때문에 옳은 예제가 됩니다.

main함수를 보면
A101::call();
과 같은 함수의 호출문이 등장합니다.

간단하게 생각하셔도 된답니다! A101동의 call을 호출하라! 간단한 의미죠?
그렇다면 namespace에서는 함수의 선언과 정의를 어떻게 분리시킬까요??

/*
namespace2.cpp
*/

#include

namespace A101{
void call();
}
namespace A102{
void call();
}

int main(){
A101::call();
A102::call();
return 0;
}

namespace A101{
void call(){
std::cout<<"101동 leanix! 야 나와!"<
}
}
namespace A102{
void call(){
std::cout<<"102동 leanix! 야 놀자!"<
}
}

간단합니다! 그저 namespace도 위와 같이 두번에 나눠적어주면 되는거죠!

강좌의 길이상, 1-5-2에서 뵙겠습니다!!




흠... 몇분의 공백기간이 있었군요;;
잠시 웹툰보고 오느라 늦었습니다. 하핳;;

*이 강좌는 C언어를 끝냈다는 가정하에 실시합니다.

 ┌───────────────┐
---앞으로의 목차---
4. 인-라인(inline)함수
5. namespace에 대해
2-1. bool형에 대해
└───────────────┘

<지난 강좌를 살펴보고 와주세요 !! : http://blog.naver.com/owndks98o/120155689916 >

1-4. 인라인(inline)함수

인라인(inline)이란 의미를 프로그래밍적으로 보지 말고 영어처럼 해석해 봅시다.
in은 안쪽에 라는 의미를 나타내고, line은 선,줄 을 나타냅니다.
즉, inline함수란 코드안에 들어간 함수를 일컫겠군요!!

우리는 C언어를 공부하면서 매크로함수에 대해 알게되었습니다.

/*
MacroExample.cpp
*/

#include
#define ADD(X,Y) ((X)+(Y))

int main(){
std::cout<
return 0;
}



위와 같이 매크로 함수를 이용하면, 소스내에 매크로가 완전히 대치되기 때문에,
속도와 메모리상의 이점이 있을 것입니다.

위와 같이 함수의 호출이 소스내에 완전히 들어가버리는 현상 을
"함수가 inline화 되었다"
라고 합니다.

하지만 C에서는 inline함수를 만들기 위해서는, 매크로를 사용하여야 했기 때문에 함수의 정의가 까다로웠습니다.
또한 그 정의의 까다로움 때문에 프로그래밍상의 여러가지 단점이 있기도 하였지요.

하지만 C++에서는 정말 말끔하게 해결할수 있습니다.
바로, 함수의 정의 앞에 inline키워드를 붙여주는 것으로 끝나게 되지요.

/*
CppMacroExample.cpp
*/ 

#include

inline int ADD(int a,int b){
return a+b;
}

int main(){
std::cout<
return 0;
}

훨씬 간결해 짐을 느낄수 있으실 것이라 생각합니다.

하지만, 비록 C++에서 이런 편리한 기능을 제공한다고는 하나,
요즘에 나오는 컴파일러들은 더욱 엄청난 것들이기 때문에, 컴파일러가 알아서 inline키워드를 붙이기도 합니다.
또한, inline키워드를 붙여도 불필요하다고 판단되는 경우, 무시해 버리기도 한답니다.

이번강에서는 inline함수를 알아보았습니다!
다음강(1-5)에서는 namespace가 뭔지 간략하게 알아볼까요?!?!




비록 짧지만 그래도 오늘로써 3번째 강좌, 5번째 글이군요!!
왠지 오늘 1단원은 다 끝낼수 있을 것 같아요 ㅋㅋ;;
저도 도움이 된다면야 열심히 합니다!

*이 강좌는 C언어를 끝냈다는 가정하에 실시합니다.

 ┌───────────────┐
---앞으로의 목차---
3. 디폴트 매개 변수
4. 인-라인(inline)함수
5. namespace에 대해
└───────────────┘

<지난 강좌를 살펴보고 와주세요 !! : http://blog.naver.com/owndks98o/120155687323 >

1-3. 디폴트(Default) 매개변수

이전강(1-2) 에서는 함수 오버로딩에 대해서 설명하였습니다.
함수 오버로딩을 통해, C++에서의 함수의 강력한 기능을 엿볼수 있었습니다.
하지만 C++에서의 함수는 이게 다가 아니라는 사실! 알고 계신가요?
모르시다면! 같이 알아보죠!!

디폴트(Default)란 컴퓨터공학에서는 "기본적인"이란 의미를 가집니다.
그렇다면 함수에서의 디폴트 매개변수란 무엇일까요?

바로,
"인자를 전달하지 않으면 기본적으로 이 값을 전달하겠다"
라고 해주는 것을 디폴트 매개변수라고 합니다.

/*
DefaultParameter.cpp
*/

#include

void func(int a=0){
std::cout<
}

int main(){
func();
func(30);
return 0;
}

위 코드는 디폴트 매개변수의 예를 보여주고 있습니다.
첫번째 함수 호출처럼, 아무런 인자를 전달하지 않을경우 인자로 0이 전달된 것으로 간주합니다.
결과는 0과 30이 출력되겠군요.

위에서는 아래와 같은 것이 성립합니다.

func()==func(0)

즉, 디폴트매개변수를 이용하면, 위와 같은 2가지의 방식을 동일하게 사용할수 있습니다.

그렇다면 더욱 많은 인자를 가지고 있는 디폴트 매개변수의 예를 살펴보죠.

/*
DefaultParameter2.cpp
*/

#include

int func(int a=1, int b=2, int c=3){
return a+b+c;
}

int main(){
std::cout<
std::cout<
std::cout<
std::cout<
return 0;
}

마치 함수오버로딩을 보는 것 같은 느낌입니다 :D
위 프로그램은 6 15 33 60 으로 출력되겠군요!

지금껏 디폴트 매개변수를 보면서 함수오버로딩을 많이 떠올리셨을 것입니다.
그럼, 함수오버로딩과 디폴트매개변수가 섞인다면?!?!

#include

int func(int a=10){
return a;
}

int func(){
return 10;
}

int main(){
std::cout<
return 0;
}

안타깝게도 위와 같은 코드는 에러를 일으킵니다.
main함수를 보세요! 과연 무엇을 가르키는걸까요? 저도 알수 없군요 하핫;;

이번시간에는 정말로 쓰임이 많은 디폴트(Default) 매개변수를 알아봤습니다!

그럼 다음강(1-4)에서는 인-라인 함수를 알아보죠!




안녕하세요? 강좌도 작게 작게 많이 하려고 준비한 강좌이니 만큼,
댓글수에 연연하지 않고 쾌속으로 나가도록 하겠습니다!!

오늘 하루... 최대한 올려보죠 ㅋㅋ

*이 강좌는 C언어를 끝냈다는 가정하에 실시합니다.

 ┌───────────────┐
---앞으로의 목차---
2. 함수 오버로딩
3. 디폴트 매개 변수
4. 인-라인(inline)함수
└───────────────┘
<지난 강좌를 살펴보고 와주세요 !! : http://blog.naver.com/owndks98o/120155673402 >

1-2. 함수 오버로딩(Function Overloading)

C언어를 배우면서 프로그래밍이란 것에 어느덧 관심이 가길 시작했던 부분이 언제였을까요?
아마도 내 입맛대로 디자인 할수 있는 함수를 배우면서 일것이라 생각합니다. 저역시 그러했고요.
C++에서는 C보다 더욱 넓은 함수의 기능을 제공합니다.
알아볼까요?

void func(void){}     //ㄱ.
void func(int a){}    //ㄴ.
void func(char c){} //ㄷ.

이런, 전혀 쓸데없는 함수 3가지가 있다고 가정해 봅시다.
하지만 이런 소스는 C언어에선 분명 문제가 있습니다.
바로 같은 이름의 함수가 선언되었다는 것이죠.

하지만 C++에서는 다르게 생각해 봐야 할 부분일 것입니다.
이 소스의 메인함수가 아래와 같이 정의되어 있을때,

int main(){
func();      //1번
func(10);   //2번
func('a');  //3번
reuturn 0;
}

당연히 여러분은,
1번함수는 위의 'ㄱ'에 해당하며, 
2번함수는 위의 'ㄴ'에 해당하며,
3번함수는 위의 'ㄷ'에 해당한다는 사실을 알 것이라 생각합니다.

바로 이것이 C++의 아이디어, 함수 오버로딩 입니다.

따라서, 함수오버로딩이란, 함수명은 같으나 인자의 타입이나 수가 다른 함수의 선언을 허용하는 것 을 일컫습니다.

함수 오버로딩의 조건은 정말로 간단합니다.
"인자의 갯수가 다르거나, 타입이 다르거나!"
간단하죠?

아래의 소스는 함수 오버로딩을 보여주고 있습니다.

/*
Function Overloading.cpp
*/

#include

void func(){
std::cout<<"FUNC 1 CALLED"<
}

void func(int a){
std::cout<
}

int main(){
func();
func(10);
return 0;
}

그렇다면 만약, 리턴값이 다르면 어떻게 될까요?

void func(){}
int func(){return 10;}

위와 같이 인자값,함수명은 같으며 리턴값이 다른 함수가 있습니다. 과연 함수오버로딩은 성립할까요?

int main(){
func();
return 0;
}

답은 X입니다.
위의 메인함수를 보면 도무지 무엇을 호출했는지 감이 잡히지 않죠.

오해하지 않으시길 바랍니다.

그럼 다음강(1-3)에서는 디폴트 매개변수를 알아보죠!




[출처] [C++ 강좌] - 1-1.달라진 입출력 -|작성자 leanix




안녕하세요? leanix입니다!
이제부터 C++에 대한 강좌를 시작할 것이며, 많은 것을 알아가셨으면 하는 마음을 가지고 시작합니다.

강좌에 나온 모든 예제는 컴파일후, 소스와 프로그램을 올리겠습니다.

*C언어를 배우셨다는 전제하에 실시합니다.

┌───────────────┐
---앞으로의 목차---
1. 달라진 입출력
2. 함수 오버로딩
3. 디폴트 매개 변수
└───────────────┘

1-1. 달라진 입출력

C언어를 배우며 제일 처음 접해본 프로그램이 아마, HelloWorld.exe 였을 것이라 생각합니다.

#include

int main(){
printf("Hello World!");
return 0;
}

이런 간결하고도 간결한 코드였죠.
C++에서도 마찬가지로 C++스타일의 Hello Word 를 작성하는 것으로 그 장대한 시작을 울려봅시다!

/*
HelloWorld.cpp
.cpp 를 사용하셔야 합니다. C++의 문법을 적용시키기 위함입니다.
*/

#include

int main(){
std::cout<<"Hello World"<
std::cout<<'A'<<123<
return 0;
}

이것이 C++의 출력의 기본입니다.
C++에서는,
iostream 헤더를 포함시킵니다.
std::cout<<출력할것  의 형식으로 출력을 합니다.
std::endl은 한줄을 넘기는 의미를 지닌다.(=\n)(endline의 약자)
std::cout<<출력1<<출력2; 등의 형식으로 이어쓸수 있다.
간단하죠??

그렇다면 이번에는 C++스타일의 입력을 알아봅시다.

/*
Plus.exe
*/

#include

int main(){
int v1,v2;

std::cout<<"1번쨰 숫자입력 : ";
std::cin>>v1;

std::cout<<"2번째 숫자입력 : ";
std::cin>>v2;

int result=v1+v2;
std::cout<<"덧셈 : "<
return 0;
}

그렇게 어렵지 않아 보입니다.
std::cin>>변수  의 형식을 통해 값을 입력받습니다.
역시, std::cin>>변수1>>변수2; 의 형식을 취할수 있습니다.
C와는 다르게, 변수의 선언이 앞부분 뿐만이 아닌, 어디서도 할수 있습니다.
이것이 printf, scanf를 대신하는 C++의 다입니다! 간단하죠??

덤으로, C++에서는

int i;
for(i=0; i<10; i++){...}

같은 코드를,

for(int i=0; i<10; i++){...}

처럼 줄일수 있습니다.

또한 Visual Studio 7.0 이상부터는 지역변수로 인정이 되어서,

for(int i=0; i<10; i++){
std::cout<
}
int i;

처럼 변수를 두번 선언하는 코드도 상관이 없답니다!!

그럼 다음강(1-2) 에서는 함수 오버로딩에 대해 알아봅시다!!
[출처] [C++ 강좌] - 1-1.달라진 입출력 -|작성자 leanix














[1] 문자열 출력

C언어 출력 함수는 printf 입력 함수는 scanf 함수등이 있었다.

우선 설명하기전에 예제를 하나보고 분석해보도록 하겠습니다.

꼭 직접 컴파일러에 입력해보시기 바랍니다.! (단! 파일의 이름을 지정할때 확장자는 반드시

.cpp로 지정해주셔야 C++문법규칙을 적용한 C++컴파일로 컴파일이 될수 있습니다.)

컴파일러 설치및 실행방법은 ( http://blog.naver.com/net_zhdk/120149784643 ) 여기나

아니면 인터넷에 직접 검색하는것이 좋습니다.!


실행 결과

위의 예제 소스코드를 자세히 보면 출력에 관한 몇가지 사실을 알 수 있다.

우선 이해하지말고 살펴보기만 하자.

헤더파일 선언 #include
std::cout<< 를 이용한 출력
std::endl 를 이용한 줄바꿈(개행)
우선 이 3가지에 대해 알아보도록 하겠습니다.

[1-1] 헤더파일 선언 #include

C언어 배우신분들은 알겠지만. C언어에서 printf 출력함수를 사용할려면 #include

이 헤더파일을 추가 해줘야만 printf함수를 사용할 수 있다.

이와 똑같이 C++언어 에서 출력하기 위해서는 #include 헤더파일을 선언해줘야 한다.

근때 강좌를 읽는분들은 이런 질문이나 생각을 할 수 도 있다.

왜 C언어 에서는 stdio.h 헤더파일 h 확장자를 붙여줫는데 C++언어 에는 그냥 iostream인가요?

맞는 말이다 ! 하지만 헤더파일 확장자는 C언어와 마찬가지로 .h 이다. 그렇지만 C++에서는

프로그래머가 만든 헤더파일이 아닌 이상, 즉 표준 헤더 파일선언에는 확장자를 않붙여주기로

약속을 했다.! 과거 C++에는 붙여줫지만 새로운 표준 라이브러리에는 확장자를

떼어 줫다.!

[1-2] std::cout<< 를 이용한 출력

위 예제에서는 뭔가를 출력하기 위해 std::cout<< 라는 문장을 사용햇었다.

사용방법은 이렇다.!

std::cout<<"출력대상";

"출력대상" 이 위치에는 무엇이든 올수 있다. 정수 또는 실수 또는 문자 문자열 공백 변수도

올수있다. C언어에서는 변수에 담긴 값들을 출력할려면 서식문자를 지정해줘야만 햇는데

C++에서는 데이터 성격에 따라 출력이 이뤄진다. 조금씩 알아가고 있지만..

아직은 정확히 모든것을 알 수 없다.. 앞으로 공부하면서 천천히 다 알게 될껏이다.

[1-3] std::endl 를 이용한 줄바꿈(개행)

그리고 자세히 문자을 보면 << 연산자가 있다. 사실 이것도 연산자 이다. 이 연산자를 이용하면

둘 이상 출력대상을 연이어 지정해줄 수 있다.

std::cout<<"출력대상1"<<"출력대상2"<<;

즉, << 연산자는 둘 이상의 데이터 출력을 할때 쓰이는 연산자이다.

그리고 std::endl 문장은 개행이다. C언어에서는 특수문자(이스케이프 시퀀스) 문자열 끝에 \n를

사용햇지만 C++에서는 std::endl 를 사용하여 문자열을 개행을 한다.


[2] 데이터 입력

이번에는 키보드로부터 뭔가를 입력 할 때 쓰이는 것들을 알아보도록 하겠다.

C언어에서는 입력함수 대표적인 scanf함수가 있었다.

그럼 C++에는 std::cin>> 이 있다.

이번에도 먼저 예제를 입력해보면서 분석해보도록 하자.


실행결과


위의 예제를 살펴보면 두가지 사실을 알수 있다.

키보드로부터의 데이터 입력에는 std::cin 과 >> 연산자가 사용된다.
C++ 언어의 변수 선언은 어디서든 가능하다.

[2-1] 키보드로부터의 데이터 입력에는 std::cin 과 >> 연산자가 사용된다.

위의 예제에 보이듯이 키보드로부터 뭔가의 데이터를 입력받을려면 이렇게 해야 된다.

std::cin>>입력변수;

입력변수 의 위치에는 데이터의 값을 저장할 변수이름이 오면 된다.

그리고 더불어 C++에서도 서식문자 지정을 않해줘도 된다.

[2-2] C++언어의 변수 선언은 어디서든 가능하다.

C언어에서 프로그램 작성할때 변수 선언은 함수 안에서 제일 먼저 등장 해야 햇다.

하지만 C++언어 에서는 함수 내 어디 위치든 변수 선언이 가능하다.

그리고 한 가지 더 std::cout<<"출력대상1"<<"출력대상2"; 와 같이..

입력 std::cin>> 도 여러가지 입력변수를 지정할수 있다.

std::cint>>입력변수1>>입력변수2; 이렇게




컴퓨터에서는 같은 1234 라고 해도, 문자열로서의 1234 일 수도 있고, 진짜 숫자로서의 1234 일 수도 있습니다.

문자로서의 숫자를, 진짜 숫자로 바꾸어서 연산을 할 수 있게 해주는 함수들입니다.

atoi() : String To int


문자로 된 숫자를, 진짜 숫자의 정수로 변환
#include
#include

int main() {
  int num;
  char *s = "1234.9999";

  num = atoi(s);
  printf("문자 = %s\n숫자(int) = %d\n", s, num);

  return 0;
}


실행 결과:
문자 = 1234.9999
숫자(int) = 1234


만약 문자열에 소수점이 있다면 반올림하지 않고 소수점 이하를 무조건 무시합니다. 에러가 난다면 0을 반환합니다.
그래서 위의 소스가 만약 char *s = "ABCD"; 이렇게 되었다면 "숫자(int) = 0" 으로 출력됩니다.

atoi() 함수는 stdlib.h 에 정의되어 있습니다.



atol() : String To long


int 가 아닌 long형 정수로 변환할 때는 atol()을 사용합니다.
#include
#include

int main() {
  long num;
  char *s = "98765432";

  num = atol(s);
  printf("문자열 = %s\n숫자(long) = %ld\n", s, num);
  return 0;
}


실행 결과:
문자열 = 98765432
숫자(long) = 98765432




atof() : String To double


문자로 된 숫자를, 진짜 숫자의 실수로 변환
#include
#include

int main() {
  double f;
  char *s = "12345.67";

  f = atof(s);
  printf("문자열 = %s\n실수(double) = %0.3f\n", s, f);

  return 0;
}


실행 결과:
문자열 = 12345.67
실수(double) = 12345.670


atof() 함수는 double형 실수를 반환합니다. 그래서 이것을 float형 실수로 받으면
warning C4244: '=' : conversion from 'double' to 'float', possible loss of data
이런 경고가 나오게 됩니다.




▶▶ [C언어] 숫자(정수;int, long, unsigned long)를 문자열로 변환하는 함수 - itoa()

▶▶ [C언어] 숫자(실수;float)를 문자열로 변환하는 함수 - sprintf()



16진수 문자열을 숫자로 변환: ▶▶ C언어] 헥사(HEX; 16진수) 문자열을, 10진수 정수 숫자로 변환 함수; Hex String to Int Number

2진수 문자열을 숫자로 변환: ▶▶ C언어] 2진수 문자열을, 10진수 정수 숫자로 변환 함수; Base-2 String to Int Number


typeid, type_info 

 

필요헤더 : typeinfo.h 또는 typeinfo( std 이름공간 사용, 밑에서는 생략 )

 

두 타입이 같거나 같지 않음을 비교, 또는 타입을 문자열로 바꿔줄 때 typeid와 type_info를 사용할 수 있다.

 

이 두 녀석은 '실행시간' 에 행해진다.

 

먼저 두 타입을 비교하기 위해서는 typeid( 타입 ) 을 사용한다. typeid 는 지정한 타입에 특정지어지는 type_info 의

 

참조값을 반환한다. type_info 는 ==, != 연산자를 가지고 있어서 이 연산자를 통해 비교할 수 있다. 즉,

 

if( typeid( int ) != typeid( char ) )

    printf( "같지 않은데요.\n" );

 

위와 같이 사용할 수 있다.

 

만약 type_info 의 참조값을 어디엔가 유지하고 싶다면 다음을 주의하자. 타입에 대한 참조값은 항상 일정한 것은 아니다. 이것은

 

&typeid( int ) == &typeid( int ) 가 항상 성립한다고 볼 수 없다는 것이다. 참조값을 유지한다면 참조에 대한 포인터를 유지하고

 

비교시 포인터의 값을 비교해야 된다.

 

예 :

    const type_info *int_type = &typeid( int );

    const type_info *char_type = &typeid( char );

 

    if( *int_type != *char_type )

        printf( "같지 않은데요.\n" );

 

 

다음으로 타입에 대한 문자열을 얻는 방법인데, 이것은 type_info 객체를 이용하는 것이다.

 

type_info 클래스는 생성자와 복사대입연산자가 private 로 설정되어 있어서 객체를 직접 생성하는 것은 불가능하고

 

typeid 로부터 얻어내야 한다. type_info 멤버함수에는 name() 함수가 있는데 이것은 자료형에 대한 const char* 타입의 문자열을

 

반환해준다. 즉,

 

printf( "이 타입은 %s타입이네요.\n", typeid( int ).name() );

 

과 같이 작성할 수 있다. 하지만 타입에 대한 문자열 변환은 표준에 없는 내용이어서 그 결과를 예측하기는 어렵다.

 

VC++6.0 에서는 다음과 같은 형태로 출력해준다.

 

class A

{

...

};

 

printf( "이 타입은 %s타입이네요.\n", typeid( A ).name() );

 

결과 : 이 타입은 class A타입이네요.

포인터? 생각만 하면 머리가 아파오는 녀석이죠..C 언어로 생계를 유지해온 저로서도 복잡한 포인터를 보면 피하고 싶습니다..이런 포인터 인데 함수포인터라니? 이건 뭐 대마왕급이군요...

그런데 이런 대마왕도 상황에 따라, 그리고 고급프로그래밍을 위해서 간간히 써주어야만 하는 돌발상황이 발생하곤 합니다..어쩔수 없는 운명이죠..TT

피할수 없다면 한번 부딪혀 보는 건 어떨까요? 기초 개념만 잡으면 너무 쉽다(?)고 느끼실 겁니다..자, 그럼 기본부터 한번 시작해 보겠습니다..

우선 다음과 같은 코드를 보죠..아주 단순한 코드입니다..

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

main()

{

int a = 10;

int* b = &a;

...

...

}

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

변수 a 에 10을 대입하고 변수 b 에는 a 의 주소값을 저장합니다. 그럼 여기서 질문하나 해볼까요? 변수 a 와 b 는 어디에 존재할까요? CPU ? 하드디스크 ? 아님 메모리?

모두 아시겠지만 변수는 메모리, 정확히 말하면 RAM 에 존재합니다. 아래 그림에 간략히 나타내보았습니다.

그럼 다음 코드를 한번 보겠습니다..좀전보다 조금 어렵습니다..(???)

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

void func(int x)

{

printf("x = %d\n",x);

}

main()

{

int a = 10;

int* b = &a;

func(a);

}

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

이번에는 함수 func 라는 놈이 등장했네요..여기서 다시 질문하나 할께요..변수는 RAM 에 저장되는데 그럼 함수 func 는 어디에 저장될까요? 또 main 도 특별한 함수죠..즉, 시작할때 제일 먼저 불리는 함수..이런 함수들은 도대체 어디에 존재하는걸까요????

함수는 변수와 마찬가지로 RAM 에 저장되어 있습니다...왜냐면 실행되는 모든 프로그램은 RAM 에 저장되어야 하는데 함수도 프로그램의 일부이니까요..그림으로 나타내 볼까요..

위 그림처럼 RAM 의 어딘가에 func 라는 함수부분이 저장되어 있습니다. RAM에는 언제나 주소가 있죠? 예를 들어 변수 a 는 &a 라는 주소에 있고 변수 b 는 &b 라는 곳에 있습니다. 그럼 func 는 어디에 있을까요?

주소를 나타내려면 & 를 붙인다고 했으니 &func? 아님 임의의 다른곳??

C 언어에서 함수가 저장되어 있는 주소값은 바로 함수 이름입니다. 즉, 함수이름이 함수가 저장되어 있는 첫번째 번지를 나타냅니다. (마치 배열과 비슷합니다. 배열 이름이 배열의 시작주소를 나타내는 것처럼요..) 그래서 func 라는 함수가 저장되어 있는 번지는 func 이고, main 함수가 저장되어 있는 번지는 main 입니다..(많이 헛갈리시죠..예전에 제가 그랬습니다...)

이제 함수가 저장되어 있는 주소값을 알았으니 그 값을 저장할수 있는 변수도 있어야겠죠..이렇듯 함수가 저장되어 있는 주소값을 저장할수 있는 변수를 '함수포인터' 라고 합니다. 즉, 함수포인터는 함수의 이름을 가지는 변수입니다..

그럼 함수이름을 저장할수 있는 변수는 어떻게 선언하고 초기화 할까요? 다음의 소스를 한번 보죠..

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

void func(int x)

{

printf("x = %d\n",x);

}

main()

{

int a = 10;

int* b = &a;

void (*test)(int);

test = func;

func(a);

}

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

우선 'void (*test)(int);' 부분입니다. 해석을 해보면 test 라는 변수는 인자로 한개의 정수(-int-) 를 가지고 반환형이 없는 (-void-) 함수를 가리키는 포인터이다 입니다. 이렇게 선언된 test 라는 변수에 func, 즉 func 가 저장되어 있는 주소값(-함수이름-)을 대입하는 곳이 소스에서 'test=func' 입니다. (func 함수가 인자로 정수한개를 받고 반환형은 없죠..확인해보세요)

그림을 통해 이해해보죠..

이제 마지막으로 함수포인터를 통해 함수가 어떻게 호출되는지 알아보겠습니다..소스코드에서 변수 포인터 b 를 통해 a 를 접근하고자 할때 '*b' 라고 기술했습니다. 그럼 함수포인터는 ? 함수포인터도 변수 이므로 *b 처럼 * 연산자를 이용해 함수를 접근할수 있습니다.다음의 코드를 보면서 결과값이 같다는 것을 확인해보시기 바랍니다...코드에서 (*test)(a) 의 해석은 다음과 같다고 할수 있습니다. 'test 라는 변수가 가리키는 곳에다 a 값을 넘겨준다'

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

void func(int x)

{

printf("x = %d\n",x);

}

main()

{

int a = 10;

int* b = &a;

void (*test)(int);

test = func;

func(a);

(*test)(a);

}

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

어떠신가요? 함수포인터라고 무시무시한 이름을 가지고 있지만 막상 별것 없죠..이런 함수포인터는 속도가 중요시되거나 그래픽관련 프로그래밍을 구현하고자 할때 가끔 쓰입니다. 또한 커널 프로그래밍을 할때도요..그러나 기본에 충실하시면 어렵지 않게 이해 할수 있을거라 믿습니다..

(이제 함수 포인터는 대마왕의 자리를 내주고 쓸쓸히 은퇴해야겠네요..)

다음의 예제를 한번 풀어보시고 이해해 보시기 바랍니다...(다음주제는 네트웍프로그래밍을 진행해 볼까 합니다..많은 응원부탁 ^^..)

언제나 즐거운 시간만 되세요...

[1] int (*fPtr1)(int); [이해난이도 : 하]

[2] int (*fPtr2)(int, int); [이해난이도 : 하]

[3] void (*signal(int, void(*handler)(int)) ) (int); [이해난이도 : 최상]

+ Recent posts