Macros in C

Posted by Greven on Tue 22 Jun 2004 11:44 PM — 10 posts, 28,569 views.

Canada #0
Anyone happen to know what header file the __line__ and __file__ macros are located in? Or more to the point, does anyone know what the __string macro does, and what file I would need to include to use it? Never heard about this one before, and I don't even know where to look via man pages.
USA #1
__LINE__ and __FILE__ are in stdio.h I believe. Never heard of the string one.
USA #2
__LINE__ and __FILE__ aren't defined in stdio.h. They're defined by the standard as being the current line and file being read. They are expanded by the preprocessor.

I haven't heard of __string I don't think, but I would guess that it takes its argument and puts "" around it.
e.g. __STRING__(x) --> "x"
USA #3
Whoops, guess lookin at examples of macro's isn't the way to go since you need stdio.h to do anything anyways. :P
Canada #4
Well, here is what its used in:
#define CHECK_LINKS(first, last, next, prev, type)		\
do {								\
  type *ptr, *pptr = NULL;					\
  if ( !(first) && !(last) )					\
    break;							\
  if ( !(first) )						\
  {								\
    bug( "CHECK_LINKS: last with NULL first!  %s.",		\
        __STRING(first) );					\
    for ( ptr = (last); ptr->prev; ptr = ptr->prev );		\
    (first) = ptr;						\
  }								\
  else if ( !(last) )						\
  {								\
    bug( "CHECK_LINKS: first with NULL last!  %s.",		\
        __STRING(first) );					\
    for ( ptr = (first); ptr->next; ptr = ptr->next );		\
    (last) = ptr;						\
  }								\
  if ( (first) )						\
  {								\
    for ( ptr = (first); ptr; ptr = ptr->next )			\
    {								\
      if ( ptr->prev != pptr )					\
      {								\
        bug( "CHECK_LINKS(%s): %p:->prev != %p.  Fixing.",	\
            __STRING(first), ptr, pptr );			\
        ptr->prev = pptr;					\
      }								\
      if ( ptr->prev && ptr->prev->next != ptr )		\
      {								\
        bug( "CHECK_LINKS(%s): %p:->prev->next != %p.  Fixing.",\
            __STRING(first), ptr, ptr );			\
        ptr->prev->next = ptr;					\
      }								\
      pptr = ptr;						\
    }								\
    pptr = NULL;						\
  }								\
  if ( (last) )							\
  {								\
    for ( ptr = (last); ptr; ptr = ptr->prev )			\
    {								\
      if ( ptr->next != pptr )					\
      {								\
        bug( "CHECK_LINKS (%s): %p:->next != %p.  Fixing.",	\
            __STRING(first), ptr, pptr );			\
        ptr->next = pptr;					\
      }								\
      if ( ptr->next && ptr->next->prev != ptr )		\
      {								\
        bug( "CHECK_LINKS(%s): %p:->next->prev != %p.  Fixing.",\
            __STRING(first), ptr, ptr );			\
        ptr->next->prev = ptr;					\
      }								\
      pptr = ptr;						\
    }								\
  }								\
} while(0)


Used in this context, I assume that it casts a pointer of unknown type to a string, but I dunno for sure.
USA #5
No, I don't think so. first is actually a macro variable and is probably some variable... e.g. ch->first_carrying.

When you do checklinks(ch->first_carrying,...), first expands to ch->first_carrying. Then, when you do __STRING() on it, you get "ch->first_carrying". This way, you get to output the variable name you're checking, as opposed to just the pointer address (which isn't very helpful.)

If it were casting a pointer to a string, how could that be useful? You'd get a string of gibberish up until the first null byte. That'd be a kind of silly function. :)
Canada #6
While I agree that you would not be getting good information out of it, I also agree that "ch->first_carrying" wouldn't exactly be that handy either, so I'm totally stumped.
USA #7
Sure it would be handy. You'd know that the character carrying list is screwing up as opposed to e.g. the room's list of people or contents. If you'd like I can whip up a small test script but I'm nearly positive that the string macro just puts on the quotation marks.
Canada #8
K, so I guess that its probably defined something like:

#define __STRING(x) "(x)"

Reason I'm asking is that it seems to be undefined in cygwin, as I making sure that it complies nicely on a bunch of different platforms. freebsd is next I guess, then RH.
USA #9
Yup.

int main()
{
    cout << __STRING(hello) << endl;

    return 0;
}


On RH, this prints out:
hello

As I would have expected.

I confirm that on Cygwin it does not seem to work.

Your define won't work; you need to do:

#define __STRING(x) #x

I believe that the # operator is the "correct" way of doing __STRING.