I have been programming in C for many years, but I have just started using GCC/Eclipse for a new project to develop a product using an embedded ARM processor. I have found a problem that hasn't existed in previous C compilers I have used:

I have created a define as follows:

#define SWS pRCC->CFGR, B2+B3, 2
#define ReadPeriph(Address, Bits, Shift) ((Address & (Bits)) >> Shift)

If in my code I insert two lines:

x8 = ReadPeriph(sRCC->CFGR, B2+B3, 2);
y8 = ReadPeriph(SWS);

I would expect both lines to compile correctly and give the same result. However, although the first line is OK, the compiler generates an errors on the second saying "Multiple markers at this line - 'ReadPeriph' undeclared (first use in this function)

Sorry, my previous post was incomplete. The full text follows:

I have been programming in C for many years, but I have just started using GCC/Eclipse for a new project to develop a new product using an embedded ARM processor. I have found a problem that hasn't existed in previous C compilers I have used:

I have created a define as follows:

#define SWS pRCC->CFGR, B2+B3, 2
#define ReadPeriph(Address, Bits, Shift) ((Address & (Bits)) >> Shift)

If in my code I insert two lines:

x8 = ReadPeriph(sRCC->CFGR, B2+B3, 2);
y8 = ReadPeriph(SWS);

I would expect both lines to compile correctly and give the same result. However, although the first line is OK, the compiler generates an errors on the second saying "Multiple markers at this line - 'ReadPeriph' undeclared (first use in this function)
- macro "ReadPeriph" requires 3 arguments, but only 1 given"

It would appear, therefore, that the macro SWS has not been expanded before invoking the macro ReadPeriph().

I don't believe there is anything wrong with the logic, as this code would compile correctly with another compiler, so I believe it to be a function of GCC.

Can anyone explain the problem?

Regards
Alan Rouse

GCC is correct, your other compiler is not.

>Can anyone explain the problem?
The order of operations for function-like macro parameters (as per section 6.10.3.1 of the C standard) is to identify the parameters, then replace any macro parameters, then substitute the parameters with actual arguments. The order you expected is replace, identify, substitute.

I have been programming in C for many years, but I have just started using GCC/Eclipse for a new project to develop a product using an embedded ARM processor. I have found a problem that hasn't existed in previous C compilers I have used:

I have created a define as follows:

#define SWS pRCC->CFGR, B2+B3, 2
#define ReadPeriph(Address, Bits, Shift) ((Address & (Bits)) >> Shift)

If in my code I insert two lines:

x8 = ReadPeriph(sRCC->CFGR, B2+B3, 2);
y8 = ReadPeriph(SWS);

I would expect both lines to compile correctly and give the same result. However, although the first line is OK, the compiler generates an errors on the second saying "Multiple markers at this line - 'ReadPeriph' undeclared (first use in this function)

Hi there,

You have defined the macro incorrectly. The second part should not have any spaces.

Wrong macro definition

#define	SWS		pRCC->CFGR, B2+B3, 2

Correct macro definition

#define	SWS		(pRCC->CFGR,B2+B3,2)

Try this and let me know if it works...
And one more thing, GCC is always correct... :)

GCC is correct, your other compiler is not.

>Can anyone explain the problem?
The order of operations for function-like macro parameters (as per section 6.10.3.1 of the C standard) is to identify the parameters, then replace any macro parameters, then substitute the parameters with actual arguments. The order you expected is replace, identify, substitute.

Can you tell me where I can find the C standard to which you are referring? I have always used "C The Complete Reference" by Hubert Schildt, which gives examples similar to the code I am using. I have found a standard at http://www.coding-guidelines.com/cbook/cbook1_1.pdf which has 1615 pages! Section 6.10.3 refers to macros, but I can't find a section 6.10.3.1.

Incidentally, to extract more of my code:

#define pRCC ((tRCC*) RCC_BASE)
#define SWSpRCC->CFGR, B2+B3, 2
#define ReadPeriph(Address, Bits, Shift) ((Address & (Bits)) >> Shift)

Sorry, I cocked up and only posted part of my message again!

GCC is correct, your other compiler is not.

>Can anyone explain the problem?
The order of operations for function-like macro parameters (as per section 6.10.3.1 of the C standard) is to identify the parameters, then replace any macro parameters, then substitute the parameters with actual arguments. The order you expected is replace, identify, substitute.

Can you tell me where I can find the C standard to which you are referring? I have always used "C The Complete Reference" by Hubert Schildt, which gives examples similar to the code I am using. I have found a standard at http://www.coding-guidelines.com/cbook/cbook1_1.pdf which has 1615 pages! Section 6.10.3 refers to macros, but I can't find a section 6.10.3.1.


To extract more from my code:

#define RCC_BASE 0x40021000
#define pRCC ((tRCC*) RCC_BASE)
#define SWS pRCC->CFGR, B2+B3, 2
#define ReadPeriph(Address, Bits, Shift) ((Address & (Bits)) >> Shift)

x8 = (u8)ReadPeriph(pRCC->CFGR, B2+B3, 2);
y8 = (u8)ReadPeriph(SWS);

So you will see that the macro SWS includes nested macros from other defines.

If I instead expand ReadPeriph into a function:

u32 ReadPeriph(u32* Address, u32 Mask, u8 Shift){
return ((*Address & (Mask)) >> Shift);
}

Then both x8 and y8 appear to evaluate correctly. This proves that SWS translates as 3 parameters when passed to a function, yet only appears as one function when passed to a macro.

Regards
Alan

>Can you tell me where I can find the C standard to which you are referring?
http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1124.pdf. This is only a draft, but it's close enough unless you're trying to write a C compiler.

