Dear,
could you tell me about the usage of "##" in preprossor
give me some simple examples.
thanks.
I just got the example from "dissection C" as follows:
#define X(i) x ## i
X(1)=X(2)=X(3);
==>
x1 = x2 = x3;
I can hardly make sense.
--
This is an implementation of a C++-ish standard header in C. The token
pasting makes it look ugly, and the reserved identifiers all over the
place uglier still, but it is what it is.
Gregory Pietsch
/* dynarray.h - dynamic array header
AUTHOR: Gregory Pietsch
This is an implementation of dynamic arrays of an unknown type.
This example assumes the following macros are defined:
T - the type of an array element. The only restriction on the
type is that it needs to be turned into a pointer by
postpending a *
TS - a "slug" prefix for all the functions in the library
and the array type
Tctor(x) - a function that initializes a T for use after malloc()ing
it. In other words, a constructor if I were using C++
Tdtor(x) - a destructor function, analagous to Tctor
Tassign(x,y) - An assignment function that assigns x to y. Both
elements are pointers to the actual elements
*/
#include <stdlib.h>
#include <stdio.h>
#define _VAL(y,x) y ## x
#define _NM(y,x) _VAL(y,x)
#ifndef CAPACITY_DEFINED
#define CAPACITY_DEFINED
typedef enum capacity
{
default_size,
reserve
} capacity;
#endif
#ifdef PROTOS_ONLY
/* types */
typedef struct _NM (TS, _ARRAY_T)
{
T *_Ptr;
size_t _Len, _Res;
} _NM (TS, _ARRAY_T);
_NM (TS, _ARRAY_T) * _NM (TS, _create) (void);
void
_NM (TS, _destroy) (_NM (TS, _ARRAY_T) *);
void
_NM (TS, _ctor) (_NM (TS, _ARRAY_T) *);
void
_NM (TS, _ctor_with_size) (_NM (TS, _ARRAY_T) *, size_t,
capacity);
void
_NM (TS, _copy_ctor) (_NM (TS, _ARRAY_T) *, _NM (TS, _ARRAY_T)
*);
void
_NM (TS, _ctor_from_ptr) (_NM (TS, _ARRAY_T) *, T *, size_t);
void
_NM (TS, _dtor) (_NM (TS, _ARRAY_T) *);
_NM (TS, _ARRAY_T) * _NM (TS, _append) (_NM (TS, _ARRAY_T) *, T *,
size_t,
size_t);
_NM (TS, _ARRAY_T) * _NM (TS, _assign) (_NM (TS, _ARRAY_T) *, T *,
size_t,
size_t);
_NM (TS, _ARRAY_T) * _NM (TS, _insert) (_NM (TS, _ARRAY_T) *, size_t,
T *,
size_t, size_t);
_NM (TS, _ARRAY_T) * _NM (TS, _remove) (_NM (TS, _ARRAY_T) *, size_t,
size_t);
_NM (TS, _ARRAY_T) * _NM (TS, _subarray) (_NM (TS, _ARRAY_T) *,
_NM (TS, _ARRAY_T) *,
size_t,
size_t);
void
_NM (TS, _swap) (_NM (TS, _ARRAY_T) *, _NM (TS, _ARRAY_T) *);
T *
_NM (TS, _get_at) (_NM (TS, _ARRAY_T) *, size_t);
void
_NM (TS, _put_at) (_NM (TS, _ARRAY_T) *, size_t, T *);
T *
_NM (TS, _base) (_NM (TS, _ARRAY_T) *);
size_t
_NM (TS, _length) (_NM (TS, _ARRAY_T) *);
void
_NM (TS, _resize) (_NM (TS, _ARRAY_T) *, size_t, T *);
size_t
_NM (TS, _reserve) (_NM (TS, _ARRAY_T) *);
void
_NM (TS, _set_reserve) (_NM (TS, _ARRAY_T) *, size_t);
#else
#ifndef Tctor
#define Tctor(x)
#endif
#ifndef Tdtor
#define Tdtor(x)
#endif
#ifndef Tassign
#define Tassign(x,y) (*(x) = *(y))
#endif
/* functions */
static void Nomemory (void)
{
fputs ("No memory\n", stderr);
abort ();
}
static void _NM (TS, _Xinv) (void)
{
fputs ("Invalid dynamic array argument\n", stderr);
abort ();
}
static void _NM (TS, _Xlen) (void)
{
fputs ("Length error: dynamic array too long\n", stderr);
abort ();
}
static void _NM (TS, _Xran) (void)
{
fputs ("Out of range: invalid dynamic array position\n", stderr);
abort ();
}
static void _NM (TS, _Tidy) (_NM (TS, _ARRAY_T) * this, int
_Constructed)
{
size_t i;
if (_Constructed && this->_Ptr != 0)
{
for (i = 0; i < this->_Len; i++)
Tdtor (this->_Ptr + i);
free (this->_Ptr);
}
this->_Len = 0;
this->_Ptr = 0;
this->_Res = 0;
}
static void _NM (TS, _Grow) (_NM (TS, _ARRAY_T) * this, size_t _N, T *
_S,
int _Trim)
{
size_t _Os = this->_Ptr == 0 ? 0 : this->_Res;
size_t _I, _M, _R;
T *_Np;
if (_N == 0)
{
if (_Trim)
_NM (TS, _Tidy) (this, 1);
}
else if (_N == _Os || _N < _Os && !_Trim);
else
{
_M = this->_Ptr == 0 && _N < this->_Res ? this->_Res : _N;
_Np = calloc (_M, sizeof (T));
if (_Np == 0)
Nomemory (); /* no memory */
for (_I = 0; _I < _M; _I++)
Tctor (_Np + _I);
_R = _M;
_M = _N < this->_Len ? _N : this->_Len;
for (_I = 0; _I < _M; ++_I)
Tassign (_Np + _I, this->_Ptr + _I);
if (_S != 0)
for (; _I < this->_Res; ++_I)
Tassign (_Np + _I, _S);
_NM (TS, _Tidy) (this, 1);
this->_Ptr = _Np;
this->_Res = _R;
}
this->_Len = _N;
}
/* Create a dynamic array from the void. */
_NM (TS, _ARRAY_T) * _NM (TS, _create) (void)
{
_NM (TS, _ARRAY_T) * x = malloc (sizeof (_NM (TS, _ARRAY_T)));
if (x == 0)
Nomemory ();
_NM (TS, _Tidy) (x, 0);
return x;
}
/* Completely return a dynamic array to the void. */
void _NM (TS, _destroy) (_NM (TS, _ARRAY_T) * x)
{
_NM (TS, _Tidy) (x, 1);
free (x);
}
/* Construct a previously allocated array. */
void _NM (TS, _ctor) (_NM (TS, _ARRAY_T) * this)
{
_NM (TS, _Tidy) (this, 0);
}
/* Construct an array with a reserve or default size. */
void _NM (TS, _ctor_with_size) (_NM (TS, _ARRAY_T) * this, size_t n,
capacity c)
{
_NM (TS, _Tidy) (this, 0);
this->_Res = n;
if (c == default_size)
_NM (TS, _Grow) (this, n, 0, 0);
}
/* Copy constructor - construct an array that is a copy of another
array. */
void _NM (TS, _copy_ctor) (_NM (TS, _ARRAY_T) * this, _NM (TS,
_ARRAY_T) * x)
{
size_t i;
_NM (TS, _Tidy) (this, 0);
_NM (TS, _Grow) (this, _NM (TS, _length) (x), 0, 0);
for (i = 0; i < this->_Len; i++)
Tassign (this->_Ptr + i, x->_Ptr + i);
}
/* Construct an array from a pointer and length. */
void _NM (TS, _ctor_from_ptr) (_NM (TS, _ARRAY_T) * this, T * s,
size_t n)
{
if (s == 0)
_NM (TS, _Xinv) ();
_NM (TS, _Tidy) (this, 0);
_NM (TS, _assign) (this, s, n, 1);
}
/* Destructor. */
void _NM (TS, _dtor) (_NM (TS, _ARRAY_T) * this)
{
_NM (TS, _Tidy) (this, 1);
}
/* Append an array to a dynamic array. */
_NM (TS, _ARRAY_T) * _NM (TS, _append) (_NM (TS, _ARRAY_T) * this, T *
_S,
size_t _N, size_t _D)
{
size_t _I;
if (NPOS - this->_Len <= _N)
_NM (TS, _Xlen) ();
_I = this->_Len;
for (_NM (TS, _Grow) (this, _N += _I, 0, 0); _I < _N; ++_I, _S +=
_D)
Tassign (this->_Ptr + _I, _S);
return this;
}
/* Assign an array to a dynamic array. */
_NM (TS, _ARRAY_T) * _NM (TS, _assign) (_NM (TS, _ARRAY_T) * this, T *
_S,
size_t _N, size_t _D)
{
size_t _I;
_NM (TS, _Grow) (this, _N, 0, 1);
for (_I = 0; _I < _N; ++_I, _S += _D)
Tassign (this->_Ptr + _I, _S);
return this;
}
/* Insert an array into a dynamic array at position _P. */
_NM (TS, _ARRAY_T) * _NM (TS, _insert) (_NM (TS, _ARRAY_T) * this,
size_t _P,
T * _S, size_t _N, size_t _D)
{
size_t _I;
if (this->_Len < _P)
_NM (TS, _Xran) ();
if (NPOS - this->_Len <= _N)
_NM (TS, _Xlen) ();
if (0 < _N)
{
_I = this->_Len - _P;
for (_NM (TS, _Grow) (this, _N + this->_Len, 0, 0); 0 < _I
{
--_I;
Tassign (this->_Ptr + (_P + _N + _I), this->_Ptr + (_P +
_I));
}
for (_I = 0; _I < _N; ++_I, _S += _D)
Tassign (this->_Ptr + (_P + _I), _S);
}
return this;
}
/* Remove _N elements from the array at position _P. */
_NM (TS, _ARRAY_T) * _NM (TS, _remove) (_NM (TS, _ARRAY_T) * this,
size_t _P,
size_t _N)
{
size_t _M, _I;
if (this->_Len < _P)
_NM (TS, _Xran) ();
if (this->_Len - _P < _N)
_N = this->_Len - _P;
if (0 < _N)
{
_M = this->_Len - _P - _N;
for (_I = 0; _I < _M; ++_I)
Tassign (this->_Ptr + (_P + _I), this->_Ptr + (_P + _I + _N));
_NM (TS, _Grow) (this, this->_Len - _N, 0, 0);
}
return this;
}
/* Assign _X to a subarray of this starting at position _P with length
_N. If this and _X are the same pointer, handle it via removing the
elements. */
_NM (TS, _ARRAY_T) * _NM (TS, _subarray) (_NM (TS, _ARRAY_T) * this,
_NM (TS, _ARRAY_T) * _X,
size_t _P,
size_t _N)
{
if (this->_Len < _P)
_NM (TS, _Xran) ();
if (this->_Len - _P < _N)
_N = this->_Len - _P;
return this == _X ? (_NM (TS, _remove) (this, _P + _N, NPOS),
_NM (TS, _remove) (this, 0, _P))
: _NM (TS, _assign) (_X, this->_Ptr + _P, _N, 1);
}
/* Swap the contents of two arrays. */
void _NM (TS, _swap) (_NM (TS, _ARRAY_T) * this, _NM (TS, _ARRAY_T) *
_X)
{
T *_Tp;
size_t _T;
_Tp = this->_Ptr;
this->_Ptr = _X->_Ptr;
_X->_Ptr = _Tp;
_T = this->_Len;
this->_Len = _X->_Len;
_X->_Len = _T;
_T = this->_Res;
this->_Res = _X->_Res;
_X->_Res = _T;
}
/* Get an element of the array. */
T *_NM (TS, _get_at) (_NM (TS, _ARRAY_T) * this, size_t _I)
{
if (this->_Len <= _I)
_NM (TS, _Xran) ();
return this->_Ptr + _I;
}
/* Put an element at a specific position in the array. If _I is one
past
the length of the array, handle it. */
void _NM (TS, _put_at) (_NM (TS, _ARRAY_T) * this, size_t _I, T * _X)
{
if (this->_Len < _I)
_NM (TS, _Xran) ();
else if (this->_Len == _I)
_NM (TS, _append) (this, _X, 1, 1);
else
Tassign (this->_Ptr + _I, _X);
}
/* Get the base of the array. */
T *_NM (TS, _base) (_NM (TS, _ARRAY_T) * this)
{
return this->_Len != 0 ? this->_Ptr : 0;
}
/* Get the length of the array. */
size_t _NM (TS, _length) (_NM (TS, _ARRAY_T) * this)
{
return this->_Len;
}
/* Resize the array. */
void _NM (TS, _resize) (_NM (TS, _ARRAY_T) * this, size_t _N, T * _X)
{
_NM (TS, _Grow) (this, _N, _X, 1);
}
/* Get the number of elements that are reserved. */
size_t _NM (TS, _reserve) (_NM (TS, _ARRAY_T) * this)
{
return this->_Res;
}
/* Set the number of elements that are reserved. This only works on
an
array with no elements in it. */
void _NM (TS, _set_reserve) (_NM (TS, _ARRAY_T) * this, size_t _R)
{
if (this->_Ptr == 0)
this->_Res = _R;
}
#endif
#undef _NM
#undef _VAL
/* END OF FILE */