about ## in ANSI C

J

J Wang

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.

--
 
J

James Hu

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.

It is the preprocessor's "paste" operator. It concatenates the
preprocessing token on its left to the preprocessing token on its
right.

Also read the answer to question 10.20 of the C-faq.

http://www.eskimo.com/~scs/C-faq/top.html

-- James
 
G

Gregory Pietsch

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 */
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
474,141
Messages
2,570,817
Members
47,362
Latest member
ChandaWagn

Latest Threads

Top