Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

typedef vs. #define

64 views
Skip to first unread message

Mark

unread,
Mar 9, 2010, 3:04:18 AM3/9/10
to
Hello

are there any other pros to using #defined new types, except the one
mentioned in C-FAQ 1.13? Quite often I see in chips SDKs things like these:

#ifndef int8
#define int8 char
#endif
...
#ifndef uint32
#define uint32 unsigned int
#endif

Looks quite ugly to me, I'd prefer 'typedef' these types, but perhaps I'm
missing something?

--
Mark

Richard Heathfield

unread,
Mar 9, 2010, 3:25:27 AM3/9/10
to
Mark wrote:
> Hello
>
> are there any other pros to using #defined new types, except the one
> mentioned in C-FAQ 1.13? Quite often I see in chips SDKs things like these:
>
> #ifndef int8
> #define int8 char
> #endif
> ....

> #ifndef uint32
> #define uint32 unsigned int
> #endif
>
> Looks quite ugly to me, I'd prefer 'typedef' these types,

Quite right.

> but perhaps
> I'm missing something?

Assuming we're talking conforming implementations here, what you're
missing is that not everyone has read the C FAQ.

--
Richard Heathfield <http://www.cpax.org.uk>
Email: -http://www. +rjh@
"Usenet is a strange place" - dmr 29 July 1999
Sig line vacant - apply within

Malcolm McLean

unread,
Mar 9, 2010, 4:15:25 AM3/9/10
to
On 9 Mar, 08:04, "Mark" <mark_cruzNOTFORS...@hotmail.com> wrote:
>
> are there any other pros to using #defined new types, except the one
> mentioned in C-FAQ 1.13? Quite often I see in chips SDKs things like these:
>
> Looks quite ugly to me, I'd prefer 'typedef' these types, but perhaps I'm
> missing something?
>
For very short programs it doesn't really matter.
However #defines are word processing commands, typedefs alias types.
This means that you can do things like

#define int8 char
unsigned int8


The technical term for this is "preprocessor abuse". It can be handy.
Another thing you can do is
stringise the #defined type macro. This might be useful if writing
some sort of God-awful generic function, using strings as cheap and
cheerful C++ templates.

Fred

unread,
Mar 9, 2010, 10:18:56 AM3/9/10
to
On Mar 9, 1:15 am, Malcolm McLean <malcolm.mcle...@btinternet.com>
wrote:

Using the #define method can easily lead to errors.
Consider:
#define String char*
vs.
typedef String char*

followed by:
String a,b,c;

If you used the #define, bad things are likely to occur.
--
Fred K

Seebs

unread,
Mar 9, 2010, 10:48:04 AM3/9/10
to
On 2010-03-09, Mark <mark_cruz...@hotmail.com> wrote:
> Looks quite ugly to me, I'd prefer 'typedef' these types, but perhaps I'm
> missing something?

The obvious thing would be the lack of a way to spell "iftypedef(uint32)".

-s
--
Copyright 2010, all wrongs reversed. Peter Seebach / usenet...@seebs.net
http://www.seebs.net/log/ <-- lawsuits, religion, and funny pictures
http://en.wikipedia.org/wiki/Fair_Game_(Scientology) <-- get educated!

ImpalerCore

unread,
Mar 9, 2010, 3:27:35 PM3/9/10
to

The typedef is the preferred implementation, but as Seebs said, not
having a convenient syntax for verifying that a typedef exists either
leads them to using #define or relying on an autoconf test to define a
HAVE_UINT32_T or maybe a HAVE_STDINT_H symbol. In my case, I have a
stdint wrapper that either includes the real stdint.h if HAVE_STDINT_H
is defined, or declare my own stdint subset (consisting mostly the
uintN_t types and the _C, _MIN, and _MAX macros).

> --
> Mark

pete

unread,
Mar 9, 2010, 7:10:18 PM3/9/10
to

I like to use both.
I prefer the readily changable part of the code to be macros.

#define E_TYPE char

typedef E_TYPE e_type

--
pete

Mark

unread,
Mar 9, 2010, 7:16:16 PM3/9/10
to
Seebs wrote:
> On 2010-03-09, Mark <mark_cruz...@hotmail.com> wrote:
>> Looks quite ugly to me, I'd prefer 'typedef' these types, but
>> perhaps I'm missing something?
>
> The obvious thing would be the lack of a way to spell
> "iftypedef(uint32)".
That was mentioned in FAQ, I thought there could be other benefits too.

