Re: Pointers

From: Daniel A. Koepke (dkoepke@california.com)
Date: 11/11/99


On Fri, 12 Nov 1999, blah wrote:

> is
>
> char *temp;
>
> the same as
>
> char *temp = NULL;

Well, obviously, they're not the same: one sets the pointer 'temp' to
NULL, the other doesn't.  A lot of newbies have trouble with the fact that
C does NOT initialize your variables to some sane value for you.  Thus,
"int a;" will NOT create an integer variable 'a' that is set to 0.  You'll
get some seemingly random numbers from 'a'.  People set pointers to NULL
because otherwise it's impossible to tell if they've been set to anything
manually.  Let's take some theoritical code, where we have to set a global
struct char_data pointer named 'g_westGeneral' to a character.  If the
pointer is already set, we need to inform the previous West General that
he has been replaced.  If there's no general, we just set the new
character:

    struct char_data *g_westGeneral;

    void
    SetWestGeneral (struct char_data *ch)
    {
        if (g_westGeneral) {
            send_to_char("You are no longer the West General!\r\n",
                         g_westGeneral);
            g_westGeneral->flags &= ~CHAR_WEST_GENERAL;
        }

        g_westGeneral = ch;
        ch->flags |= CHAR_WEST_GENERAL;
        send_to_char("You are now the West General!\r\n", ch);
    }

This code will crash the MUD.  It doesn't work because we haven't set
g_westGeneral to any value and C doesn't initialize variables for you so
g_westGeneral is NOT NULL.  That means "if (g_westGeneral)" is TRUE the
first time we use SetWestGeneral(), even though there's no actual
g_westGeneral.  When we attempt to inform the old general, who's
nonexistent, of his demotion, we crash.  There's no useful way to test the
validity of a pointer in this circumstance, and even if there were it
would be so much more practical to first initialize the g_westGeneral
pointer and never have to bother with it.

Note that this is also why people set pointers back to NULL even after
calling free() on them.  free() does not change the address the pointer is
pointing to, only the memory at that address.  This means that if on a
theoritical 16 bit computer we have a pointer to the address 0x054A, and
call free() on it, the pointer's "value" is still 0x054A, just the memory
at 0x054A is no longer valid.  To use our above example, we could
introduce a function like,

    void
    RemoveWestGeneral (void)
    {
        if (!g_westGeneral) return;
        free(g_westGeneral);
        g_westGeneral = NULL;
    }

Note that without the last line in the body of the function, the next call
to SetWestGeneral() would crash the MUD because g_westGeneral, although it
is not NULL, is an invalid pointer (i.e., it points to memory that our
process doesn't currently own).

> or even with structs (struct char_data *me as opposed to struct char_data
> *me = NULL).

As a general rule, a pointer is a pointer, regardless of its type.  All
pointers are 4 bytes on 32 bit computers (because, of course, an address
on a 32 bit computer is 32 bits long, or 4 bytes).  Thus, the compiler
does not treat, "char *temp = NULL;" any differently than it
treats, "struct char_data *ch = NULL;".

-dak


     +------------------------------------------------------------+
     | Ensure that you have read the CircleMUD Mailing List FAQ:  |
     |  http://qsilver.queensu.ca/~fletchra/Circle/list-faq.html  |
     +------------------------------------------------------------+



This archive was generated by hypermail 2b30 : 12/15/00 PST