Use of C macros

Question about which tools to use, bugs, the best way to implement a function, etc should go here. Don't forget to see if your question is answered in the wiki first! When in doubt post here.
Post Reply
pini

Use of C macros

Post by pini »

I have defined a simple C macro like this

Code: Select all

#define M 0
M here takes the value 0, but it could (in the future) take any integer positive value between 0 and 64 (for example).

Elsewhere, I want to define a prototype according to the value of M (not the same prototype for all values).
That is, I would like to do something like that :

Code: Select all

#if M=0
typeA func()
#else
typeB func()
#end if
And some goes for this function's body.

How is it possible to achieve this (mainly with GCC) ?
pini

Re:Use of C macros

Post by pini »

I found out that

Code: Select all

#if !M
works when M is 0 (that way, the #else clause gives M not 0).

Can I check M against other values (positive) ?
User avatar
Pype.Clicker
Member
Member
Posts: 5964
Joined: Wed Oct 18, 2006 2:31 am
Location: In a galaxy, far, far away
Contact:

Re:Use of C macros

Post by Pype.Clicker »

afaik,

Code: Select all

#if M==0
#if M>32
#if M<N
should work aswell ...
User avatar
Solar
Member
Member
Posts: 7632
Joined: Thu Nov 16, 2006 12:01 pm
Location: Germany
Contact:

Re:Use of C macros

Post by Solar »

Hmmm... you don't tell us what this "trick" would be for, but for your example, it would probably be "better" (in terms of readability) to do this:

Code: Select all

#define RET_T typeA

RET_T func()
Every good solution is obvious once you've found it.
sonneveld

Re:Use of C macros

Post by sonneveld »

urgh.. don't use #define for types. What if you did this?

Code: Select all

#define MYTYPE int *

{
     MYTYPE a,b,c;
}
You would actually get:

Code: Select all

{
     int *a, b, c;
}
which means only 'a' is an integer pointer.

Use typedef instead. I think the reason why it was introduced was because macros just didn't cut it when it came to types in C.

Code: Select all

typedef int* MYTYPE ;

{
     MYTYPE a,b,c;  /* a, b and c are all int* */
}
- Nick
User avatar
Solar
Member
Member
Posts: 7632
Joined: Thu Nov 16, 2006 12:01 pm
Location: Germany
Contact:

Re:Use of C macros

Post by Solar »

He... see, too long in C++ country using templates and you start forgetting the basics. Of course you're right, a typedef would be much better.

But...
Nick Sonneveld wrote:

Code: Select all

#define MYTYPE int *

{
     MYTYPE a,b,c;
}
You would actually get:

Code: Select all

{
     int *a, b, c;
}
This is (one of the many reasons) why you shouldn't typedef a pointer type, ever. A pointer to a type is not a type itself. Additionally:

* think hard about writing more than one declaration per line;

* initialize your values at declaration.
Every good solution is obvious once you've found it.
User avatar
Candy
Member
Member
Posts: 3883
Joined: Tue Oct 17, 2006 11:33 pm
Location: Eindhoven

Re:Use of C macros

Post by Candy »

This is (one of the many reasons) why you shouldn't typedef a pointer type, ever.
You mean: "This is (one of the many reasons) why you shouldn't #define a pointer type, ever"

Typedeffing any types is ok, #define-ing normal types (ints, floats) is also ok, #define-ing pointers is bad (same goes for references, but that's c++)

To the original question, if you're trying to do something like me (making portable code) you might want to make a types.h file containing a list of types that are platformspecific types. My own list has int8, int16, int32, int64 all defined so they end up being that size on each computer I'm aiming for, and intn for native ints. A native int has 32 bits on a 32-bit cpu, 64 bits on a 64-bit cpu etc.

If you are trying to do the same, try using uintn (or sintn) for those functions, resulting in:

uintn function();

which ends up being what you want on both platforms.

HTH, Candy
User avatar
Solar
Member
Member
Posts: 7632
Joined: Thu Nov 16, 2006 12:01 pm
Location: Germany
Contact:

Re:Use of C macros

Post by Solar »

Candy wrote:
This is (one of the many reasons) why you shouldn't typedef a pointer type, ever.
You mean: "This is (one of the many reasons) why you shouldn't #define a pointer type, ever"

Typedeffing any types is ok, #define-ing normal types (ints, floats) is also ok, #define-ing pointers is bad (same goes for references, but that's c++)
No, actually I meant what I said. It's personal taste, and I've been known to be a purist, but I feel that a pointer to something should always be just that, a pointer to something - not a something. It does make a difference e.g. when coding containers in C++.

One exception I find acceptable are function pointers, which by their syntax are so unwieldly that it's usually a good idea to typedef them.

Again, that's personal taste.
Every good solution is obvious once you've found it.
Perica
Member
Member
Posts: 454
Joined: Sat Nov 25, 2006 12:50 am

Re:Use of C macros

Post by Perica »

..
Last edited by Perica on Sun Dec 03, 2006 9:20 pm, edited 1 time in total.
User avatar
Solar
Member
Member
Posts: 7632
Joined: Thu Nov 16, 2006 12:01 pm
Location: Germany
Contact:

Re:Use of C macros

Post by Solar »

Perica wrote: Just out of curiosity, do all platforms support the addressing and acess of data smaller than it's native size? For example, are there any platforms that force you to acess data on a native-size aligned boundary??
Yes, there definitely are architectures that e.g. don't allow to access a word at an odd address.

IIRC the MC68k was such a system (I still remember the Guru Meditation on my Amiga telling me of unaligned access). I don't know about the PPC, Sparc, or other such up-to-date systems.
Every good solution is obvious once you've found it.
Perica
Member
Member
Posts: 454
Joined: Sat Nov 25, 2006 12:50 am

Re:Use of C macros

Post by Perica »

..
Last edited by Perica on Sun Dec 03, 2006 9:20 pm, edited 1 time in total.
Jamethiel

Re:Use of C macros

Post by Jamethiel »

Perica wrote: Or, can i make the assumption that when compiling this code for such a platform, the data will receive the proper alignment etc. ?
In general, any variables allocated in your stack frame or at translation unit or global scope in C will have sufficient alignment for their natural use.

Any memory allocated with malloc() and friends will have alignment sufficient for the most restrictive type for the CPU (if your CPU requires some data to be aligned on an 8-byte boundary, then malloc() will return space aligned on an 8-byte boundary).

Any struct definitions that haven't been messed about with by somehting like GCC's __attribute__ ((packed)) notation will have all field offsets within them aligned appropriately to their type, assuming that the base of the struct is aligned as if it was returned from malloc().

In general, you aren't likely to run into too much trouble, since many systems merely suffer performance degredation from unaligned access rather than taking an exception. For most of the rest, you're only going to run into trouble when parsing structured data by hand.

Of course there are still platforms out there with weird and wonderful addressing setups such as only supporting 36-bit wide words, and only supporting word addressing, but you aren't likely to run into these in practice.

(For more weird and wonderful memory addressing semantics, there are systems out there which, when you read memory, checks to see if it has a 'forwarding pointer' which tells the system to go read a different memory location for the real data.)

But, as I said, unless you're going to target something messed up like a 68000 (not a 68020 or better, the original 68000), some of the PDPs, or Lisp Machine hardware, alignment isn't something to waste too much worry on.
Post Reply