당신도 초보일수 있습니다. Work-IT

프로그래밍 팁(#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 ------
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 ==========


제대로 된 코드는 일단 char* dim = {1,2,3} 을 수정해야 하는데, 이런 방법들이 있습니다.

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) 혹시 이글루에 코드 쉽고 예쁘게 올리는 방법 알고 계신분 계신가요?

핑백

덧글

  • Anonymous 2009/05/25 10:53 # 답글

    </pre> 로 묶으면 된다는 말이 있더군요.
  • KHAN 2009/05/25 15:38 #

    답변 감사드립니다.
  • 써니 2009/05/25 11:38 # 답글

    css(cascading style sheet)를 설정해야 하는데,
    어느 분이 예전에 포스팅 한 적 있어서...

    검색해보니, 아래 예제가 있군요.

    http://swguru.egloos.com/1992642
  • KHAN 2009/05/25 15:38 #

    흠... 다음에 글쓸때 확인해봐야겠네요 ㅎㅎ. 감사합니다.
  • ayh1800 2009/05/25 17:17 # 답글

    솔직히 말씀드리면, 그냥, C++의 string 객체나, vector를 사용하는게 속편하겠다는 생각이 듭니다.
    하긴, 이런 접근이 필요한 분야가 있을 테니깐요..
  • 써니 2009/05/25 19:54 #

    실행 속도와 호환성 측면 때문에 C로 구현하는 경우가 의외로 많이 있습니다.

    SI와 웹만 개발하다 최근에 임베디드 혹은 다양한 운영체제 기반 시스템을 개발하게 되었는데,
    다양한 플랫폼에 호환 되는 함수를 만들려다 보면 결국 C++ 도 아니고, C로 개발하게 되더군요.
  • KHAN 2009/05/25 20:05 #

    Visual Studio 2008 은 어떨런지 잘 모르겠는데 (이런 글이 있긴 한데 왠지 정황상 C#을 의미하는것 같군요... http://kaistizen.net/EE/index.php/weblog/comments/stlclr_performance_issue/ )
    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++ 에서 클래스에 대한 개념 없는것 보다 포인터 모르는게 더 안좋더라고요 ^^;
  • 우주괴물 2009/05/25 19:24 # 답글

    전 c 스타일 배열을 쓸때 싸이즈는 그냥 define거는편입니다. 프로그래머가 확실하게 싸이즈값을 알고 쓰는게 나을거 같습니다.
  • KHAN 2009/05/25 20:06 #

    뭐 그런데 사실 string 의 경우는 length 를 얻기위해 뻘짓하는게 귀찮을때도 있죠.. 속도도 느리고요.
  • 오린간 2009/05/26 01:35 # 답글

    호. 그래서 그런가 strcpy_s 라는 함수가 있자나요.
    ㅎㅎ
댓글 입력 영역