# Thread: Strange macro, valid?

1. ## Strange macro, valid?

In a header I was looking at, I saw this...

Code:
`#define MMM_X(x)_Z(z)	(0x0C + (((x)-1)*3 + ((z)-1))*4)`
... is that valid? I don't recall seeing a macro like that before.

2. Looks strange, I've never seen anything like that, actualy... Does it compile?

--
Mats

3. Why not use 12 instead of 0x0C? I've never understood why people use hex when decimal is simpler. Yeah, that does look weird.

4. What on earth is that supposed to do?

5. That ain't right whatever it is. Even if _Z(x) was another macro that did something, it looks malformed. And if it does do something it needs to be rewritten free of stupid so we know what the hell is going on.

> Why not use 12 instead of 0x0C? I've never understood why people use hex when decimal is simpler.

Some people are nerds. There are uses for hex values though (it can be convenient if you're talking about bits or colors), but don't mix radices like that.

6. Originally Posted by Tommo
Why not use 12 instead of 0x0C? I've never understood why people use hex when decimal is simpler. Yeah, that does look weird.
I may be a nerd, but to me, there's really no difference between hex or decimal, but of course, it's not particularly easy to translate 0x1267 to 4711 decimal to me either. But common numbers such as 0x0C or 0x100, 0x200, 0xFFFF, I don't see a problem with.

There are different reasons to use one or another. In this case, perhaps the 0x0C is a register/offset/other-constant defined as 0x0C by some documentation?

--
Mats

7. Does it compile?
The kernel build completes without error.
Why not use 12 instead of 0x0C?
As I said in the original post, it is part of a kernel header, a large one, in which dozens of register values are defined, bit masks and other offsets. All of these are in hex. If I convert this line to decimal, I will be adding a source of error, since it will be assumed to be 0x12 to a non-careful reader.
we know what the hell is going on.
What "the hell" is going on, is at a base address, begins a list of registers, (in an ARM9 processor), dedicated to a particular function. At offset 0x0C, a repeating structure begins whereby there are 5 sets of 3 registers dedicated to subchannels in an on chip communications controller, or at least, that is what the macro is trying to do.

Thus, assuming a 0x00 start address and port 1 register 1...
Code:
`#define MMM_X(x)_Z(z)	(0x0C + (((x)-1)*3 + ((z)-1))*4)`
MMM_X(1)_Z(1);

(X-1)*3 = 0
(Z-1)*4 = 0

... therefore the address of port 1 register 1 is 0x00 + 0x0C + 0 + 0 i.e. 0x0C.

That is what I believe the designer of the header wishes to acheive, reading the datasheet of the chip, it certainly makes sense.

Regardless of the proclivity for embedded designers to work in hex, as we do, and the failure of GCC to complain, the question really remains the same. Is it legal?

I suspect not, but I tend to avoid the pre-processor and have done for years. I don't know for sure.

8. How about using "gcc -E" to output the preprocessed stuff and see what actually comes out?

--
Mats

9. Originally Posted by Exit
In a header I was looking at, I saw this...

Code:
`#define MMM_X(x)_Z(z)	(0x0C + (((x)-1)*3 + ((z)-1))*4)`
... is that valid? I don't recall seeing a macro like that before.
It would be "clearer" if the missing space had been retained:

Code:
`#define MMM_X(x) _Z(z)	(0x0C + (((x)-1)*3 + ((z)-1))*4)`
It's a macro of a single argument, x. _Z is presumably some other macro which reduces to a function name or function pointer.

Not particularly mysterious.

10. It would be "clearer" if the missing space had been retained:
Apart from name changes to "protect the innocent" that is as it appears in the header, there is NO space in the macro definition.

Your explanation does, in no way, reflect the actual requirement. If what you are suggesting is correct, then the author is way off. Clearly, 2 arguments are necessary to return the correct register offset.

11. Originally Posted by Exit
Apart from name changes to "protect the innocent" that is as it appears in the header, there is NO space in the macro definition.
I didn't say there was.

Your explanation does, in no way, reflect the actual requirement. If what you are suggesting is correct, then the author is way off. Clearly, 2 arguments are necessary to return the correct register offset.
Someone's confused, but it's not me:

Code:
```File mac1.c:
#define MMM_X(x)_Z(z)   (0x0C + (((x)-1)*3 + ((z)-1))*4)

int main()
{
int x, z;
MMM_X(1)_Z(2);
}

\$ gcc -E mac1.c
int main()
{
int x, z;
_Z(z) (0x0C + (((1)-1)*3 + ((z)-1))*4)_Z(2);
}```
Which is nonsense. Unless of course there is a macro called _Z.

12. I didn't say there was.
...
It would be "clearer" if the missing space had been retained:
Your implication was that a space had been omitted - that is not the case.

Consider, also, the actual requirement, which I have detailed.

I have already stated that I believe the construct to be dubious, however, it does not alter the fact that it is in a kernel header applicable to my current project, indeed, I now need to modify these registers in that switch, hence my interest.

13. Ok, so given what brewbuck points out (which is that the macro does work correctly).

Put a simpler way, this is LEGAL, even if it's not pretty, and will expand as follows

Code:
```#define a(x)y(x)
int main() {
a(7);
....```
becomes
Code:
```int main() {
y(7);
....```
So, yes, it's legal and works correctly - I'm pretty sure other compilers will also work OK with this construction, not just GCC.

However, I would insert a space there if I was modifying the file anyways.

--
Mats

14. so would it be right to conclude from this then that a closing bracket in a macro name delimits the end of that macro's name (and the start of its definition)? Interesting... can anyone confirm if this complies with the ISO99 definition of a C macro?

15. Originally Posted by @nthony
so would it be right to conclude from this then that a closing bracket in a macro name delimits the end of that macro's name (and the start of its definition)? Interesting... can anyone confirm if this complies with the ISO99 definition of a C macro?
I have no idea about what the standard says, but yes, it makes some sense that it is that way - spaces are really only used to delimit things when there is NOTHING else to go by - you can certainly use other constructs without spaces when there is a different delimiter...

I don't think there's any way to "use" the fact that there's no space between the macro name and it's definition...

--
Mats

Popular pages Recent additions