2009년 05월 25일
당신도 초보일수 있습니다.
프로그래밍 팁(#1) - 배열 넘기기
자기가 자기를 아무리 고수라고 생각해도 필요 없습니다.
리눅스 커널 커미터든 뭐든 상관 없어요...
코드 만들고 '설마 이런 코드가 오류날까' 하고 확인도 안하고 끝내버리면
당신은 여전히 초보입니다.
괜히 엄한일 해서 남 헷갈리게 하지 말아주세요... ㅠㅠ
#include "stdafx.h"
int _tmain(int argc, _TCHAR* argv[])
{
char* dim = {1,2,3};printf("%d", sizeof(dim) / sizeof(dim[0]));
return 0;
}
1>------ Build started: Project: Test, Configuration: Debug Win32 ------제대로 된 코드는 일단 char* dim = {1,2,3} 을 수정해야 하는데, 이런 방법들이 있습니다.
1>Compiling...
1>Test.cpp
1>d:\work\Test\Test\Test.cpp(9) : error C2440: 'initializing' : cannot convert from 'int' to 'char *'
1> Conversion from integral type to pointer type requires reinterpret_cast, C-style cast or function-style cast
1>d:\work\Test\Test\Test.cpp(9) : error C2078: too many initializers
1>Build log was saved at "file://d:\Work\Test\Test\Debug\BuildLog.htm"
1>Test - 2 error(s), 0 warning(s)
========== Build: 0 succeeded, 1 failed, 0 up-to-date, 0 skipped ==========
1. 어떤 경우든 쓸수 있는 일반적인 방법.
char dim[] = {'1','2','3'};이게 일단은 맞는데, string 을 쓰려고 했다면 귀찮아서 이렇게는 잘 안하죠..
unicode 같은걸 지원하려고 하는 라이브러리 같은 경우에는 귀찮은것을 떠나서 이런식으로 코딩하는 경우도 있습니다.
#define UNICODE_CHAR_1 L'1'
#define UNICODE_CHAR_2 L'2'
#define UNICODE_CHAR_3 L'3'
wchar_t dim[] = {UNICODE_CHAR_1, UNICODE_CHAR_2, UNICODE_CHAR3};
2. char 타입이라 쓸수 있는 방법 - 스트링으로 생각.
char dim[] = "123";이 경우에는 sizeof(dim) 이 4 로 나옵니다. (null terminate string 이기 때문에..)
그리고, count_of(a) (= sizeof(a) / sizeof(a[0]) 를 쓰는건 대부분의 경우에 생각처럼 좋지않습니다..
배열형태로 정의된 const string 의 경우에는 쓸만하지만, 보통은 보기에는 좋지만 고려할게 늘어나기 때문이죠.
살짝 예제를 들어보겠습니다.
다음 코드의 결과값을 예측해보세요..
#include "stdafx.h"
char dim[] = "1234567890";
void A()
{
printf("A: %d, %d\n", sizeof(dim), sizeof(dim[0]));
}void B(char* dim2)
{
printf("B: %d, %d\n", sizeof(dim2), sizeof(dim2[0]));
}void C(char dim2[])
{
printf("C: %d, %d\n", sizeof(dim2), sizeof(dim2[0]));
}int _tmain(int argc, _TCHAR* argv[])
{
A();
B(dim);
C(dim);return 0;
}
function B, C 는 꽤나 일반적인 array 의 parameter passing 을 보여줍니다.
count_of 가 범용적으로 사용되기 위해서는 위의 경우에 모두 같은 결과값을 보여주어야 할테지만, 실상은 그렇지 않죠.
결과값은 다음과 같습니다.
A: 11, 1
B: 4, 1
C: 4, 1
계속하려면 아무 키나 누르십시오 . . .
와우. function B 나 C 에서 배열을 넘기기 위해 count_of 를 사용하였다면 꽤나 어이없는 버그가 났겠네요 :D
이건 B 나 C 입장에서는 dim2 가 pointer 이기 때문에 sizeof(dim2) 를 pointer 의 사이즈를 리턴하기 때문입니다.
64bit OS 의 경우에는 아마 8이 나왔겠죠..
이건 제 코딩철학입니다만은, 고려할것이 하나가 늘어나면 버그는 (N+1)^2 로 늘어납니다.
그런 의미에서,
1. count_of 를 써도 되는 곳인지 안되는 곳인지 판단해야 하고
2. count_of 를 쓴 뒤에 array size 가 필요한지 string size 가 필요한지 판단해야 하기 때문에 (저기 위에서 보면 function A 가 sizeof(dim) 으로 11 을 넘겼는데, 그건 배열 사이즈는 null 문자를 포함하기 때문에 문자열 크기 + 1이 되어서 그런 것입니다. string length 가 필요한 경우에는 저기서 1 을 빼야합니다.)
되도록이면 count_of 를 쓰지 않도록 하는편이 낫다고 봅니다. 뭐, 괜찮으시다면 그냥 쓰시는것도 좋긴 하지만요..
ps) 혹시 이글루에 코드 쉽고 예쁘게 올리는 방법 알고 계신분 계신가요?
# by | 2009/05/25 10:40 | Work-IT | 트랙백(1) | 핑백(1) | 덧글(10)





☞ 내 이글루에 이 글과 관련된 글 쓰기 (트랙백 보내기) [도움말]
제목 : 당신 역시 초보일 수 있습니다
자려는데 대략, … “http://lymose.egloos.com/4958036 당신도 초보일 수 있습니다.” 에 트랙백. 저 글에서 트랙백한 원본 글에 나와있는 다음과 같은 코드가 있다. char *dim = { 3, 1, 5, 9, 7 }; foo(dim); /* 5개 합산 -> 정상 */ 의미론적으로 문제가 좀 있긴 하지만, C 코드라고 놓고 보면 하등의 문제가 없는 코드다 — 적어도 C......more
... 처음 글 : http://lymose.egloos.com/4958036트랙백 원글 : http://rein.upnl.org/wordpress/archives/1642 0. 변명...?사실 문법에 크게 신경쓰는 편 ... more
어느 분이 예전에 포스팅 한 적 있어서...
검색해보니, 아래 예제가 있군요.
http://swguru.egloos.com/1992642
하긴, 이런 접근이 필요한 분야가 있을 테니깐요..
SI와 웹만 개발하다 최근에 임베디드 혹은 다양한 운영체제 기반 시스템을 개발하게 되었는데,
다양한 플랫폼에 호환 되는 함수를 만들려다 보면 결국 C++ 도 아니고, C로 개발하게 되더군요.
Visual Studio 6.0 때는 STL 에 이런저런 문제점이 많았습니다.
memory leak 이라던가 : http://affectandrobot.blogspot.com/2008/06/visual-studio-60-stl-memory-leak.html
디버깅 힘듬 : http://eslife.tistory.com/251
Performance 저하 : http://www.eggheadcafe.com/forumarchives/vcstl/nov2005/post24215811.asp
이런 저런 문제점으로 인해 ATL class 인 CList 등을 사용하는 경우도 있고... 해서 STL 아니까 땡이다 라는 생각은 좀 위험합니다.
뭐 그런 것이 아니더라도 포인터는 상당히 기본적인 개념이라 필수적으로 알아두어야 하고요.
C++ 에서 클래스에 대한 개념 없는것 보다 포인터 모르는게 더 안좋더라고요 ^^;
ㅎㅎ