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

best way to declare struct to be used in other c and c++ files

1 view
Skip to first unread message

Tammy

unread,
Sep 5, 2008, 8:30:20 PM9/5/08
to
Hello all,

I am wondering what is the best way to declare a struct to be used in
other c and c++ files. Such as for a C API that will be used by
others.

1. Declaring the typedef and the struct in the header file and
including this file in all source files that need it? For example:

mystruct.h

typedef mystruct mystruct_t;

struct mystruct {
int x;
char c;
};

-OR-
2. Declaring the typedef in a header file and declaring the struct in
the .c file ( I am not certain that this will work). For example:

mystruct.h

typedef mystruct mystruct_t;


mystruct.c

#include "mystruct.h"

struct mystruct {
int x;
char c;
};

.....(other code using the structure)

-OR-

3. Other methods??

Thanks in advance for your help,
Tammy


pete

unread,
Sep 5, 2008, 8:42:11 PM9/5/08
to
Tammy wrote:
> Hello all,
>
> I am wondering what is the best way to declare a struct to be used in
> other c and c++ files. Such as for a C API that will be used by
> others.
>
> 1. Declaring the typedef and the struct in the header file and
> including this file in all source files that need it?

I define the typedef in the header file
and include this file in all source files that need it.

http://www.mindspring.com/~pfilandr/C/e_driver/e_driver.h

#define E_TYPE struct {char array[40]; d_type data;} e_type
#define D_TYPE long double d_type
typedef D_TYPE;
typedef E_TYPE;

http://www.mindspring.com/~pfilandr/C/e_driver/

--
pete

Ian Collins

unread,
Sep 5, 2008, 9:34:26 PM9/5/08
to
Tammy wrote:
> Hello all,
>
> I am wondering what is the best way to declare a struct to be used in
> other c and c++ files. Such as for a C API that will be used by
> others.
>
> 1. Declaring the typedef and the struct in the header file and
> including this file in all source files that need it? For example:
>
> mystruct.h
>
> typedef mystruct mystruct_t;
>
> struct mystruct {
> int x;
> char c;
> };
>
This is the normal way for a public structure declaration, with the
addition of a conditionally compiled extern "C" wrapper for the benefit
of C++ files that include the header.

> -OR-
> 2. Declaring the typedef in a header file and declaring the struct in
> the .c file ( I am not certain that this will work). For example:
>
> mystruct.h
>
> typedef mystruct mystruct_t;
>
>
> mystruct.c
>
> #include "mystruct.h"
>
> struct mystruct {
> int x;
> char c;
> };
>

If you want the details of mystruct to remain hidden, this is also
common practice.

--
Ian Collins.

Keith Thompson

unread,
Sep 5, 2008, 9:37:37 PM9/5/08
to
Tammy <TammyMa...@gmail.com> writes:
> I am wondering what is the best way to declare a struct to be used in
> other c and c++ files. Such as for a C API that will be used by
> others.
>
> 1. Declaring the typedef and the struct in the header file and
> including this file in all source files that need it? For example:
>
> mystruct.h
>
> typedef mystruct mystruct_t;
>
> struct mystruct {
> int x;
> char c;
> };

That needs to be "typedef struct mystruct mystruct_t;".

> -OR-
> 2. Declaring the typedef in a header file and declaring the struct in
> the .c file ( I am not certain that this will work). For example:
>
> mystruct.h
>
> typedef mystruct mystruct_t;
>
>
> mystruct.c
>
> #include "mystruct.h"
>
> struct mystruct {
> int x;
> char c;
> };
>
> .....(other code using the structure)

[...]

It depends on whether the client code needs to see the members and/or
declare objects of the type.

With the second approach struct mystruct, and therefore mystruct_t, is
an incomplete type as far as anything with a #include "mystruct.h" is
concerned. That means that client code can declare and manipulate
pointers to the type, but it can't declare objects of the type or
refer to its members.

--
Keith Thompson (The_Other_Keith) ks...@mib.org <http://www.ghoti.net/~kst>
Nokia
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"

Keith Thompson

unread,
Sep 5, 2008, 9:43:56 PM9/5/08
to

That's a very odd use of macros; I find it extremely counterintuitive.