--
Mark

Nick Keighley

unread,
Mar 10, 2010, 3:14:15 AM3/10/10
to
On 9 Mar, 08:04, "Mark" <mark_cruzNOTFORS...@hotmail.com> wrote:

> Hello

Hello, I've taken my pedantry medication this morning.


> are there any other pros to using #defined new types,

technically, you can't create new types with a preprocessor macro.


> [...] Quite often I see in chips SDKs things like these:


>
> #ifndef int8
> #define int8    char
> #endif
> ...
> #ifndef uint32
> #define uint32   unsigned int
> #endif
>
> Looks quite ugly to me, I'd prefer 'typedef' these types, but perhaps I'm
> missing something?

you can't create a new types witha typedef. typedef only creates a
type alias.


Consider:-
<code>

#define M_int int
typedef int T_int;

struct S_int1
{
int i;
};

struct S_int2
{
int i;
};

int main (void)
{
int *pi;
M_int *mpi;
T_int *tpi;
struct S_int1 *spi1;
struct S_int2 *spi2;

mpi = pi; /* 1 */
tpi = pi; /* 2 */

spi1 = spi2; /* 3 */

return 0;
}

</code>

the lines marked 1 and 2 don't give an error because in the first case
the copiler sees no difference and the second they are merely aliases
for each other. structs on the other hand *are* new types so you get a
type incompatibility warning (from VCC anyway).

Is this a required diagnostic? I'd hope so.


--
- Yes it works in practice - but does it work in theory?

Phred Phungus

unread,
Mar 10, 2010, 3:57:04 AM3/10/10
to
pete wrote:
> Mark wrote:
>> Hello
>>
>> are there any other pros to using #defined new types, except the one
>> mentioned in C-FAQ 1.13? Quite often I see in chips SDKs things like these:
>>
>> #ifndef int8
>> #define int8 char
>> #endif
>> ...
>> #ifndef uint32
>> #define uint32 unsigned int
>> #endif
>>
>> Looks quite ugly to me, I'd prefer 'typedef' these types,
>> but perhaps I'm missing something?
>
> I like to use both.
> I prefer the readily changable part of the code to be macros.

What do you mean? Function-like macros?


>
> #define E_TYPE char
>
> typedef E_TYPE e_type
>

E_TYPE seems to be popular this way.
--
fred

pete

unread,
Mar 10, 2010, 6:37:37 AM3/10/10
to

/*
** I meant the E_TYPE macro:
*/
#define E_TYPE unsigned
/*
** and also some function like macros:
*/
#define MOV(A, B) ((void)(*(A) = *(B)))
#define GT(A, B) (*(A) > *(B))
/*
** Then I don't have to touch the typedef or the function definition
** or the SWAP macro.
*/
#define SWAP(A, B, T) \
(MOV((T), (A)), MOV((A), (B)), MOV((B), (T)))

typedef E_TYPE e_type;

void ssort(e_type *array, size_t nmemb)
{
e_type *first, *middle, temp;
size_t counter;

while (nmemb-- > 1) {
first = middle = array + 1;
counter = nmemb;
while (--counter != 0) {
++middle;
if (GT(first, middle)) {
first = middle;
}
}
if (GT(array, first)) {
SWAP(array, first, &temp);
}
++array;
}
}

--
pete

pete

unread,
Mar 10, 2010, 6:45:39 AM3/10/10
to
Phred Phungus wrote:
> pete wrote:

>> #define E_TYPE char
>>
>> typedef E_TYPE e_type
>>
>
> E_TYPE seems to be popular this way.

/*
** This is the more interesting use of it:
*/

/* BEGIN output from ia_sort.c */

Arrays of element type (int),
are being sorted into ascending order.

This is the original order of the test array:
7
8
6

Sorted by simple selection sort:
6
7
8

Sorted by stable insertionsort:
6
7
8


Arrays of element type (char [sizeof "seven"]),
are being sorted by string length.

This is the original order of the test array:
seven
eight
six

Sorted by simple selection sort:
six
eight
seven

Sorted by stable insertionsort:
six
seven
eight

/* END output from ia_sort.c */


/* BEGIN ia_sort.c */
/*
** ia_sort.c shows how to
** sort an array of int and also how to
** sort an array of array of six char,
** from within the same file,
** using sort functions with the e_type interface.
*/
#include "ia_init.h"

#include <stdio.h>
#include <string.h>

#define NMEMB(A) (sizeof (A) / sizeof *(A))

