3

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?

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Jitesh
  • 31
  • 1
  • I think it should be "When I return StrArray[4] .." –  Nov 09 '09 at 18:53
  • Hmm depends - it could be the OP meant StrArray[5] – mmmmmm Nov 09 '09 at 18:56
  • 2
    It is not related to your question, but in the example you are not using the myNum parameter which you are passing to foo. – Francesco Nov 09 '09 at 18:57
  • This works but I recommend against doing this. Define your constants somewhere else. Although, it depends on your situation, there might be a time when this is an ok design. Just think about it a little bit. – BobbyShaftoe Nov 09 '09 at 19:09

5 Answers5

8

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
  • 951,095
  • 183
  • 1,149
  • 1,285
  • Isn't it returning a char * to the character array, StrArray[4] ? Correct me, if I am wrong. –  Nov 09 '09 at 18:56
  • 3
    @Amit: You are incorrect, the original question is returning a pointer to whatever StrArray[4] points to, which is "BB". – Greg Hewgill Nov 09 '09 at 18:58
  • @Greg: Thanks, I understand the explanation you gave. –  Nov 09 '09 at 19:01
  • 2
    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 Nov 09 '09 at 19:03
  • 3
    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. – AnT stands with Russia Nov 09 '09 at 19:13
  • @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 Nov 09 '09 at 19:15
  • Greg's example helped me better understand this scope of the string literal. Thanks... – Jitesh Nov 09 '09 at 19:18
  • 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 Nov 09 '09 at 19:21
  • @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 Nov 09 '09 at 19:22
  • @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. – AnT stands with Russia Nov 09 '09 at 19:28
  • Oh, right, that's fair. Still, my point about not obscuring the example remains. :) – Greg Hewgill Nov 09 '09 at 19:29
4

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
  • 106,608
  • 13
  • 126
  • 198
2

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.

AnT stands with Russia
  • 312,472
  • 42
  • 525
  • 765
0

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.

mmmmmm
  • 32,227
  • 27
  • 88
  • 117
0

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

Clifford
  • 88,407
  • 13
  • 85
  • 165