Strange macro, valid?

This is a discussion on Strange macro, valid? within the C Programming forums, part of the General Programming Boards category; 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 ...

  1. #1
    Registered User
    Join Date
    Aug 2003
    Posts
    15

    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. #2
    Kernel hacker
    Join Date
    Jul 2007
    Location
    Farncombe, Surrey, England
    Posts
    15,677
    Looks strange, I've never seen anything like that, actualy... Does it compile?

    --
    Mats

  3. #3
    Registered User Tommo's Avatar
    Join Date
    Jun 2007
    Location
    Scotland
    Posts
    101
    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. #4
    Technical Lead QuantumPete's Avatar
    Join Date
    Aug 2007
    Location
    London, UK
    Posts
    894
    What on earth is that supposed to do?
    "No-one else has reported this problem, you're either crazy or a liar" - Dogbert Technical Support
    "Have you tried turning it off and on again?" - The IT Crowd

  5. #5
    Registered User whiteflags's Avatar
    Join Date
    Apr 2006
    Location
    United States
    Posts
    7,667
    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. #6
    Kernel hacker
    Join Date
    Jul 2007
    Location
    Farncombe, Surrey, England
    Posts
    15,677
    Quote Originally Posted by Tommo View Post
    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. #7
    Registered User
    Join Date
    Aug 2003
    Posts
    15
    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.
    Last edited by Exit; 08-31-2007 at 09:11 AM. Reason: Spelling.

  8. #8
    Kernel hacker
    Join Date
    Jul 2007
    Location
    Farncombe, Surrey, England
    Posts
    15,677
    How about using "gcc -E" to output the preprocessed stuff and see what actually comes out?

    --
    Mats

  9. #9
    Captain Crash brewbuck's Avatar
    Join Date
    Mar 2007
    Location
    Portland, OR
    Posts
    7,239
    Quote Originally Posted by Exit View Post
    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. #10
    Registered User
    Join Date
    Aug 2003
    Posts
    15
    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.
    Last edited by Exit; 08-31-2007 at 02:53 PM.

  11. #11
    Captain Crash brewbuck's Avatar
    Join Date
    Mar 2007
    Location
    Portland, OR
    Posts
    7,239
    Quote Originally Posted by Exit View Post
    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. #12
    Registered User
    Join Date
    Aug 2003
    Posts
    15
    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. #13
    Kernel hacker
    Join Date
    Jul 2007
    Location
    Farncombe, Surrey, England
    Posts
    15,677
    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. #14
    Registered Abuser
    Join Date
    Jun 2006
    Location
    Toronto
    Posts
    591
    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. #15
    Kernel hacker
    Join Date
    Jul 2007
    Location
    Farncombe, Surrey, England
    Posts
    15,677
    Quote Originally Posted by @nthony View Post
    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

Page 1 of 2 12 LastLast
Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Problem building Quake source
    By Silvercord in forum Game Programming
    Replies: 16
    Last Post: 07-11-2010, 09:13 AM
  2. Errors including <windows.h>
    By jw232 in forum Windows Programming
    Replies: 4
    Last Post: 07-29-2008, 01:29 PM
  3. Quantum Random Bit Generator
    By shawnt in forum C++ Programming
    Replies: 62
    Last Post: 06-18-2008, 10:17 AM
  4. recursion error
    By cchallenged in forum C Programming
    Replies: 2
    Last Post: 12-18-2006, 08:15 AM
  5. Strange results using dnsapi and windns
    By Niara in forum Networking/Device Communication
    Replies: 3
    Last Post: 08-13-2005, 10:21 AM

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21