상태메시지
double ans[]={.33066404772027283E3,1<<0xA};main(){--1[ans]?*ans/=2,main():puts(ans);}
실행결과
☀🪄
C로 컴파일해서 실행하면 솔라매직을 상징하는 해(solar)와 마법봉(magic)을 출력한다.
계기
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
도 재귀가 가능하다. 그래서 main
을 ans[1]
만큼 반복하면서 절반으로 나누고 그값을 출력하면 원본 글자가 나온다. 재귀의 판정은 삼항연산자를 사용했다.
난독화를 조금도 하기 위해서 --ans[1]
을 --1[ans]
로 썼다. (C 수업을 되새겨보면 이게 왜 가능한지 생각날 것이다.) 또한 ans[0]
은 자연스럽게 *ans
바꿔써도 상관이 없다.
마무리
나의 상태메시지를 설명하는 글이었다. 프로그래머라면 위 코드 및 다른 코드들을 활용해서 나만의 코드 상태메시지를 하나씩 가져보면 좋을 것 같다.