tags:

views:

199

answers:

5

Consider this code:

 char* foo(int myNum) {
    char* StrArray[5] = {"TEST","ABC","XYZ","AA","BB"};

    return StrArray[4];
 }

When I return StrArray[4] to the caller, is this supposed to work? Since the array is defined on the stack, when the caller gets the pointer, that part of memory has gone out of scope. Or will this code work?

+8  A: 

This code will work. You are returning the value of the pointer in StrArray[4], which points to a constant string "BB". Constant strings have a lifetime equal to that of your entire program.

The important thing is the lifetime of what the pointer points to, not where the pointer is stored. For example, the following similar code would not work:

char* foo(int myNum) {
   char bb[3] = "BB";
   char* StrArray[5] = {"TEST","ABC","XYZ","AA",bb};

   return StrArray[4];
}

This is because the bb array is a temporary value on the stack of the foo() function, and disappears when you return.

Greg Hewgill
Isn't it returning a char * to the character array, StrArray[4] ? Correct me, if I am wrong.
Amit
@Amit: You are incorrect, the original question is returning a pointer to whatever StrArray[4] points to, which is "BB".
Greg Hewgill
@Greg: Thanks, I understand the explanation you gave.
Amit
As an additional note - in C,a string literal have static storage duration (it'll exist until the end of the application..). The array is gone at the end of the function scope here - but the string literals are not
nos
A mandatory pedantic remark :) : `bb` in an aggregate initializer would only be allowed in C99, but not in C89/90. The latter only allows constant expressions in aggregate initializers, which the above `bb` is not.
AndreyT
@AndreyT: True, I could have done a two-step `char bb[3]; strcpy(bb, "BB");` but I didn't want to obscure the point of the example with extra code.
Greg Hewgill
Greg's example helped me better understand this scope of the string literal. Thanks...
Jitesh
It should also be worth mentioning that using non-const string literals is deprecated. `StrArray` should be declared as `const char *StrArray[5]`, and `foo()` should return `const char*`.
Adam Rosenfield
@Amit: give also a look to [this][link] SO question which expands nos' comment above. [link]: http://stackoverflow.com/questions/349025/is-a-string-literal-in-c-created-in-static-memory
Francesco
@Greg Hewgill: There's no problem with initialization of `bb` itself - it fine even for C89/90. I was talking about initialization of `StrArray`. `char* StrArray[] = { bb };` is illegal in C89/90.
AndreyT
Oh, right, that's fair. Still, my point about not obscuring the example remains. :)
Greg Hewgill
A: 

C uses arrays with indicies beginning at 0. So the first element is StrArray[0]

Thus StrArray[5] was not declared in your code.

C will allow you to write code to return StrArray[5] but wht happens is undefined and will differ on OS and compiler but often will crash the program.

Mark
+1  A: 

The code will work. The point you are returning (StrArray[4]) points to a string literal "BB". String literals in C are anonymous array objects with static storage duration, which means that they live as long as your program lives (i.e forever). It doesn't matter where you create that sting literal. Even if it is introduced inside a function, it still has static storage duration.

Just remember, that string literals are not modifiable, so it is better to use const char* pointers with string literals.

AndreyT
+3  A: 

Beware: you're lying to the compiler.

Each element of StrArray points to a read-only char *;
You're telling the compiler the return value of your function is a modifiable char *.
Lie to the compiler and it will get its revenge sooner or later.

In C, the way to declare a pointer to read-only data is to qualify it with const.

I'd write your code as:

const char* foo(int myNum) {
   const char* StrArray[5] = {"TEST","ABC","XYZ","AA","BB"};

   return StrArray[4];
}
pmg
In that specific example you could even take it one step further and make it `const char* const StrArray[5] = { /* whatever */ };` :))
AndreyT
A: 

Only the array of pointers is on the stack, not the string-literal-constants.

Clifford