Proper way to initialize a string in C

后端 未结 11 1242
臣服心动
臣服心动 2021-02-01 08:23

I\'ve seen people\'s code as:

char *str = NULL;

and I\'ve seen this is as well,

char *str;

I\'m wonder, what

相关标签:
11条回答
  • 2021-02-01 09:23

    this is a general question about c variables not just char ptrs.

    It is considered best practice to initialize a variable at the point of declaration. ie

    char *str = NULL;
    

    is a Good Thing. THis way you never have variables with unknown values. For example if later in your code you do

    if(str != NULL)
     doBar(str);
    

    What will happen. str is in an unknown (and almost certainly not NULL) state

    Note that static variables will be initialized to zero / NULL for you. Its not clear from the question if you are asking about locals or statics

    0 讨论(0)
  • 2021-02-01 09:23

    Because free() doesn't do anything if you pass it a NULL value you can simplify your program like this:

    char *str = NULL;
    
    if ( somethingorother() )
    {
        str = malloc ( 100 );
    
        if ( NULL == str )
            goto error;
    }
    

    ...

    error:
    
    cleanup();
    free ( str );
    

    If for some reason somethingorother() returns 0, if you haven't initialized str you will free some random address anywhere possibly causing a failure.

    I apologize for the use of goto, I know some finds it offensive. :)

    0 讨论(0)
  • 2021-02-01 09:24
    I'm wonder, what is the proper way of initializing a string?

    Well, since the second snippet defines an uninitialized pointer to string, I'd say the first one. :)

    In general, if you want to play it safe, it's good to initialize to NULL all pointers; in this way, it's easy to spot problems derived from uninitialized pointers, since dereferencing a NULL pointer will yield a crash (actually, as far as the standard is concerned, it's undefined behavior, but on every machine I've seen it's a crash).

    However, you should not confuse a NULL pointer to string with an empty string: a NULL pointer to string means that that pointer points to nothing, while an empty string is a "real", zero-length string (i.e. it contains just a NUL character).

    char * str=NULL; /* NULL pointer to string - there's no string, just a pointer */
    const char * str2 = ""; /* Pointer to a constant empty string */
    
    char str3[] = "random text to reach 15 characters ;)"; /* String allocated (presumably on the stack) that contains some text */
    *str3 = 0; /* str3 is emptied by putting a NUL in first position */
    
    0 讨论(0)
  • 2021-02-01 09:25

    You're supposed to set it before using it. That's the only rule you have to follow to avoid undefined behaviour. Whether you initialise it at creation time or assign to it just before using it is not relevant.

    Personally speaking, I prefer to never have variables set to unknown values myself so I'll usually do the first one unless it's set in close proximity (within a few lines).

    In fact, with C99, where you don't have to declare locals at the tops of blocks any more, I'll generally defer creating it until it's needed, at which point it can be initialised as well.

    Note that variables are given default values under certain circumstances (for example, if they're static storage duration such as being declared at file level, outside any function).

    Local variables do not have this guarantee. So, if your second declaration above (char *str;) is inside a function, it may have rubbish in it and attempting to use it will invoke the afore-mentioned, dreaded, undefined behaviour.

    The relevant part of the C99 standard 6.7.8/10:

    If an object that has automatic storage duration is not initialized explicitly, its value is indeterminate. If an object that has static storage duration is not initialized explicitly, then:

    • if it has pointer type, it is initialized to a null pointer;
    • if it has arithmetic type, it is initialized to (positive or unsigned) zero;
    • if it is an aggregate, every member is initialized (recursively) according to these rules;
    • if it is a union, the first named member is initialized (recursively) according to these rules.
    0 讨论(0)
  • 2021-02-01 09:27

    Your first snippet is a variable definition with initialization; the second snippet is a variable definition without initialization.

    The proper way to initialize a string is to provide an initializer when you define it. Initializing it to NULL or something else depends on what you want to do with it.

    Also be aware of what you call "string". C has no such type: usually "string" in a C context means "array of [some number of] char". You have pointers to char in the snippets above.

    Assume you have a program that wants the username in argv[1] and copies it to the string "name". When you define the name variable you can keep it uninitialized, or initialize it to NULL (if it's a pointer to char), or initialize with a default name.

    int main(int argc, char **argv) {
        char name_uninit[100];
        char *name_ptr = NULL;
        char name_default[100] = "anonymous";
    
        if (argc > 1) {
            strcpy(name_uninit, argv[1]); /* beware buffer overflow */
            name_ptr = argv[1];
            strcpy(name_default, argv[1]); /* beware buffer overflow */
        }
    
        /* ... */
    
        /* name_uninit may be unusable (and untestable) if there were no command line parameters */
        /* name_ptr may be NULL, but you can test for NULL */
        /* name_default is a definite name */
    }
    
    0 讨论(0)
提交回复
热议问题