C의 foreach

2025. 01. 25.
카테고리
게시일
Jan 25, 2025
notion image
리눅스 스터디 3주차에 발표자 팀원이 재미있는 코드 부분을 가져왔다.
아래는 linux kernel에서 에서 cgroup subsystem을 초기화하는 부분이다. 사실 cgroup subsystem 이 무엇인지는 이 글에서 중요한 내용은 아니고, 컨테이너 데이터를 차례로 순회하는 코드블럭, 즉 foreach 블럭을 c에서도 매크로를 이용해 멋들어지게 만들 수 있다는 점이 이 글을 쓰는 이유이다.
from kernel 6.8.1, /kernel/cgroup/cgroup.c
struct cgroup_subsys *ss; int i; // ... bla bla for_each_subsys(ss, i) { // bla bla cgroup의 ss를 초기화 if (ss->early_init) cgroup_init_subsys(ss, true); }
위 코드는 정의된 서브시스템의 각각의 정보를 가져온다. 일종의 for each 문으로 동작하며, 존재하는 ss 포인터에 한번에 하나씩 순회하면서 가져와서 아래 코드블럭을 실행한다.
/** * for_each_subsys - iterate all enabled cgroup subsystems * @ss: the iteration cursor * @ssid: the index of @ss, CGROUP_SUBSYS_COUNT after reaching the end */ #define for_each_subsys(ss, ssid) \ for ((ssid) = 0; (ssid) < CGROUP_SUBSYS_COUNT && \ (((ss) = cgroup_subsys[ssid]) || true); (ssid)++)
실제 for_each_subsys는 매크로로 구현되어있으며, 그 실체는 for문의 머리부분이다. 실제로 iterator를 업데이트 하는 부분은 가운데 condition statement에서 일어난다.
이런식으로 만든것은 독립된 코드블럭을 만들어주기 위해 일종의 꼼수(?)를 쓴 것이다. 왜 세번째 부분(ssid++)에 넣어주지 않고 굳이 condition state에서 || true를 이용한 꼼수를 써주었냐 하면, consition state는 for문이 최초로 동작할 때 코드블럭보다 먼저 실행이 된다는 점을 이용한 것이다.
for(...) // 매크로부분, iterator를 for의 머리에서 전부 처리해주면 { // 블럭부분 // 위 for문에서 전부 처리해준 덕분에 이 부분은 마치 다른 언어의 foreach 블럭을 사용하는 것 처럼 자유로워진다. }
아래 글 참조
C는 공부하면 공부할수록 매크로의 만능성에 감탄하게 되는 것 같다.
제목: C의 foreach작성일: 2025. 01. 25.