[완료] #define 문장에서의 ##용법

zipsinworm의 이미지

Windows소스를 분석하다가 #define문의 ##용법에 대해 궁금증이 생겼습니다.
예를들어,

#define CAT(a,b) a##b

int main(void)
{
int arr={100,200};
printf("%d",CAT(arr,[1]);
return 0;
}

라는 소스가 있다고 하면 출력 결과는 200이 나와야 한다고 생각합니다.

그런데 Linux(SUSE)에서 저 소스를 컴파일 하니 CAT(arr,[1]) 이 문장에서 [ <- 이것을 파싱하지 못한다고
에러가 나왔습니다.

게다가, 다른 소스
printf("%s",CAT("HAHA","haha")라는 문장도 출력 결과가 HAHAhaha가 나와야 하는데 컴파일시 에러가 발생합니다.

그 외에 함수나 변수등을 테스트 해보니 컴파일시 에러도 안나고 출력결과도 정확히 나옵니다. 문자열과 배열만
컴파일시 에러가 발생합니다.

컴파일시 에러가 안나오게 하는 방법은 없을까요?

cwryu의 이미지

##는 여러 개를 이어서 하나의 토큰을 만들어낼 때 사용합니다.

위의 경우 arr[1]에서 arr, [, 1, ] 모두 별도의 토큰이므로 ##로 붙이는 게 아닙니다. 스트링 두 개도 이은다고 하나의 토큰이 되지는 않구요.

----
익명이나 오래전 글에 리플은 무조건 -1

zipsinworm의 이미지

Windows VC++에서 위 소스를 C 컴파일을 사용해 컴파일하면 잘 돌아갑니다.

물론 printf("%s",CAT("HAHA","haha")); 도 잘 돌아가고요.

그런데 Linux에서 컴파일 하면 에러가 납니다.

arr[1]가 모두 별도의 토큰이라는 말씀은 이해가 가는데 ##로 붙이는게 아니라면 어떻게 붙이는지, 그리고

스트링 두개도 잇는다고 하나의 토큰이 되지 않는다면 어떻게 하나의 토큰으로 만들어 붙이는지 궁금합니다.

전웅의 이미지

> Windows VC++에서 위 소스를 C 컴파일을 사용해 컴파일하면 잘 돌아갑니다.
>
> 물론 printf("%s",CAT("HAHA","haha")); 도 잘 돌아가고요.
>

## 로 생성되는 토큰이 유효한 토큰이 아닐 경우 행동이 정의되지 않기
때문에 맘대로 행동할 수 있습니다. MSVC 의 경우 유효하지 않은 토큰을
억지로 단일 토큰으로 만들어 오류로 인식하기 보다는 임의로 분리된
토큰으로 인식하기를 선택한 것입니다.

>
> 그런데 Linux에서 컴파일 하면 에러가 납니다.
>
> arr[1]가 모두 별도의 토큰이라는 말씀은 이해가 가는데 ##로 붙이는게 아니라면 어떻게 붙이는지, 그리고
>

토큰에 대해 뭔가 오해를 하고 계신 것 같습니다. 전처리 과정에서
토큰에는 다음과 같은 6가지 종류가 있습니다. (실제론 7가지이지만, 설명
에 오해만 불러일으킬 수 있는 한 가지는 일부러 뺍니다.)

- 명칭(identifier)
- pp-number
- 문자열 상수(string literal)
- 문자 상수(character constant)
- 구두점(punctuator)
- 헤더명(header name)

arr[1] 은 명칭(arr), 구두점([), pp-number(1), 구두점(]) 의 4개의 토큰
으로 구성되어 있습니다. 즉, 토큰 별로 구분해 쓰면 "arr" "[" "1" "]" 이
됩니다. arr 과 [ 사이에 ## 를 넣어 토큰 연결을 시도 한다는 것은 "arr["
라는 하나의 토큰을 만드려는 것에 해당합니다. "arr[" 는 과연 위에서
언급한 부류 중 어디에 속할 수 있을까요? 없습니다. 따라서 유효하지 않은
토큰이 되고 그 이후 컴파일러는 자기 나름대로의 판단에 따라 행동할 수
있게 됩니다 (gcc 는 오류로 처리하길 선택한 것이며, MSVF 는 "arr[" 를
다시 "arr" "[" 로 찢어 2개 올바른 토큰으로 인식해 처리한 것입니다).

> 스트링 두개도 잇는다고 하나의 토큰이 되지 않는다면 어떻게 하나의 토큰으로 만들어 붙이는지 궁금합니다.
>

"abc" ## "def" 의 경우에도 동일한 이야기가 적용됩니다. (이번에는
하나의 토큰을 구분하기 위해 [] 를 사용합니다.) ["abc"]["def"] 는
유효한 2개의 string literal 이지만, ["abc""def"] 는 유효하지 않은
토큰이 됩니다.

문자열 상수의 내용을 합해 하나의 문자열로 만들고자 한다면 이미 다른
분이 적어주신 방법을 사용하시면 됩니다. 단, 그와 같은 방식의 문자열
연결은 전처리 과정 이후에 이루어지는 것이기 때문에 "전처리기에서는"
문자열 연결의 효과를 볼 수 없습니다.

그럼...

--
Jun, Woong (woong at icu.ac.kr)
Web: http://www.woong.org (서버 공사중)

--
Jun, Woong (woong at gmail.com)
http://www.woong.org

cppig1995의 이미지

"HAHA" "haha"는 그냥 "HAHA" "haha"라고만 써도 잘 됩니다.
따라서 이런 용도에는 #define CAT(a, b) a b 쓰면 됩니다.
arr[1]도 마찬가지로 알고 있습니다. 전처리기가 arr [1]로 바꿔주니까요.

##는 이럴때 쓰는거겠죠.

#define paste(a, b) a ## b
int a = 20, b = 40, ab = 10;
printf("%d\n", paste(a, b));

결과: 10

ANSI 이전의 컴파일러를 위한 트릭으로는 a/**/b가 있는데
ANSI 표준에 의해 /**/는 빈칸 하나로 치환되어 a b(ab가 아닌)가 되므로
ANSI 이전의 컴파일러에만 쓸수 있다고 알고있습니다.
(즉, 호환성을 위한 방법이 아님.)



절망으로 코딩하고 희망으로 디버깅하자.

Real programmers /* don't */ comment their code.
If it was hard to write, it should be /* hard to */ read.

cppig1995의 이미지

실수로 두개 올렸습니다.



절망으로 코딩하고 희망으로 디버깅하자.

Real programmers /* don't */ comment their code.
If it was hard to write, it should be /* hard to */ read.

zipsinworm의 이미지

전웅님께서 말씀하신것이 확실히 이해가 된다음 cppig1995님께서 예를 들어주신것이 쐐기를 박았네요.

전처리 과정에서의 토큰해석에 관해서 모르고 있었는데 중요한 점을 찍어주셔서

감사합니다!!

댓글 달기

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
이것은 자동으로 스팸을 올리는 것을 막기 위해서 제공됩니다.