behzad.nouri
behzad.nouri

Reputation: 77941

address of local variable

I have a hard time understanding the difference between these three:

const char * f() {
  return "this is a test";
}

const char * g() {
  const char * str = "test again";
  return str;
}

const double * h() {
  const double a = 2.718;
  return &a;
}

I get a warning for the h(), as warning: address of local variable ‘a’ returned. Which makes sense, but I do not understand why the compiler (gcc -Wall) is ok with the f() and g() function.

Upvotes: 3

Views: 2682

Answers (7)

Grzegorz
Grzegorz

Reputation: 3335

These strings are physically and permanently placed inside your data memeory, so their addresses are permanent. The automatic variable is on the stack, so it will disappear the moment you return from the call.

Upvotes: 0

pb2q
pb2q

Reputation: 59607

In the function h, a is a local variable that won't exist after the function returns. You're returning a pointer to that variable, and so dereferencing the pointer outside the function is incorrect, and undefined behavior.

In f and g you're returning literal strings. Literal strings have static storage: they aren't allocated on the stack, and they'll exist beyond the lifetime of the functions.

In the definition of g:

const char *g()
{
   const char *str = "test again";
   return str;
}

str is a local variable, but it's a pointer to non-local - statically allocated - memory. It's that address that you're returning, not a reference to the local variable.

Consider another definition of g:

const char *g()
{
    const char str[] = "test again";
    // incorrect: can't use str after the return:
    return str;
}

Now g has the same problem as your function h, and when compiling it you should see the same warning about returning the address of a local variable.

Upvotes: 1

Keith Randall
Keith Randall

Reputation: 23265

String literals are not stored in the local stack frame. They live in a fixed place in your executable. Contrast:

const char * g() {
  const char * p = "test again";
  return p;
}

with

const char * g() {
  const char a[] = "test again";
  return a;
}

In the former, the return value points to a fixed place in your executable. In the latter, the return value points to (a now invalid location in) the stack.

Upvotes: 8

Sarfaraz Nawaz
Sarfaraz Nawaz

Reputation: 361254

const char * g() {
  const char * str = "test again";
  return str;
}

This doesn't return the address of local variable. The variable is str, and therefore it address should be &str which would be different from str itself:

std::cout << (void*) str  << std::endl; 
std::cout << (void*) &str << std::endl; //address of str (local variable)

They would print different values!

So a more apt example would be this:

const char ** g() {
  const char * str = "test again";
  return &str;  //difference!
}

Now it returns the address of the local variable. A good compiler may issue warning for this.

Another example would be this:

const char * g() {
  const char str[] = "test again"; //difference!
  return str;  //same as before
}

Now even though you return str which doesn't seem to be the address of the local variable, it may give warning, as in this case, the value of str and &str would be exactly same! Try printing these now:

std::cout << (void*) str  << std::endl; 
std::cout << (void*) &str << std::endl; //address of str (local variable)

They would print the same value!

Upvotes: 3

Dirk Holsopple
Dirk Holsopple

Reputation: 8831

The string literals aren't local variables. The string equivalent of the third function is this

const char * f() {
  const char str[] = "this is a test";
  return str;
}

Upvotes: 1

anio
anio

Reputation: 9161

Storage allocation for string literals is static, that is why you don't get a warning.

Try this and you will get undefined behavior:

const char* getFoo()
{

  std::string foo("hi");
  return foo.c_str();
}

Because the string foo made a copy of the literal string.

Upvotes: 0

ForEveR
ForEveR

Reputation: 55887

It's string literals.

n3337 2.14.5/8

Ordinary string literals and UTF-8 string literals are also referred to as narrow string literals. A narrow string literal has type “array of n const char”, where n is the size of the string as defined below, and has static storage duration

Upvotes: 6

Related Questions