유튜브 알고리즘에 낚여서 또 CppCon 영상을 봤다..
https://www.youtube.com/watch?v=1hwRxW99lg0
분명 첫 코드까지만 해도 아무생각이 없었다
auto main() -> int {
return 0;
}
// Result: 0
근데 바로 뒤에 이게 등장했다
auto main() -> int {
return -(-![]{});
}
// Result: 0
네?..선생님?..어째서 저게 0인거죠?
그리고 바로 다음 장면에서는 저걸로 1을 만든다
auto main() -> int {
return (-(-![]{}))-(-!(![]{}));
}
// Result 1
도저히 모르겠어서 요즘 핫하다는 Chat-GPT한테 물어봤다
initializer list 어쩌구하면서 헛소리를 정성스럽게 한다
아니 저거 lambda expression이잖아..
valid하지 않은 문법이란다
아니 방금 돌려보고 왔는데 무슨 말도 안되는
그 다음엔 무슨 Undefined Behavior라고 한다
이 새끼 컴파일러 탓도하네..
Chat-GPT에게서 원하는 대답을 얻을 수 없다는걸 깨닫고 구글링을 해보았다
근데 안나온다..
그래서 그냥 무지성으로 Debugging하면서 해석해보았다
auto main() -> int {
auto lambda = []{};
}
위에 적힌 저 Expression이 Lambda인 것은 자명한 사실이다
그런데 저기에 not operator!
을 붙인다면?
auto main() -> int {
int some_integer = ![]{};
}
갑자기 정수형이 된다
그리고 심지어 저 값은 0이다
auto main() -> int {
int zero = ![]{};
return zero;
}
// Result: 0
그때 무심코 한가지 개념이 머리속을 스쳐지나갔다
Lambda는 Capture가 없을 경우, funtion pointer로 변환이 가능합니다
어디에 나와있는지 찾기 귀찮음
Pointer에 not operator!
을 취하면 0(NULL)이 된다
auto foo() -> void {}
auto main() -> int {
void (*ptr)() = foo;
int zero_from_ptr = !ptr;
return zero_from_ptr;
}
// Result: 0
이제 모든게 이해가 된다
덕지덕지 붙어있는 Symbol을 걷어내고 나면 결국 나오는건 Pointer다
이제 아래와 같은 단계를 거치면 모든 정수를 얻을 수 있다
!
을 취해 0으로 만든다!
을 취해 1로 만든다이해를 했다면 이제 검증을 해보자
cpp 개발자의 필수 교양 godbolt.org에 아래 코드를 넣고 결과를 뽑아봤다
GCC 13.1 --std=c++2b -O0 -march=skylake
auto main() -> int {
int zero_from_lambda = ![]{};
}
main:
push rbp
mov rbp, rsp
mov DWORD PTR [rbp-4], 0
mov eax, 0
pop rbp
ret
Optimization이 없는데도 바로 0으로 만들어버린다
이제 function pointer
에서도 동일한 결과가 나오는지 확인해보자
GCC 13.1 --std=c++2b -O0 -march=skylake
auto foo() -> void {}
auto main() -> int {
int zero_from_func_ptr = !(&foo);
}
foo():
push rbp
mov rbp, rsp
nop
pop rbp
ret
main:
push rbp
mov rbp, rsp
mov DWORD PTR [rbp-4], 0
mov eax, 0
pop rbp
ret
완벽하게 동일한 결과가 나온다
우리가 적은 code는 mov DWORD PTR [rbp-4], 0
부분이다
즉, lambda가 function pointer
와 같이 바뀌었음을 확인할 수 있다
단순한 개념인데 이걸 놓쳐서 1시간 삽질을 했다
화나서 Chat-GPT한테 욕하다가 답변을 다시보니 정답과 비슷한 답변이 있었다
무려 5번의 질문 끝에 정답에 가까운 소리를 하기 시작했다..
behavior에서 아래 2개는 그냥 개소리고 2번째도 엄밀히 말하면 틀린말이다
!
를 붙여서 function pointer
처럼 동작하는게 아니다..
그리고 그 뒤에 왜 이상한걸 갖다 붙이니..
이 새낀 Initializer List를 좋아하는게 분명하다