Is initializing a char[] with a string literal bad practice?

  • I was reading a thread titled "strlen vs sizeof" on CodeGuru, and one of the replies states that "it's anyways [sic] bad practice to initialie [sic] a char array with a string literal."

    Is this true, or is that just his (albeit an "elite member") opinion?


    Here is the original question:

    #include <stdio.h>
    #include<string.h>
    main()
    {
        char string[] = "october";
        strcpy(string, "september");
    
        printf("the size of %s is %d and the length is %d\n\n", string, sizeof(string), strlen(string));
        return 0;
    }
    

    right. the size should be the length plus 1 yes?

    this is the output

    the size of september is 8 and the length is 9

    size should be 10 surely. its like its calculating the sizeof string before it is changed by strcpy but the length after.

    Is there something wrong with my syntax or what?


    Here is the reply:

    It's anyways bad practice to initialie a char array with a string literal. So always do one of the following:

    const char string1[] = "october";
    char string2[20]; strcpy(string2, "september");
    

    Note the "const" on the first line. Could it be that the author assumed c++ instead of c? In c++ it is "bad practice", because a literal should be const and any recent c++ compiler will give a warning (or error) about assigning a const literal to a non-const array.

    @André C++ defines string literals as const arrays, because that is the only safe way of dealing with them. That C *doesn't* is the problem, so you have a social rule that enforces the safe thing

    @Caleth. I know, I was more trying to argue that the author of the reply was approaching the "bad practice" from a c++ perspective.

    @André it isn't a bad practice in C++, because it *isn't a practice*, it's a straight up type error. It *should be* a type error in C, but it isn't, so you have to have a style guide rule telling you "It's forbidden"

  • John Bode

    John Bode Correct answer

    8 years ago

    It's anyways bad practice to initialie a char array with a string literal.

    The author of that comment never really justifies it, and I find the statement puzzling.

    In C (and you've tagged this as C), that's pretty much the only way to initialize an array of char with a string value (initialization is different from assignment). You can write either

    char string[] = "october";
    

    or

    char string[8] = "october";
    

    or

    char string[MAX_MONTH_LENGTH] = "october";
    

    In the first case, the size of the array is taken from the size of the initializer. String literals are stored as arrays of char with a terminating 0 byte, so the size of the array is 8 ('o', 'c', 't', 'o', 'b', 'e', 'r', 0). In the second two cases, the size of the array is specified as part of the declaration (8 and MAX_MONTH_LENGTH, whatever that happens to be).

    What you cannot do is write something like

    char string[];
    string = "october";
    

    or

    char string[8];
    string = "october";
    

    etc. In the first case, the declaration of string is incomplete because no array size has been specified and there's no initializer to take the size from. In both cases, the = won't work because a) an array expression such as string may not be the target of an assignment and b) the = operator isn't defined to copy the contents of one array to another anyway.

    By that same token, you can't write

    char string[] = foo;
    

    where foo is another array of char. This form of initialization will only work with string literals.

    EDIT

    I should amend this to say that you can also initialize arrays to hold a string with an array-style initializer, like

    char string[] = {'o', 'c', 't', 'o', 'b', 'e', 'r', 0};
    

    or

    char string[] = {111, 99, 116, 111, 98, 101, 114, 0}; // assumes ASCII
    

    but it's easier on the eyes to use string literals.

    EDIT2

    In order to assign the contents of an array outside of a declaration, you would need to use either strcpy/strncpy (for 0-terminated strings) or memcpy (for any other type of array):

    if (sizeof string > strlen("october"))
      strcpy(string, "october");
    

    or

    strncpy(string, "october", sizeof string); // only copies as many characters as will
                                               // fit in the target buffer; 0 terminator
                                               // may not be copied, but the buffer is
                                               // uselessly completely zeroed if the
                                               // string is shorter!
    

    @KeithThompson: not disagreeing, just added it for completeness' sake.

    Please note that `char[8] str = "october";` is bad practice. I had to literally char count myself to make sure it wasn't an overflow and it breaks under maintenance... e.g. correcting a spelling error from `seprate` to `separate` will break if size not updated.

    I agree with djechlin, it is bad practice for the reasons given. JohnBode's answer doesn't comment at all on the "bad practice" aspect (which is the main part of the question!!), it just explains what you can or cannot do to initialize the array.

    Minor: As 'length" value returned from `strlen()` does not include the null character, using `MAX_MONTH_LENGTH` to hold the maximum size needed for `char string[]` often _looks_ wrong. IMO, `MAX_MONTH_SIZE` would be better here.

License under CC-BY-SA with attribution


Content dated before 6/26/2020 9:53 AM