tags:

views:

240

answers:

4

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

+3  A: 

You haven't initialized the keys array, so it contains whatever happened to be in memory. keys[1] and on up to 7 weren't zero in that instance.

David
+4  A: 
/* ... */
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.

pmg
Okay so lets say I don't know how many elements I need? would I do char **keys; and then use malloc?
see my edit at bottom
See my edit at bottom :)
pmg
whats difference between that and memset(keys, '\0', sizeof(keys))?
You could just use "char *keys[SIZE] = {};" to get around typing a 5-line comment
Sean
My compiler tells me "warning: ISO C forbids empty initializer braces". I tried to get the proper reference out of the Standard, but didn't find it.
pmg
Oh, right this is C not C++ ... well, why not use {0} then?
Sean
+1  A: 

For the second part of question,

If u need to initialize an array that is like 1000 instead of 2 then use the following

char *keys[1000] = {0};

If u initialize one element of array with a value, then all other members of array will be automatically initialized to zero.

ie, if u use char *keys[1000] = {42}; then first member of array will be initialized to 42 and all other members of array will be automatically initialized to zero.

Byju
what about memset(keys, '\0', sizeof(keys))? is there any difference?
There is a difference if it's an array of `float`, for example. Using `{}` will initialize to `0` (or `0.0`, or null pointer value), which isn't always the same as all bits 0.
Pavel Minaev
Also, you don't have to write `={0}`. You can just write `={}`.
Pavel Minaev
+1  A: 

What's the difference between implicitly initializing array elements to 0 and explicitly setting them to 0 with memset()?

char *data[1000] = {0};
memset(data, 0, sizeof data);

The first option (implicit initialization) sets every element of the array to zero of the proper type; the second option sets all bits of all elements (plus any padding) to 0. Usually (99.99% of all current computers) there is no difference between a typed 0 and all bits 0.

Imagine a computer with segmented memory ... where a pointer is composed of two parts. When you set it to 0 (the right type of 0) the compiler can make that 0 different than all bits 0. If you specifically set all bits to 0, you might end up with an invalid pointer.

void *test = 0; /* can make test something like "0xC0DE:0x0000" */
memset(test, 0, sizeof test); /* will make test as "0x0000:0x0000" */
pmg
They say that 99% of statistics are made up on the spot. ;)
San Jacinto
For all integral types (including `char`), ISO C and C++ actually guarantee that "all bits 0" is the value 0 (though converse is not true: value 0 needs not be "all bits 0" - in case of sign-bit representation, which is legal, either one of +0 and -0 will have one bit not zero). So make it 100%.
Pavel Minaev