신기한 상태 메시지 만들기

상태메시지

double ans[]={.33066404772027283E3,1<<0xA};main(){--1[ans]?*ans/=2,main():puts(ans);}

실행결과

☀🪄

C로 컴파일해서 실행하면 솔라매직을 상징하는 해(solar)와 마법봉(magic)을 출력한다.

온라인 IDE 결과

계기

double k[]={12.596070810382761,495};main(){k[1]--?k[0]/=2,main():puts(k);}

Steam 친구 자기소개에 이런게 있는 것을 발견했다. 실행해보니 결과는 kcy1019! 신기해서 어떻게 만드는지를 물어봤다.

만들기

#include <cstdio>
#include <cassert>
#include <cstring>

int main(int argc, char *argv[]) {
    assert(argc > 1);
    int n = strlen(argv[1]);
    assert(n < 9);

    char buf[8] = {};
    memcpy(buf, argv[1], n);

    double v = *(double*)buf;
    int shl = 0;
    for (; v < 10; v *= 2) ++shl;
    printf("double k[]={ %.15f,%d};main(){k[1]--?k[0]/=2,main():puts(k);}", v, shl);
    return 0;
}

친절하게 만드는 코드까지 제공해주셨다.

기본적인 원리는 간단하다. 8바이트 ASCII문자를 하나의 double(8바이트)로 담은다음에 변형하고 다시 출력하는 것이다. long long같은 8바이트 정수로 하면 좀 더 직관적이다.

변형

하지만 내 이름은 10글자(solarmagic) 이기 때문에 그대로 쓰기에는 조금 무리였다. 16바이트 자료형인 long double이나 __int128 같은 걸 사용하면 될 수도 있지만 그냥 그대로 써먹기로 했다. 대신 ASCII문자가 아니라 유니코드 문자를 이용해서 출력하면 좀 더 비직관적인 결과가 나오지 않을까 생각해서 솔라매직을 이모지로 출력하기로 마음 먹었다.

☀🪄 가 가장 적절한 이모지로 보였다. ☀ 이모지는 환경에 따라서 좀 많이 다르게 보이는게 조금 아쉬웠지만 그래도 가장 적절한 이모지라 생각했다.

원본 코드는 적절히 한 10.x 되는 수로 만들어 주는데 나는 뭔가 1024($2^{10}$)번 반복하는게 컴공 답다고 생각해서 코드를 조금 변형 시켰다.

double ans[]={.33066404772027283E3,1<<0xA};main(){--1[ans]?*ans/=2,main():puts(ans);}

배열이름은 ans로 바꾸었고(PS 사이트에 올릴것이기 때문에 적절한 이름이다.) 배열 원소를 직접 지정할때 [] 안에 수를 안써도 되는 것은 모두 알 것이다.

그밖에 코드를 보면 실수를 그냥 330.xxx 담는 것보다는 .330...E3 형태로 표기하면 난독화가 조금더 올라갈거라 생각했다. 참고로 0.x 의 수에서 0을 생략하는건 C/C++에서 가능하다.

$1024$도 $1024$라고 쓰는것보다 1<<10이라 쓰는게 좋아보였고 한 술 더떠서 1<<0xA로 $10$을 $16$진수로 표기했다.

코드의 기본 동작은 main 함수의 재귀이다. 사람들이 잘 모르는 사실이지만 main도 재귀가 가능하다. 그래서 mainans[1] 만큼 반복하면서 절반으로 나누고 그값을 출력하면 원본 글자가 나온다. 재귀의 판정은 삼항연산자를 사용했다.

난독화를 조금도 하기 위해서 --ans[1]--1[ans]로 썼다. (C 수업을 되새겨보면 이게 왜 가능한지 생각날 것이다.) 또한 ans[0] 은 자연스럽게 *ans 바꿔써도 상관이 없다.

마무리

나의 상태메시지를 설명하는 글이었다. 프로그래머라면 위 코드 및 다른 코드들을 활용해서 나만의 코드 상태메시지를 하나씩 가져보면 좋을 것 같다.