Looking at the web page, it makes *some* sense in context. You have
(I'm abbreviating this):

#define STRUCTURES 0 /* 0 or 1, This is the line to change */

#if STRUCTURES == 0 /* Not this one */

#define E_TYPE long unsigned e_type
#define D_TYPE long unsigned d_type

#else

#define E_TYPE struct {char array[40]; d_type data;} e_type
#define D_TYPE long double d_type

#endif

typedef D_TYPE;
typedef E_TYPE;

I'm sure there's some good reason to conditionally define E_TYPE and
D_TYPE either as unsigned long or as a struct and a long double; I
haven't read enough of the code to understand what that reason might
be. But I definitely wouldn't write it that way. I'd probably write
something more like this:

#undef STRUCTURES /* defined or undefined

#ifdef STRUCTURES

typedef long double d_type;
typedef struct {char array[40]; d_type data;} e_type;

#else

typedef unsigned long d_type;
typedef unsigned long e_type;

#endif

In any case, your code sample illustrates the use of the preprocessor
to conditionally define types in one of two different ways, which
isn't what the OP was asking about.

pete

unread,
Sep 6, 2008, 2:50:47 AM9/6/08
to

I prefer to have the readily changeable parts of the program,
be macros.
The program also prints out the stringized macros.

The proper use of of the e_type interface,
is to define at least these three macros in a header file,
(there may be other macros depending on the sort algorithm)
for sorting functions which can then be used to sort
arrays of elements of any type, including arrays of arrays:

#define E_TYPE
#define MOV(A, B)
#define GT(A, B)

For example, I was looking at:
http://www.pobox.com/~qed/sort.html
which redirected me to
http://www.azillionmonkeys.com/qed/sort.html
and I downloaded the program at this link:
http://www.azillionmonkeys.com/qed/sorttest.c

and since I like to race sorting functions,
I changed the name of the program to pq_test
and replaced the definition of main with this:

#include "test_sort.h"

#define str(s) # s
#define xstr(s) str(s)

int main (void)
{
int seed = 0;
double r0, r1, r2, r3, r4, r5, r6, r7;

/* Warm up the cache */
{
int i;
for (i = 0; i < NUM_ITEMS; i++) numbers[i] = i;
heapSort (numbers, NUM_ITEMS);
}

r0 = timetest (seed, heapSort);
r1 = timetest (seed, quickSort);
r2 = timetest (seed, mergeSort);
r3 = NUM_ITEMS > 600 ? 0 : timetest (seed, insertSort);
r4 = timetest (seed, hsortmwrapper);
r5 = timetest (seed, pqsortwrapper);
r6 = timetest (seed, stablewrapper);
r7 = NUM_ITEMS > 600 ? 0 : timetest (seed, sisortwrapper);

puts("/* BEGIN pq_test.c output */\n");
puts("#define NUM_ITEMS " xstr(NUM_ITEMS) "\n");
printf (" heapsort: %.3f\n", r0);
printf (" quicksort: %.3f\n", r1);
printf (" mergesort: %.3f\n", r2);
printf ("insertsort: %.3f\n", r3);
putchar('\n');
printf (" hsortm: %.3f\n", r4);
printf (" pqsort: %.3f\n", r5);
printf (" stable: %.3f\n", r6);
printf (" sisort: %.3f\n", r7);
puts("\n/* END pq_test.c output */");

return 0;
}

Then I got these results:

/* BEGIN pq_test.c output */

#define NUM_ITEMS 6000

heapsort: 4.594
quicksort: 3.375
mergesort: 4.531
insertsort: 0.000

hsortm: 4.296
pqsort: 2.562
stable: 3.640
sisort: 0.000

/* END pq_test.c output */

Then I changed NUM_ITEMS to 600 and got these results:

/* BEGIN pq_test.c output */

#define NUM_ITEMS 600

heapsort: 0.375
quicksort: 0.265
mergesort: 0.359
insertsort: 2.406

hsortm: 0.344
pqsort: 0.203
stable: 0.281
sisort: 1.125

/* END pq_test.c output */

I also wrote 4 files to complete the program:
test_sort.h
test_sort.c
pqsort.h
pqsort.c

The point of doing it that way, is that the file,
pqsort.c, can be used as is, to sort arrays of any type,
without changing even a single byte.

The files look like this:

/* BEGIN test_sort.h */

#ifndef H_TEST_SORT_H
#define H_TEST_SORT_H

void hsortmwrapper(int numbers[], int qty);
void pqsortwrapper(int numbers[], int qty);
void stablewrapper(int numbers[], int qty);
void sisortwrapper(int numbers[], int qty);

#endif

/* END test_sort.h */


/* BEGIN test_sort.c */

#include <assert.h>

#include "test_sort.h"
#include "pqsort.h"

void hsortmwrapper(int numbers[], int qty)
{
hsortm(numbers, qty);
}

void pqsortwrapper(int numbers[], int qty)
{
assert(SMALL_PARTITION >= 4);
pqsort(numbers, qty);
}

void stablewrapper(int numbers[], int qty)
{
assert(SMALL_MERGE >= 1);
stable(numbers, qty);
}

void sisortwrapper(int numbers[], int qty)
{
sisort(numbers, qty);
}

/* END test_sort.c */


/* BEGIN pqsort.h */

#ifndef H_PQSORT_H
#define H_PQSORT_H

#include <stddef.h>

#define E_TYPE int e_type
#define MOV(A, B) ((void)(*(A) = *(B)))
#define GT(A, B) (*(A) > *(B))
#define SMALL_PARTITION 24
#define SMALL_MERGE 32

typedef E_TYPE;
/*
** (hsortm) is a double siftdown, casual heapsort.
*/
void hsortm(e_type *array, size_t nmemb);
/*
** (pqsort) is an introspective, median of three, quicksort.
*/
void pqsort(e_type *array, size_t nmemb);
/*
** (stable) is a stable merge sort / insertion sort.
*/
void stable(e_type *array, size_t nmemb);
/*
** (sisort) is a stable insertion sort.
*/
void sisort(e_type *array, size_t nmemb);

#endif

/* END pqsort.h */


/* BEGIN pqsort.c */

#include <stdlib.h>

#include "pqsort.h"

#define SWAP(A, B, T) \
(MOV((T), (A)), MOV((A), (B)), MOV((B), (T)))
#define SORT_3(A, B, C, T) \
if (GT((A), (B))) { \
MOV((T), (A)); \
if (GT((C), (B))) { \
MOV((A), (B)); \
if (GT((T), (C))) { \
MOV((B), (C)); \
MOV((C), (T)); \
} else { \
MOV((B), (T)); \
} \
} else { \
MOV((A), (C)); \
MOV((C), (T)); \
} \
} else { \
if (GT((B), (C))) { \
MOV((T), (B)); \
if (GT((A), (C))) { \
MOV((B), (A)); \
MOV((A), (C)); \
} else { \
MOV((B), (C)); \
} \
MOV((C), (T)); \
} \
}
#define SIFTDOWNM(P) \
{ \
parent = (P); \
child = parent * 2; \
MOV(&temp, array + parent); \
while (nmemb - parent > parent) { \
if (GT(array + child + 1, array + child)) { \
++child; \
} \
if (GT(array + child, &temp)) { \
MOV(array + parent, array + child); \
parent = child; \
child *= 2; \
} else { \
break; \
} \
} \
if (nmemb == child && GT(array + child, &temp)) { \
MOV(array + parent, array + child); \
parent = child; \
} \
MOV(array + parent, &temp); \
}

static void pqloop(e_type *array, size_t nmemb, size_t d);
static void merge(e_type *array, size_t nmemb, e_type *buff);

void hsortm(e_type *array, size_t nmemb)
{
size_t p, child, parent;
e_type temp;

if (nmemb > 1) {
p = --nmemb / 2;
do {
SIFTDOWNM(p);
} while (p-- != 0);
SWAP(array, array + nmemb, &temp);
while (--nmemb != 0) {
SIFTDOWNM(0);
SWAP(array, array + nmemb, &temp);
}
}
}

void pqsort(e_type *array, size_t nmemb)
{
size_t d, n;

d = 2;
for (n = nmemb / 4; n != 0; n /= 2) {
++d;
}
pqloop(array, nmemb, 2 * d);
}

void stable(e_type *array, size_t nmemb)
{
e_type *buff = malloc(nmemb / 2 * sizeof *buff);

if (buff != NULL) {
merge(array, nmemb, buff);
free(buff);
} else {
sisort(array, nmemb);
}
}

void sisort(e_type *array, size_t nmemb)
{
e_type *base, *low, *high, temp;

if (nmemb-- > 1) {
base = array;
do {
low = array++;
if (GT(low, array)) {
high = array;
MOV(&temp, high);
do {
MOV(high, low);
if (--high == base) {
break;
}
--low;
} while (GT(low, &temp));
MOV(high, &temp);
}
} while (--nmemb != 0);
}
}

static void pqloop(e_type *array, size_t nmemb, size_t d)
{
e_type *i, *j, temp;

while (nmemb > SMALL_PARTITION) {
if (!d--) {
hsortm(array, nmemb);
return;
}
i = 1 + array;
j = --nmemb + array;
SORT_3(j, array, i, &temp);
do {
SWAP(j, i, &temp);
do {
++i;
} while (GT(array, i));
do {
--j;
} while (GT(j, array));
} while (j > i);
SWAP(array, j, &temp);
pqloop(j + 1, nmemb + array - j, d);
nmemb = j - array;
}
sisort(array, nmemb);
}

static void merge(e_type *array, size_t nmemb, e_type *buff)
{
if (nmemb > SMALL_MERGE) {
e_type *mid_ptr;
size_t const half = nmemb / 2;
e_type *const after_buff = buff + half;
e_type *const middle = array + half;
e_type *const after_array = array + nmemb;

merge(middle, nmemb - half, buff);
merge(array, half, buff);
do {
if (GT(array, middle)) {
mid_ptr = middle;
buff = after_buff;
do {
--buff;
--mid_ptr;
MOV(buff, mid_ptr);
} while (array != mid_ptr);
MOV(array, middle);
mid_ptr = middle + 1;
while (middle != ++array) {
if (GT(buff, mid_ptr)) {
MOV(array, mid_ptr);
++mid_ptr;
} else {
MOV(array, buff);
++buff;
}
}
while (after_buff != buff) {
if (after_array != mid_ptr) {
if (GT(buff, mid_ptr)) {
MOV(array, mid_ptr);
++mid_ptr;
} else {
MOV(array, buff);
++buff;
}
++array;
} else {
do {
MOV(array, buff);
++array;
++buff;
} while (after_buff != buff);
break;
}
}
break;
} else {
++array;
}
} while (middle != array);
} else {
sisort(array, nmemb);
}
}

/* END pqsort.c */


--
pete

ac

unread,
Sep 6, 2008, 12:13:42 PM9/6/08
to
On Sat, 06 Sep 2008 07:50:47 +0100, pete <pfi...@mindspring.com> wrote:

> I prefer to have the readily changeable parts of the program,
> be macros.
> The program also prints out the stringized macros.
>
> The proper use of of the e_type interface,
> is to define at least these three macros in a header file,
> (there may be other macros depending on the sort algorithm)
> for sorting functions which can then be used to sort
> arrays of elements of any type, including arrays of arrays:
>
> #define E_TYPE
> #define MOV(A, B)
> #define GT(A, B)
>
> For example, I was looking at:
> http://www.pobox.com/~qed/sort.html
> which redirected me to
> http://www.azillionmonkeys.com/qed/sort.html
> and I downloaded the program at this link:
> http://www.azillionmonkeys.com/qed/sorttest.c
>
> and since I like to race sorting functions,
> I changed the name of the program to pq_test
> and replaced the definition of main with this:

Maybe a potential problem with this E_TYPE is we can only define one
etype_t in one C source file, which means we cannot sort an integer array
and a double array in the same C source file. Is that true? I think a
better way to achieve generic types is this example, using token
concatenation:

http://www.freewebs.com/attractivechaos/ksort.h.html
http://www.freewebs.com/attractivechaos/ksort_test.c.html

No function calls are made for comparisons, either.

BTW, it seems that you have implemented really efficient sorting
functions! How is it compared to STL sort?

Thanks,

-ac

pete

unread,
Sep 6, 2008, 10:20:21 PM9/6/08
to
ac wrote:
> On Sat, 06 Sep 2008 07:50:47 +0100, pete <pfi...@mindspring.com> wrote:
>
>> I prefer to have the readily changeable parts of the program,
>> be macros.
>> The program also prints out the stringized macros.
>>
>> The proper use of of the e_type interface,
>> is to define at least these three macros in a header file,
>> (there may be other macros depending on the sort algorithm)
>> for sorting functions which can then be used to sort
>> arrays of elements of any type, including arrays of arrays:
>>
>> #define E_TYPE
>> #define MOV(A, B)
>> #define GT(A, B)
>>
>> For example, I was looking at:
>> http://www.pobox.com/~qed/sort.html
>> which redirected me to
>> http://www.azillionmonkeys.com/qed/sort.html
>> and I downloaded the program at this link:
>> http://www.azillionmonkeys.com/qed/sorttest.c
>>
>> and since I like to race sorting functions,
>> I changed the name of the program to pq_test
>> and replaced the definition of main with this:
>
> Maybe a potential problem with this E_TYPE is we can only define one
> etype_t

I've heard that etype_t is reserved under POSIX rules,
which is why I write e_type.

> in one C source file, which means we cannot sort an integer
> array and a double array in the same C source file. Is that true?

Yes.

> I think a better way to achieve generic types is this example,
> using token concatenation:
>
> http://www.freewebs.com/attractivechaos/ksort.h.html
> http://www.freewebs.com/attractivechaos/ksort_test.c.html
>
> No function calls are made for comparisons, either.

Thank you.
That's very interesting to me.
I have no experience with ##.
Maybe it's about time for me to become more familiar with it.

> BTW, it seems that you have implemented really efficient sorting
> functions!

Thank you. It's a hobby of mine.

> How is it compared to STL sort?

It's actually Dann Corbit's C version of STL sort.
It's a smidgeon slower.

--
pete

ac

unread,
Sep 7, 2008, 1:17:58 PM9/7/08
to
On Sun, 07 Sep 2008 03:20:21 +0100, pete <pfi...@mindspring.com> wrote:

> That's very interesting to me.
> I have no experience with ##.
> Maybe it's about time for me to become more familiar with it.

If you are interested in this method, you may also have a look at this
header file:

http://www.freebsd.org/cgi/cvsweb.cgi/src/sys/sys/tree.h

This file is part of freebsd. It implements a splay tree and a rb tree,
allowing for generic types.

-ac

Peter Nilsson

unread,
Sep 7, 2008, 11:56:30 PM9/7/08
to
pete <pfil...@mindspring.com> wrote:
> ...The proper use of of the e_type interface,

> is to define at least these three macros in a header file,
> (there may be other macros depending on the sort algorithm)
> for sorting functions which can then be used to sort
> arrays of elements of any type, including arrays of arrays:
>
> #define E_TYPE
> #define MOV(A, B)
> #define GT(A, B)

I prefer to make the configurable components of the sort
template functions as macro parameters. [The following is
just proof of concept. File break up requires (re)insertion
of include guards and other details.]


%type sort.c
/* --------- */
/* pp_util.h */
/* --------- */
#define pp_cat(a, b) a ## b
#define pp_concat(a, b) pp_cat(a, b)

#define pp_t(T) pp_concat(T, _t)
typedef int int_t; /* and the rest */

#define pp_lt(a, b) ((a) < (b))
#define pp_assign(a, b) ((a) = (b))
#define pp_memcpy(a, b) memcpy(a, b, sizeof(a))


/* --------- */
/* pp_sort.h */
/* --------- */

/* #include "pp_util.h" */
#include <stddef.h>

#define pp_sort(T, a, n) \
pp_concat(sort_, T)(a, n)

#define pp_decl_sort(T) \
void pp_concat(sort_, T)(pp_t(T) *, size_t)

/* trivial for sake of demo */
#define pp_defn_sort(T, lt_pp, assign_pp) \
void pp_concat(sort_, T)( pp_t(T) *a, \
size_t n ) \
{ \
size_t i, j, k; \
pp_t(T) t; \
\
for (i = 0; i < n - 1; i++) \
{ \
for (k = i, j = i + 1; j < n; j++) \
if (lt_pp(a[j], a[i])) \
k = j; \
\
if (k != i) \
{ \
assign_pp(t, a[i]); \
assign_pp(a[i], a[k]); \
assign_pp(a[k], t ); \
} \
} \
}

pp_decl_sort(int); /* built-ins */


/* ----------- */
/* gauss_int.h */
/* ----------- */

typedef int gauss_int_t[2];
pp_decl_sort(gauss_int);


/* ------ */
/* main.c */
/* ------ */

/* #include "gauss_int.h" */
/* #include "pp_sort.h" */
#include <stdio.h>

#define countof(x) \
((size_t) (sizeof(x)/sizeof*(x)))

int main(void)
{
int ai[] = { 2, -4, 8, -16 };
gauss_int_t gi[] = { { 2, -4},
{ -8, 16 },
{32, -64},
{-128, 256} };
size_t i;

/* Integers */
for (i = 0; i < countof(ai); i++)
printf(" %d", ai[i]);
puts("");

sort_int(ai, countof(ai));

for (i = 0; i < countof(ai); i++)
printf(" %d", ai[i]);
puts("\n");

/* Gaussian Integers */
for (i = 0; i < countof(ai); i++)
printf(" (%d, %d)", gi[i][0], gi[i][1]);
puts("");

sort_gauss_int(gi, countof(gi));

for (i = 0; i < countof(ai); i++)
printf(" (%d, %d)", gi[i][0], gi[i][1]);
puts("");

return 0;
}


/* ------ */
/* sort.c */
/* ------ */

/* #include "pp_sort.h" */

pp_defn_sort(int, pp_lt, pp_assign)


/* ----------- */
/* gauss_int.c */
/* ----------- */

/* #include "pp_util.h" */
/* #include "pp_sort.h" */
#include <string.h>

#define pp_gauss_lt(a, b) \
( pp_lt( (a)[0], (b)[0] ) ? 1 \
: pp_lt( (b)[0], (a)[0] ) ? 0 \
: pp_lt( (a)[1], (b)[1] ) )

pp_defn_sort(gauss_int, pp_gauss_lt, pp_memcpy)

% acc sort.c

% a
2 -4 8 -16
-16 -4 2 8

(2, -4) (-8, 16) (32, -64) (-128, 256)
(-128, 256) (-8, 16) (2, -4) (32, -64)

%

--
Peter

pete

unread,
Sep 8, 2008, 2:33:22 AM9/8/08
to

Thank you.
I'll give it a good look.


--
pete

pete

unread,
Nov 16, 2008, 12:22:09 AM11/16/08
to

Thanks. I looked at that, but I've never learned trees.
I think I've got it down to something simple:


/* BEGIN output from ic_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 ic_sort.c */

/* BEGIN ic_sort.c */
/*
** ic_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 <stdio.h>
#include <string.h>

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

#define E_TYPEc char e_typec[sizeof "seven"]
#define MOVc(A, B) ((void)memcpy((A), (B), sizeof *(A)))
#define GTc(A, B) (strlen(*(A)) > strlen(*(B)))

#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)) { \
MOV##N(&temp, array); \
MOV##N(array, first); \
MOV##N(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 NMEMB(A) (sizeof (A) / sizeof *(A))

SORT_INIT(i)
SORT_INIT(c)

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[])(e_typei *, size_t) = {
no_sorti,
ssorti,
sisorti,
};
const char string[][sizeof "seven"] = {"seven","eight","six"};
char arraychar[NMEMB(string)][sizeof "seven"];
void (*sort_char[])(e_typec *, size_t) = {
no_sortc,
ssortc,
sisortc,
};

puts("/* BEGIN output from ic_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 ic_sort.c */");
return 0;
}

/* END ic_sort.c */


--
pete

pete

unread,
Nov 16, 2008, 10:43:33 AM11/16/08
to
pete wrote:
> ac wrote:
>> On Sun, 07 Sep 2008 03:20:21 +0100, pete <pfi...@mindspring.com> wrote:
>>
>>> That's very interesting to me.
>>> I have no experience with ##.
>>> Maybe it's about time for me to become more familiar with it.
>>
>> If you are interested in this method, you may also have a look at this
>> header file:
>>
>> http://www.freebsd.org/cgi/cvsweb.cgi/src/sys/sys/tree.h
>>
>> This file is part of freebsd. It implements a splay tree and a rb
>> tree, allowing for generic types.
>
> Thanks. I looked at that, but I've never learned trees.
> I think I've got it down to something simple:
>
> /* BEGIN output from ic_sort.c */

And I think I like it this way,
for multifile program organization:

/* 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 <stdio.h>
#include <string.h>

#include "ia_init.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)][sizeof "seven"];

void (*sort_char[])(char (*)[sizeof "seven"], 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

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 <string.h>

#include "ia_init.h"

#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

0 new messages