#define 사용 시 멤버 변수를 for문 인자로으로 받을 수 없나요?
다음과 같은 코드는 정상 동작 합니다.
#if 1
#define INT_i(n) int i##n = n;
#define SUM(res, n) (res) += i##n
#define PRINT(n) printf("i%d = %d\n", n , i##n)
int main()
{
int res=0;
int i;
for(i=0; i<2; i++)
{
INT_i(i);
PRINT(i);
SUM(res,i);
}
printf("결과 : %d\n", res);
return 0;
}
#endif
**실행결과**
i0 = 0
i1 = 1
결과 : 1
다음과 같은 코드는 컴파일 에러가 납니다.
#if 1
#define INT_i(n) int i##n = n;
#define SUM(res, n) (res) += i##n
#define PRINT(n) printf("i%d = %d\n", n , i##n)
int main()
{
int res=0;
int i;
#if 1
int i0, i1,i2;
i0 = 0;
i1 = 1;
#endif
for(i=0; i<2; i++)
{
/* INT_i(i); */
PRINT(i);
SUM(res,i);
}
printf("결과 : %d\n", res);
return 0;
}
#endif
**컴파일결과**
a.c: In function 'main':
a.c:61: error: 'ii' undeclared (first use in this function)
a.c:61: error: (Each undeclared identifier is reported only once
a.c:61: error: for each function it appears in.)
첫번째 코드와 다르게 i0, i1 을 직접 선언하는 경우
#define 매크로에서 ##으로 연결하는 부분을 넘겨받는 숫자가 아니라 문자 그대로 i로
인식을 하는데요.. 변수를 선언하고 쓰는 것과 for에서 INT_i(i) 로 선언해서 쓰는 것이
왜 결과가 다를까요?
구조체 멤버를 i0, i1, i2 형태로 해서 for문을 돌려서 사용 하고 싶은데
위 예제와 똑같은 에러가 나네요.. 어떻게 사용할 방법이 없을까요?
이런 오류가 나네요.
[Error] 'ii' was not declared in this scope
ii 라고 이름이 나옵니다.
//
이런 방식인거 같습니다.
#define ##arg 이런 내용도 있네요.
http://www.google.co.kr/search?q=%23define+%23%23arg&hl=ko&biw=&bih=&gbv=2&oq=%23define+%23%23arg&gs_l=heirloom-serp.3..0j0i30l9.639.3995.0.4386.5.5.0.0.0.0.250.866.1j2j2.5.0....0...1ac.1.34.heirloom-serp..1.4.615.8YY-CdZpY5Y
----------------------------------------------------------------------------
젊음'은 모든것을 가능하게 만든다.
매일 1억명이 사용하는 프로그램을 함께 만들어보고 싶습니다.
정규 근로 시간을 지키는. 야근 없는 회사와 거래합니다.
각 분야별. 좋은 책'이나 사이트' 블로그' 링크 소개 받습니다. shintx@naver.com
매크로 함수...
C언어를 사용하실 때는, 프로그램을 컴파일하고 실행하는 과정에서 다음과 같은 4단계를 거친다는 것을 확인하고, 자신이 원하는 작업이 어느 단계에서 이루어지길 바라는지 분명히 할 필요가 있습니다.
[전처리 단계] -> [컴파일 단계] -> [링크 단계] -> [실행(런타임) 단계]
질문자님이 제시하신 첫 번째 코드는 분명히 잘 컴파일되고 (아마도) 의도하신 대로 실행되는 것처럼 보이지만 전혀 그렇지 않습니다. 매크로 확장 결과 어떻게 되는지 보여드리죠.
int main()
{
int res=0;
int i;
for(i=0; i<2; i++)
{
int ii = i;; // INT_i(i)
printf("i%d = %d\n", i , ii); // PRINT(i)
(res) += ii; // SUM(res, i)
}
printf("결과 : %d\n", res);
return 0;
}
보이십니까? for문 안에서 i=0일 때 INT_i(i)가 int i0 = 0; 이 되길 바라신 것 같은데, 틀리셨습니다.
매크로 확장은 전처리 단계에서 일어납니다. 전처리기는 for문이 뭔지도 모르고, 심지어 i가 변수인지 아닌지도 모릅니다.
전처리기가 아는 건 그냥 n 자리에 문자열 i가 들어왔다는 것 뿐이고, int i##n = n;에 고스란히 치환해서 int ii = i;으로 만들 뿐입니다.
그 아래의 다른 매크로들도 마찬가지입니다. 분명히 의도한 것과 다른데 우연히도 맞는 코드가 만들어져서 잘 도는군요. 이럴 때 참 골치 아프죠.
이 점을 상기하면 둘째 코드가 왜 컴파일이 안 되는지도 아시겠지요.
int main()
{
int res=0;
int i;
int i0, i1,i2;
i0 = 0;
i1 = 1;
for(i=0; i<2; i++)
{
printf("i%d = %d\n", i , ii); // PRINT(i)
(res) += ii; // SUM(res, i)
}
printf("결과 : %d\n", res);
return 0;
}
변수 ii는 애초에 선언되지도 않았으니 컴파일이 안 되는 게 당연하지요.
구조체 멤버를 i0, i1, i2 와 같이 만들어서 for문을 돌려서 사용하고 싶으시다고요?
for문은 실행 단계에서 동작하는 겁니다. 그러면 (전처리 단계가 아니라) 실행 단계에서 참조할 수 있게 짜야죠.
가장 편한 방법은 배열입니다. 아래와 같은 코드는 어떤가요.
#include
struct foo{
int i[2];
};
int main(void){
struct foo bar;
int i, res=0;
bar.i[0] = 0;
bar.i[1] = 1;
for(i=0;i<2;i++){
printf("bar.i[%d] = %d\n", i, bar.i[i]);
res += bar.i[i];
}
printf("결과 : %d\n", res);
return 0;
}
한편 배열의 크기는 컴파일 단계에서 정해져 있어야 하니, 그것까지 실행 단계에서 지정하려면 동적 할당을 써야 합니다.
#include
#include
struct foo{
int *i;
};
int main(void){
struct foo bar;
int i, res=0;
int n;
if(scanf("%d", &n) != 1 || n <= 0)
return EXIT_FAILURE;
bar.i = (int *)malloc(n * sizeof(int));
if(!bar.i)
return EXIT_FAILURE;
for(i=0;i bar.i[i] = i;
}
for(i=0;i printf("bar.i[%d] = %d\n", i, bar.i[i]);
res += bar.i[i];
}
printf("결과 : %d\n", res);
free(bar.i);
return 0;
}
마지막으로 덧붙이자면, 매크로 함수 쓰기 전에는 꼭 한번 더 생각하세요. 특히 ##와 같이 쓸 때는 더더욱.
음;
레이아웃이 이상하게 깨졌네요. printf문 안에 들어간 특수문자 때문인 것 같은데 읽는 데는 문제 없으리라고 생각됩니다. 그 바로 밑에 드린 코드의 printf문이랑 똑같아요.
댓글 달기