C에서는 auto나 decltype 같은 예약어가 도입될 가능성이 없을까요?

twinwings의 이미지

혹시나 해서 gcc -std=c11 옵션 주고 해봤는데 역시나 안되네요.

간단한 매크로 작성(swap 같은) 할 때 편할 것 같은데...

익명 사용자의 이미지

1. C언어 표준과 C++언어 표준은 별개입니다.
C++11이 있다고 C11이 있는 건 아니죠. 각 표준이 언제 개정되었는지는 구글링해보면 금방 나옵니다.
두 표준은 실용적인 목적에서 서로를 제법 닮아 있었고, 덕분에 한동안 C++언어가 C언어의 superset 비스무리한 것처럼 여겨도 대충 맞는 말처럼 들렸지요.
뭐, C++03때도 이미 C++엔 C에 없는 기능이 제법 많았는데(클래스는 말할 필요도 없고, 오버로딩, 레퍼런스, 템플릿 등등...) C++11에 다소 파격적으로 더 많이 추가됐다 한들 (auto, rvalue reference 등) 놀랄 게 있을까요.

2. 그래서, C언어에 auto나 decltype이 필요할까요?
주관적인 의견만 드릴 수 있겠네요.
둘 다 소위 type inference라 불리는 기능들인데, 사실 저 두 기능이 제대로 빛을 보려면 템플릿처럼 "알려지지 않은 타입 T를 받아서 이리저리 조작하는" 메커니즘이 필요하지 않은가요.
알려진 타입(예컨대 int)에 알려진 동작(예컨대 +)을 취하면 auto나 decltype같은 거 없이도 결과 타입은 어차피 뻔한데요.(이 예에서는 int)
이러한 "일반화 프로그래밍"이 가능하려면 또 뒷받침해야 하는 것들이 있죠. 일반적인 함수 오버로딩은 물론이고, 구조체 같은 자료형을 마치 int처럼 쓸 수 있게 해주는 연산자 오버로딩, assign operator에서처럼 lvalue를 반환한다는 걸 명시적으로 나타내기 위한 레퍼런스 타입 등..

이렇게 보니 점점 "클래스 상속 없는 C++"에 비슷해져가고 있는 것 같지 않습니까. 그에 따라 언어적으로, 또 그 컴파일러 등 구현환경도 복잡해져 갈 것이고요.

괜히 쓸데없이 비약시킨다고 생각하신다면 반박하셔도 좋습니다. 하지만 저는 이렇게까지 C언어가 C++를 쫓아갈 필요는 없다고 생각해요. 지금 C언어가 활용되는 영역은 분명히 따로 있고, 그 안에서 더 유용하게 쓰일 수 있는 기능에 집중하는 게 더 맞다고 봅니다.

익명 사용자의 이미지

C11은 실제로 있군요. "C++11이 있다고 C11이 있는 건 아니죠" 라고 드린 말씀은, "C++11에 대응되는 버전으로서 자연스럽게 C11도 뒤따르는 건 아니다"라는 의미로 드린 말씀이니 오해 없으시길 바랍니다.
두 표준이 같은 해(2011년)에 개정되었을 뿐 C++11과 C11은 별개이고, C++11에 추가된 기능이 C11에도 있을 거라는 기대 역시 불가능합니다.

HDNua의 이미지

재밌게 읽었습니다.

저는 이렇게 생각했습니다.

kukyakya의 이미지

전반전인 내용에 대해선 전적으로 동의합니다.

