Skip to main content

C++ of the Day #4 - Changing const object

Question

오늘은 별로 흥미진진한 내용은 아니네요. 역시 뉴스그룹에서 가져왔습니다. ((comp.lang.c++.moderated:prog output?))
#include "iostream.h"

void main(void)
{
  const int i = 10;
  int *p;
  p = const_cast(&i);
  *p = 111;
  cout << i << "  " << *p;
}
/*
output:
10  111 
*/
질문은...
  1. 왜 i 와 *p의 출력이 다르게 나오는가?


Answer

뉴스그룹의 친절한 답변자들 모두 답에 앞서 코드에 있는 문제들을 지적하네요.
  1. 표준 헤더를 쓸 생각이었다면 iostream.h가 아니라 iostream을 써야 할것이다.
  2. 또한 표준 헤더라면 <>괄호를 사용하여야 한다.
  3. main의 리턴 타입은 int이다.
모두 적용하면 다음과 같이 되겠군요.
#include 

int main()
{
  const int i = 10;
  int *p;
  p = const_cast(&i);
  *p = 111;
  std::cout << i << "  " << *p;
}
진짜 중요한 문제의 답은 간단합니다.
const 객체를 수정하는 코드의 결과는 정의되어 있지 않으므로(undefined behavior) 컴파일러는 위 프로그램에서 어떤 값이라도 출력할 수 있습니다.
너무 간단하죠? 참고로 undefined behavior에 대해 얼마전 DDJ에 올라온 Pete Becker의 Living By the Rules에서 인용해봅니다.
Violations of semantic rules that are not diagnosable semantic rules result in undefined behavior; that is, the C++ Standard doesn't impose any requirement on what a compiler does when faced with such code. When referring to this, please don't use the abominable wording "This program invokes undefined behavior." The correct phrasing is "The behavior of this program is undefined." And please keep in mind that undefined behavior means only that the C++ Standard doesn't say what the code in question does. It does not mean that compilers are obliged to do nasty things like set fire to your hard drive. Often, the best way to write code that takes maximal advantage of the hardware it will run on is to use code constructs whose behavior is undefined, but well understood. For example, if you really need speed, instead of testing whether an integer value is greater than or equal to zero and less than some upper limit, you can convert it to an unsigned integer type with the same number of bits and test whether the result is greater than the upper limit. On most architectures, converting the value doesn't change any bits, so it doesn't require any code; negative values are simply treated as large unsigned values, which will always exceed the limit. The behavior of that code is formally undefined, but it works. Except when it doesn't. Test for it.
마지막 부분에 있는 undefined behavior의 사용예를 보니 간단하면서도 아이디어가 좋네요. 실제로는 가독성이라던가 유지 보수성을 감안했을땐 사용하지 않는게 좋겠죠? :-)

Comments

Popular posts from this blog

1의 개수 세기

저도 간단한 알고리즘 문제 하나... :-)

어떤 수 n이 주어졌을때 1~n까지의 수를 쭈욱 썼을때 나오는 1의 개수를 구하는 문제입니다.

예를 들어 13이라는 수가 주어지면 1~13까지의 수 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13에서 1은 1, 10, 11, 12, 13에 나오며 그 개수는 6이 됩니다. 즉, f(13)=6.

원래 문제는 f(n)=n이 되는 1이 아닌 가장 작은 수를 구하는 문제인데 이 문제의 경우에는 처음부터 쭈욱 세어나가면 되기 때문에 간단히 다음과 같이 구현을 하면 됩니다. ((한가지 주의할 점은 이전에 찾았던 n-1값을 사용하지 않고 다시 처음부터 n까지 값을 계산하면 시간이 너무 많이 걸린다는 점입니다. 위의 코드에서는 static 변수를 사용하여 이전 값에 계속 더해나가는 방법을 사용했습니다.))


#include

int count1(int n)
{
static int cnt = 1; // not 0 because n starts from 2. see main.

while (n > 0) {
if ((n % 10) == 1) ++cnt;
n /= 10;
}

return cnt;
}

int main()
{
using namespace std;

int n = 2;

while (count1(n) != n) ++n;
cout << n << endl;
}


좀 재미가 없죠? 그래서 이번 문제는 어떤 수 n에 대해서 f(n)을 O(1)시간에 구하는 알고리즘을 만드는 것입니다. 관심있으신 분들은 한번 풀어보세요. 제가 만든 코드는 내일 올려보겠습니다.

C++ of the Day #9 - Boost.Python 사용하기 #1

Python은 가장 인기있는 interpret 언어중의 하나입니다. Python의 장점 중 하나는 C/C++ 모듈과 쉽게 연동할 수 있다는 점입니다. 물론 손으로 일일히 wrapper를 만드는 것은 손이 많이 가고 에러를 만들수 있는 작업이나 SWIG등과 같은 도구를 사용하면 쉽게 python 모듈을 만들 수 있습니다.

Boost.Python은 이런 SWIG와 같이 python 모듈을 쉽게 만들 수 있도록 도와주는 라이브러리로 순수 C++만을 사용한다는 점이 SWIG와 다른 점입니다. 그리고 개인적으로는 Boost 라이브러리에 포함되어 있는 것들이 왠지 좀 더 믿음직스러워서... :-)

이번 글에서는 Boost.Python 문서에 나와 있는 예제를 가지고 간단하게 python 모듈을 만드는 방법에 대해서 알아보겠습니다.

Requirements리눅스
이 글에서는 리눅스 환경에서의 사용 방법을 설명한다.Boost.Python 라이브러리 (1.33.1)
Boost 라이브러리를 다운로드받아 아래와 유사한 명령으로 라이브러리를 빌드한다.
bjam -sTOOLS=gcc -with-python install

bjam의 --prefix 옵션으로 라이브러리가 설치될 위치를 변경할 수 있다.Python 라이브러리 (2.4.3)
Python을 다운로드 받아 빌드하여 설치한다.
위의 경우와 유사하게 configure의 --prefix 옵션으로 설치될 위치를 변경할 수 있다.

Write C++ Code다음과 같이 코드를 작성한다.

// greet.cpp #include <stdexcept> char const* greet(unsigned x) { static char const* const msgs[] = { "hello", "Boost.Python", "world!" }; if (x > 2) throw std::range_error("greet: index out of range"…

Hello Wordpress, again.

한 두주일 정도 Textpattern을 사용해봤는데 다시 Wordpress로 돌아오기로 결정했습니다. 무엇보다 스킨 변경이 너무 복잡하고 사용자층이 Wordpress에 비해 너무 앏네요. 원하는 plugin도 찾기 어렵고... :-|

그동안 Textpattern에 썼던 글들은 모두 Wordpress로 옮겼습니다. 2개 있던 댓글도 옮겼는데 그중의 하난 제가 쓴... ;-)

애초에 wp-dokuwiki plugin이 무거워서 옮겼던 것이라 이 plugin은 설치를 안할 예정인데 몇가지 아쉬운 점이 있네요.

첫째는 code highlighting 기능인데 이 기능은 예전에 만들어 놨던 것을 조금 수정해서 쓰려고 준비중입니다. 두번째는 Footnote 기능인데 찾아보니 Footnotes 0.9 Plugin for WordPress 2.0.x라는게 있네요.

이정도면 비록 wiki syntax에 비할바는 아니지만 쓸만할 것 같습니다. :-)