R – C can someone tell me what is going on here

cfreemalloc

I can not figure out what the heck is happening here. What I expect is that the output should say that there is only 1 element in keys, it's saying there are 7 when I have allocated only the 0 position with 120 bytes.

void add2(char **b, char *i) {
    if (!i) {
        b[0] = (char*) malloc(120);
        sprintf(b[0], "%s", "hithere");
    } else {
        strcat(b[0], "\\\\");
        strcat(b[0], i);
    }
}

void add1(char **b) {
    add2(b, NULL);
    add2(b, "one");
    add2(b, "two");
    add2(b, "three");
}

void add() {
    char *keys[2];
    int i;
    add1(keys);
    fprintf(stderr, "%s\n", keys[0]);
    for (i = 0; keys[i]; i++)
        fprintf(stderr, "%d\n", i);
    free(keys[0]);
}

int main (int argc, char** argv)
{   
     add();
     add();
     return 255;
}

outputs:
hithere\one\two\three
0
1
2
3
4
5
6
7
hithere\one\two\three
0
1
2
3
4
5
6
7

the strings are as I expect them to be however i thought only 0 should be printed out after since 0 is the only element I added to. I need to be able to free each spot instead of just free[0] but when i put the free[i] in the for loop that prints out i it stack dumps.

with regard to initialization from response below, if i need an array that is like 1000 instead of 2 then how do i init them all to 0 without typing out 1,000 0's

Best Answer

/* ... */
void add() {
    char *keys[2];
/* ... */

keys is an array of 2 pointers to char, but it is not initialized.
Try this

/* ... */
void add() {
    char *keys[2] = {0, 0}; /* explicit initialization of the two elements */
/* ... */

In the absence of explicit initializers for all members, the uninitialized ones are initialized to zero (the right zero for their type).

/* ... */
void add() {
    char *keys[1000] = {42}; /* explicit initialize the first element to 42 */
                             /* and implicitly initialize all other elements to 0 */
                             /* **ATTENTION** */
                             /* initializing a pointer to 42 is wrong */
                             /* I only wrote that as an example */
/* ... */

Edit, quote from the Standard

6.7.8 Initialization
Syntax
1

initializer:

assignment-expression
{ initializer-list }
{ initializer-list , }

initializer-list:

designationopt initializer
initializer-list , designationopt initializer

There is no syntax for an empty initializer-list.