C언어 define 매크로

kkb의 이미지

for (i=0; i<3; i++)
        printf("%s \n", FRUIT(i));

위와 같이 i 값에 따라서 출력하면
apple
orange
banana

출력될 수 있도록
define 매크로를 선언하려고 하는데
어떻게 해야 할 지 모르겠습니다.
어떤 식으로 해야 될까요?

#define FRUIT_0 "apple"
#define FRUIT_1 "orange"
#define FRUIT_2 "banana"
#define FRUIT(index) FRUIT_##index
 
for (i=0; i<3; i++)
        printf("%s \n", FRUIT(i));

이렇게 하면 될 줄 알았는데 어떻게 해야 할 지 모르겠습니다.

김정균의 이미지

concatenation 는 저렇게 사용할 수는 없을 거 같은데요. 일단
https://gcc.gnu.org/onlinedocs/cpp/Concatenation.html 참조해 보시고..

원하시는 바를 하려면 다음과 같이 하면 되지 않을까 싶은데요.
뭐 macro 확장을 공부 하시는 거라면 도움이 안되실 듯.. ㅠ

char *a[3] = { "apple", "orange", "bananna" };
#define FRUIT(i) a[i]
 
int main (void) {
    int i;
    for ( i=0; i<3; i++ )
        printf ("%s\n", FRUIT(i));
    return 0;
}
kkb의 이미지

그것도 생각해봤었던 건데
제가 원했던 것은 아니지만 답변 감사드립니다.
항상 많은 도움 받고 있습니다.

cstria0106의 이미지

매크로를 런타임에 있는 i 변수로 접근할 수는 없습니다. FRUIT(i)는 그냥 전처리기에 의해서 FRUIT_i로 바뀔 뿐입니다. c언어에서 반복 가능한 매크로는 지원하지 않기때문에 아마 쉽게 하기는 어려울 것 같습니다. 아마 c++이라면 가능할 지 모르겠습니다. 아래 링크를 참고하시면 가능한 경우의 수를 다 적어주는 식으로 구현하는 방법도 있긴 합니다.

https://stackoverflow.com/questions/28231743/self-unrolling-macro-loop-in-c-c

kkb의 이미지

#define FRUIT_ADDR(i) (0x20 + (i) * 2)
 
int main (void) {
    int i;
    for ( i=0; i<3; i++ )
        printf ("%d\n", FRUIT_ADDR(i));
    return 0;
}

address 접근할 때 위와 같이 흔히 사용되니까요.

jick의 이미지

매크로가 언제 적용되나를 잘 생각해 보시면 될 것 같네요. 매크로는 실행은커녕 컴파일러의 나머지 부분이 돌기도 전에 가장 먼저 처리됩니다. 그러니까 위의 코드의 FRUIT_ADDR(i)는 이렇게 바뀌는 거죠:

printf("%d\n", (0x20 + (i) * 2))

매크로는 여기서 i가 변수인지 상수인지 런타임에 몇 번 바뀌는지 그런 거 전혀 모릅니다. 그냥 코드를 저렇게 바꿔 버리고, 그 코드가 컴파일이 되면 나중에 i가 바뀌면서 저 코드가 실행이 되는 거죠.

그러니까 다시 원 질문의 매크로를 들여다보면 안 된다는 걸 알 수 있습니다. FRUIT(i)는 코드에 존재하는 "i"라는 텍스트를 가지고 뭔가를 할 수 있을 뿐, 그 i의 값이 나중에 뭐가 되는지는 매크로가 알 수가 없습니다. i라는 변수가 존재해서 그 변수에 값을 대입하고 자시고 할 때에는 이미 매크로는 다 사라진 이후니까요.

kkb의 이미지

이렇게 설명하시니 확실히 이해가 되네요.
단순한 걸 헷갈려했네요.
그나마 배열로 처리하는 것이 가장 낫겠네요.
답변 주신 분들 모두 감사드립니다.

MySprtlty의 이미지

전처리기 입장에서는 i가 변수 명칭(Identifier)인지 조차도 모릅니다. 그냥 i는 명칭(Preprocessing Token 中 1)으로밖에 안보입니다. 변수인지 아닌지는 Parsing(컴파일)과정 쯤 되어서야 알 수 있습니다.

댓글 달기

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