int main(void)
{
size_t sort, element;
char *description[] = {
{"This is the original order of the test array:"},
{"Sorted by simple selection sort:"},
{"Sorted by stable insertionsort:"}
};
const int integer[] = {7,8,6};
int arrayint[NMEMB(integer)];
void (*sort_int[])(int *, size_t) = {
no_sorti,
ssorti,
sisorti,
};
const char string[][sizeof "seven"] = {"seven","eight","six"};
char arraychar[NMEMB(string)][NMEMB(*string)];
void (*sort_char[])(char (*)[NMEMB(*string)], size_t) = {
no_sorta,
ssorta,
sisorta,
};

puts("/* BEGIN output from ia_sort.c */");
puts("\nArrays of element type (int),\n"
"are being sorted into ascending order.\n");
for (sort = 0; sort != NMEMB(sort_int); ++sort) {
memcpy(arrayint, integer, sizeof arrayint);
sort_int[sort](arrayint, NMEMB(arrayint));
puts(description[sort]);
for (element = 0; element != NMEMB(arrayint); ++element) {
printf("%d\n", arrayint[element]);
}
putchar('\n');
}
puts("\nArrays of element type (char [sizeof \"seven\"]),\n"
"are being sorted by string length.\n");
for (sort = 0; sort != NMEMB(sort_char); ++sort) {
memcpy(arraychar, string, sizeof arraychar);
sort_char[sort](arraychar, NMEMB(arraychar));
puts(description[sort]);
for (element = 0; element != NMEMB(arraychar); ++element) {
printf("%s\n", arraychar[element]);
}
putchar('\n');
}
puts("/* END output from ia_sort.c */");
return 0;
}

/* END ia_sort.c */


/* BEGIN ia_init.h */

#ifndef H_IA_INIT_H
#define H_IA_INIT_H

#include <stddef.h>

void no_sorti(int *array, size_t nmemb);
void ssorti(int *array, size_t nmemb);
void sisorti(int *array, size_t nmemb);

void no_sorta(char (*array)[sizeof"seven"], size_t nmemb);
void ssorta(char (*array)[sizeof"seven"], size_t nmemb);
void sisorta(char (*array)[sizeof"seven"], size_t nmemb);

#endif

/* END ia_init.h */


/* BEGIN ia_init.c */

#include "ia_init.h"

#include <string.h>

#define SWAP(N, A, B, T) \
(MOV##N((T), (A)), MOV##N((A), (B)), MOV##N((B), (T)))

#define SORT_INIT(N) \
typedef E_TYPE##N; \
void no_sort##N(e_type##N *array, size_t nmemb) \
{ \
array, nmemb; \
} \
void ssort##N(e_type##N *array, size_t nmemb) \
{ \
e_type##N *first, *middle, temp; \


size_t counter; \
\
while (nmemb-- > 1) { \
first = middle = array + 1; \
counter = nmemb; \
while (--counter != 0) { \
++middle; \

if (GT##N(first, middle)) { \
first = middle; \
} \
} \
if (GT##N(array, first)) { \
SWAP(N, array, first, &temp); \
} \
++array; \
} \
} \
void sisort##N(e_type##N *array, size_t nmemb) \
{ \
e_type##N *base, *low, *high, temp; \
\
if (nmemb-- > 1) { \
base = array; \
do { \
low = array++; \
if (GT##N(low, array)) { \
high = array; \
MOV##N(&temp, high); \
do { \
MOV##N(high, low); \
if (--high == base) { \
break; \
} \
--low; \
} while (GT##N(low, &temp)); \
MOV##N(high, &temp); \
} \
} while (--nmemb != 0); \
} \
}

#define E_TYPEi int e_typei
#define MOVi(A, B) ((void)(*(A) = *(B)))
#define GTi(A, B) (*(A) > *(B))

#define E_TYPEa char e_typea[sizeof "seven"]
#define MOVa(A, B) ((void)memcpy((A), (B), sizeof *(A)))
#define GTa(A, B) (strlen(*(A)) > strlen(*(B)))

SORT_INIT(i)
SORT_INIT(a)

/* END ia_init.c */


--
pete

pete

unread,
Mar 10, 2010, 6:50:42 AM3/10/10
to
Phred Phungus wrote:
>
> pete wrote:

> > #define E_TYPE char
> >
> > typedef E_TYPE e_type
> >
>
> E_TYPE seems to be popular this way.

I forgot to mention that I got it from Dann Corbit.

--
pete

0 new messages