>I have always used "C The Complete Reference" by Hubert Schildt
Herbert Schildt is notoriously clueless when it comes to C.

>So you will see that the macro SWS includes nested macros from other defines.
Which has precisely nothing to do with your problem.

>This proves that SWS translates as 3 parameters when passed to a
>function, yet only appears as one function when passed to a macro.
I don't know what you're trying to prove. The preprocessor has finished running long before functions are processed.

>Can you tell me where I can find the C standard to which you are referring?
http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1124.pdf. This is only a draft, but it's close enough unless you're trying to write a C compiler.

>I have always used "C The Complete Reference" by Hubert Schildt
Herbert Schildt is notoriously clueless when it comes to C.

You are certainly living up to your self-proclaimed reputation "I'm a programmer. My attitude starts with arrogance, holds steady at condescension, and ends with hostility. Get used to it. ". I would be reluctant to call someone who has written an 800 page reference book 'clueless'!

>So you will see that the macro SWS includes nested macros from other defines.
Which has precisely nothing to do with your problem.

I'm sorry if you couldn't understand my reasoning. Other macros replace any keywords within them with their macro expansions before interpreting the new meaning, so why doesn't the ReadPeriph macro do the same?

>This proves that SWS translates as 3 parameters when passed to a
>function, yet only appears as one function when passed to a macro.
I don't know what you're trying to prove. The preprocessor has finished running long before functions are processed.

I thought this reasoning would be equally obvious. The compiler gives an error 'macro "ReadPeriph" requires 3 arguments, but only 1 given', which clearly confirms that it has interpretted SWS as a single variable instead of expanding its macro definition of representing three parameters. The function ReadPeriph needs three parameters, and the compiler doesn't generate any errors, so it obviously interprets SWS and its expanded definition of three parameters

>I would be reluctant to call someone who has written an 800 page reference book 'clueless'!
You might, but I know enough about C to know that the majority of Herbie's books are flat out wrong. He's a good writer to be sure, but a good writer or a good teacher does not equate to a good programmer. My opinion isn't isolated either. When the hacker (that's expert programmers, not people who break into computers) community coins a disparaging slang word in your honor, it's fair to say that you've become infamous.

>I'm sorry if you couldn't understand my reasoning.
I understand your reasoning, but in reality it doesn't apply to the problem you're having.

>so why doesn't the ReadPeriph macro do the same?
Because it does something different. While you may not agree, there's a significant difference between the replacement text of an object-like macro and the argument list of a function-like macro. Different things, different rules.

>I thought this reasoning would be equally obvious.
Nope, I really was baffled by what you were trying to prove with that particular example.

>clearly confirms that it has interpretted SWS as a single variable instead
>of expanding its macro definition of representing three parameters
This is correct.

>so it obviously interprets SWS and its expanded definition of three parameters
This is also correct, but you've stated an obvious truth that has no bearing at all on your problem. Clearly SWS will be replaced long before the ReadPeriph function is parsed. This is obvious because the preprocessor runs before the compiler. However, SWS will not be replaced before the argument list of the ReadPeriph macro is evaluated. The only time you'll have replacement conflicts like this is during the operation of the preprocessor. That's why I can't understand what you're trying to prove by showing that your code works by changing the macro to a function.

Comments
I should drop by the programming forums if you're back in skewering mode. :icon_razz:

I trust you can see what I am trying to achieve. My extract of code:

#define RCC_BASE 0x40021000
#define pRCC ((tRCC*) RCC_BASE)
#define SWS pRCC->CFGR, B2+B3, 2
#define ReadPeriph(Address, Bits, Shift) ((Address & (Bits)) >> Shift)

y8 = (u8)ReadPeriph(SWS);

is intended to give flexibility so I can define numerous macros like SWS and build them into the code by using the ReadPeriph macro. Can you suggest a way I can do this?

Incidentally, I found a webpage at http://gcc.gnu.org/ml/gcc-patches/2000-09/msg00430.html which I think describes a similar application to mine, and suggests that a patch added to gcc in 2000 should allow my application to work. To quote from it:

...there is now no hard limit on the number of nested macro invocations. If you have a long sequence of

#define a 1
#define b a+1
#define c b+1
...

with more than 200 macros in the chain, and you used the last one, the code used to be rejected; no more. (You should still use an enum instead.) The ISO C prohibition of macro recursion suffices to avoid infinite macro nesting.

this is wrong

#define SWS pRCC->CFGR, B2+B3, 2

do it like this, include the braces...

#define SWS (pRCC->CFGR, B2+B3, 2)

>this is wrong
Please explain why. I'm inclined to think that you're just repeating what your teachers have told you without understanding the rationale.

>do it like this, include the braces...
FYI, {} are braces, [] are brackets, () are parentheses.

>I trust you can see what I am trying to achieve.
Yes, of course.

>Can you suggest a way I can do this?
You've already discovered an ideal solution: change ReadPeriph to a function. If you want a direct comparison to the macro, make it inline. This saves you from monkeying with the preprocessor when you seem to have trouble even understanding what you're doing wrong.

>suggests that a patch added to gcc in 2000 should allow my application to work
That patch refers to a different issue. Your problem isn't recursion depth, it's the evaluation of an object-like macro as the argument to a function-like macro. You want the object-like macro to be expanded before the arguments are evaluated so that the expanded object-like macro represents an argument list rather than a single argument.

this is wrong

#define SWS pRCC->CFGR, B2+B3, 2

do it like this, include the braces...

#define SWS (pRCC->CFGR, B2+B3, 2)

I take this back... I meant something else... Apologies guys...
I thought if there is space in the macro, the other arguments will be ignored and so I thought parenthesis was required... but thats not the case... I tried with space, its working...

This article has been dead for over six months. Start a new discussion instead.