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
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
#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.
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
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!
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
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
> 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?
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
/*
** 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
>> #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
> > #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