다만 C11에도 _Generic(http://en.cppreference.com/w/c/language/generic)이나 이에 기반한 tgmath(http://en.cppreference.com/w/c/numeric/tgmath)같이 다소 원시적이나마 generic programming에 대한 시도가 추가되는 것을 보면 꼭 C라고 해서 일반화 프로그래밍에 관한 키워드가 필요 없다고 얘기하긴 힘들 것 같습니다.

익명 사용자의 이미지

앞서 제가 쓴 바와 같이, 템플릿처럼 광범위한 규모의 generic programming의 도입까지는 솔직히 조금 과하다고 생각합니다만,
저도 최소한 파라미터 타입에 따른 function overloading이나 default arguments 같은 건 지원했으면 좋겠다고 생각합니다.
(후자는 뭐 일반화 프로그래밍하고는 다소 무관하긴 한데, C++ 오래 쓰다가 간혹 C 쓰게 되면 없다는 걸 자꾸 까먹게 되네요. -_-;;)

전자의 부재는 powf니 powl이니 하는 다소 nontrivial한 라이브러리 함수 이름을 양산해 냈었던 원흉이지요.
사실 근본적인 원인은 애초에 C++와 달리 C언어는 함수 이름을 파라미터 타입과 같이 인코딩(name mangling)하지 않고 그냥 그 이름 그대로 쓰기 때문에,
같은 이름에 파라미터 타입만 다른 함수들이 외부에 노출될 수가 없다는 역사적인 문제가 있기는 합니다.
그래도 기왕 C언어에 타입 시스템이 있는 김에 일종에 타입 기반 switch문 같은 걸 만들면 코드가 덜 지저분해지겠죠. 컴파일 타임에 처리되니까 런타임 부담이 있는 것도 아니고.
C11에서 추가된 _Generic이 그런 의미에서 꽤 좋은 키워드라고 생각합니다. 근데 널리 알려지고 쓰이는 데 얼마나 시간이 걸릴까요...

twinwings의 이미지

네 저도 C가 C++을 따라가야 한다고 생각하지 않습니다.

C++ 예찬하다가 C++ 특유의 비직관성때문에

(Call by value일지 Call by refer일지, rvalue로 넘어갈지 lvalue로 넘어갈지, 기타 등등..)

최근엔 C만 쓰고 있죠.

그리고 "알려지지 않은 타입 T를 받아서 이리저리 조작하는" 메커니즘은

C에서 매크로라는 이름으로 기능하지 않나요? 대표적으로

#define SWAP(x, y, T) do { T SWAP = x; x = y; y = SWAP; } while (0)

이런 코드가 있죠.. 이런 것들을 위해서 decltype과 같은 예약어가

도움이 되지 않을까 해서 적어 본 글이었습니다.

익명 사용자의 이미지

C++가 직관적이냐 비직관적이냐...는 조금 주관적인 여지가 있겠죠.
그보다는 C++의 철학이 "프로그래머가 모든 걸 잘 알고 알아서 할 테니 프로그래머를 믿는다"라는 점에는 이견의 여지가 좀 더 적을 것 같네요.

아무튼 저는 개인적으로 C언어와 C++언어 둘 다 좋아합니다.
다만 딱히 예찬해야 한다는 생각까진 안 들고요, 여러 언어들의 특징과 철학을 잘 파악하고 적합한 용도에 써먹는 것이 가장 효율적이라고 생각합니다.

본론으로 들어가서..

1. 네. C언어엔 전처리 매크로가 있죠.
사실 이 매크로라는 물건이 C언어 신택스와 단순 텍스트 치환 매크로 사이의 어딘가에 있는 물건인데요.
그러다보니 가끔은 위험스러울 정도로 강력한 기능을 자랑하는가 하면, 가끔은 또 꼭 필요한 기능을 지원을 안 해서 불편을 겪습니다. -_-;;;

C언어 고수들은 매크로를 가지고 정말 무지막지한 짓들을 하던데(저는 매크로를 떡칠해가며 C언어로 OOP 개발 해놓은 프로젝트 코드도 봤습니다.) 보면 정말 기가 막힙니다.

2. 아무튼 그래서 매크로 테크닉으로 타입에 대한 일반화 프로그래밍이 가능하나고요? 흐음;

조금 위험할 수는 있어도 어느 정도는 가능할 것 같긴 해요.

C언어로 이루어진 프로젝트 여럿 보신 분이라면, 임의 타입에 적용하여 연결 리스트를 만들어주는, 흡사 STL list를 연상케 하는 일련의 유틸리티 매크로들을 보셨을 겁니다.
개인적으로 처음 봤을 때 참 기가 막혔는데요. 이런 건 STL로만 되는 줄 알았거든요.
다만 인터페이스 측면에서는, 후술할 어떤 문제 때문에 조금 위험한 문제가 하나 있었습니다.

제시하신 코드 역시 괜찮은 코드 스니펫입니다.
어쩌다가 사용자가 x 혹은 y로 SWAP이라는 identifier를 넘겨 주지만 않는다면요. 이러면 컴파일러 경고 같은 것도 있을 리 없고 말짱 꽝이겠죠.

프로그래머가 좀 더 신중할수록 위험성을 줄일 수 있긴 합니다만 (예컨대 저라면 내부 변수를 SWAP_internal_ ## x ## y 같은 걸로 했을 겁니다. 이러면 x와 y 중 어느 것과도 안 겹치겠죠.) 하려는 일이 복잡해질수록 잘못되기 쉬울 게 명백해 보입니다.

auto나 decltype만 있으면 이런 상황이 좀 더 나아질까요? 뭐 예컨대 이런 걸 기대하시는 거겠죠?

#include <iostream>
using namespace std;
 
#define SWAP(x, y) do { decltype(x) SWAP = x; x = y; y = SWAP; } while (0)
 
int main(void){
        int v1 = 2, v2 = 3;
        SWAP(v1, v2);
        cout << v1 << ", " << v2 << endl;
        SWAP((v1), v2);
        cout << v1 << ", " << v2 << endl;
        return 0;
}

가벼운 장난입니다. :) 한번 돌려보세요. 이 예제 때문에 C++에서 더 멀어지시게 되는 건 아닌지 모르겠네요. 그러지는 말아주세요(?)
decltype(x) 대신 auto를 쓰면 뭐 잘 돌겠죠. 물론 C++이면 매크로 함수를 쓰느니 애초에 인라인 템플릿 함수를 쓰는 게 당연히 훨씬 낫습니다.

그런데 매크로를 동원해도 구현이 어려운 것들도 있습니다. 아래 글 기억하시죠?

https://kldp.org/node/154748

#define SWAP(T,E) (T ## _swap(E))라니, 구차하지 않습니까?
C++에서 템플릿을 썼다면 SWAP<T>라고 썼을 텐데, 언어 차원에서 이런 게 지원이 안 되니 무식하게 토큰을 그냥 붙여서 함수 이름으로 쓰고 말았죠.
게다가 T가 두 개 이상의 토큰이면 안 된다는, 사용자 입장에서 굉장히 비직관적인 제약 조건은 덤입니다.
T1과 T2가 typedef에 의한 같은 타입일 때조차 SWAP(T1, 0)와 SWAP(T2, 0)이 다른 함수를 호출한다는 게 두 번째 덤이고요.

이런 종류의 문제 어떻게 해결이 안 될까요? 일단 제가 아는 선에서는 방법이 없어 보이는데요.
앞서 설명한 연결 리스트의 예에서도 이 문제가 불거지는데, 리스트 라이브러리는 데이터 자체를 건드리지는 않으니 그냥 char * 따위로 다룰 수 있다고 쳐도
리스트에 어떤 타입의 데이터가 담겨 있는지를 매크로만 가지곤 어디다 기록해둘 수가 없어서 매번 사용자에게 물어봐야 합니다.
그리고 사용자가 알려준 그대로 강제 캐스팅을 해버리기 때문에 한 번만 실수해도 아무 경고도 없이 바로 망가집니다. -_-;;

3. 이런 이유 때문에 사실 저는 C언어가 일반화 프로그래밍을 지원하냐는 질문에 조금 난색을 표합니다.
그리고 본격적으로 일반화 프로그래밍을 해야 하는 상황이라면 웬만하면 C++ 혹은 다른 언어를 선택하죠.

auto나 decltype이 있으면 타이핑을 줄일 수 있을 때가 있기는 할 거에요. 그것만으로도 유용하다고 주장할 수 있을지도 모르겠습니다.
하지만 지금으로썬 함수 오버로딩조차 지원을 안 하는 C언어에 auto나 decltype만 있다고 얼마나 활용할 수 있을까요.
또 auto나 decltype가 활용될 여지를 주기 위해 C언어에 다른 기능을 추가한다면, C언어는 그만큼 더 복잡해지지 않을까요.

단언하지는 않겠습니다. 아무래도 제가 익명 가지고 너무 어그로를 끌고 있는 것 같아서 말이죠. 어쨌건 생각해 볼 문제인 것 같기는 합니다.
혹시 모르죠. 언젠간 정말 추가가 될지도. C++ 표준이 요즘 크게 약진하면서 C언어와 차이를 많이 벌렸지만, 다시 좁혀질 수도 있는 거 아니겠습니까?

익명 사용자의 이미지

내부 변수를 SWAP_internal_ ## x ## y 따위로 지어버리면 x나 y가 identifier가 아니라 다른 lvalue expression (예컨대 포인터 p, q에 대해서 SWAP(*p, *q))일 때 문제가 생기는군요. 아오.
저 언급은 취소하겠습니다. 잊어주세요. 괜히 으스대다가 제 꾀에 제가 넘어갔네요.

혹시 더 좋은 생각 있으신 분? -_-;;;

댓글 달기

Filtered HTML

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

BBCode

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param>
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

Textile

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • You can use Textile markup to format text.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Markdown

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • Quick Tips:
    • Two or more spaces at a line's end = Line break
    • Double returns = Paragraph
    • *Single asterisks* or _single underscores_ = Emphasis
    • **Double** or __double__ = Strong
    • This is [a link](http://the.link.example.com "The optional title text")
    For complete details on the Markdown syntax, see the Markdown documentation and Markdown Extra documentation for tables, footnotes, and more.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Plain text

  • HTML 태그를 사용할 수 없습니다.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 줄과 단락은 자동으로 분리됩니다.
댓글 첨부 파일
이 댓글에 이미지나 파일을 업로드 합니다.
파일 크기는 8 MB보다 작아야 합니다.
허용할 파일 형식: txt pdf doc xls gif jpg jpeg mp3 png rar zip.
CAPTCHA
이것은 자동으로 스팸을 올리는 것을 막기 위해서 제공됩니다.