Page 1 of 1

Use of C macros

Posted: Wed Oct 08, 2003 7:15 am
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) ?

Re:Use of C macros

Posted: Wed Oct 08, 2003 7:20 am
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) ?

Re:Use of C macros

Posted: Wed Oct 08, 2003 7:40 am
by Pype.Clicker
afaik,

Code: Select all

#if M==0
#if M>32
#if M<N
should work aswell ...

Re:Use of C macros

Posted: Wed Oct 08, 2003 7:54 am
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()

Re:Use of C macros

Posted: Wed Oct 08, 2003 8:08 am
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

Re:Use of C macros

Posted: Wed Oct 08, 2003 8:52 am
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.

Re:Use of C macros

Posted: Thu Oct 09, 2003 4:15 am
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

Re:Use of C macros

Posted: Thu Oct 09, 2003 4:29 am
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.

Re:Use of C macros

Posted: Thu Oct 09, 2003 7:16 am
by Perica
..

Re:Use of C macros

Posted: Thu Oct 09, 2003 8:34 am
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.

Re:Use of C macros

Posted: Thu Oct 09, 2003 8:56 am
by Perica
..

Re:Use of C macros

Posted: Thu Oct 09, 2003 12:15 pm
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.