Thursday, January 27, 2011

Don't initialise local strings

Consider the following code:

void s(int i)
{
  char string[2048]="";
  sprinf(string,"Value = %i",i);
  printf("String = %s\n",string);
}

The C standards require that if any elements of the character array string are initialised, then all of them should be. We can demonstrate this by compiling with gcc:

$ gcc -O -S f.c
$ more f.s
        .file   "f.c"
...
        .type   s, #function
        .proc   020
s:
        save    %sp, -2160, %sp
        stx     %g0, [%fp-2064]
        add     %fp, -2056, %o0
        mov     0, %o1
        call    memset, 0
        mov    2040, %o2

You can see that explicitly initialising string caused all elements of string to be initialised with a call to memset(). Removing the explicit initialisation of string (the ="") avoids the call to memset().

2 comments:

  1. Anyway, the way of initialization depends on the implementation of the Compiler and that will change rapidly. GCC version 4.4.3 on Ubuntu has no this issue.

    ReplyDelete
  2. Interesting. Thanks for that information. I've dug out more details. Here's a link to a draft version of the C standard:
    http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1124.pdf

    Here's the part that deals with initialising strings:

    "If there are ... fewer characters in a string literal used to initialize an array of known size than there are elements in the array, the remainder of the aggregate shall be
    initialized implicitly the same as objects that have static storage duration."

    Here's how an object with static storage is initialised:

    "If an object that has static storage duration is not initialized explicitly, then:
    ...
    — if it has arithmetic type, it is initialized to (positive or unsigned) zero;"

    Which explains the current behaviour of initialising the string to zeros.

    ReplyDelete