1

I have a function named 'Address':

template <class Variable> unsigned long Address(Variable *X){
    return (unsigned long &) X;
}

This function returns address of given argument. Even given argument is not a variable, it's returns a value and when i point this value to another pointer, i can access the value.

When i'm playing with this function, i see this function always return same value on non-variable (like "Hello world!") argument.

cout << "Address (?) of 'Hello world!' :" << Address("Hello world!") << "\n";

And

cout << "Address (?) of 'Hello world' :" << Address("Hello world") << "\n";

are gives same output. But when i try

cout << "Address (?) of 'Hello world!' :" << Address("Hello world!") << "\n";
cout << "Address (?) of 'Hello world!' :" << Address("Hello world") << "\n";

do this in same file, outputs are different.

What is why of this?

A. Ite
  • 151
  • 1
  • 7

2 Answers2

4

The address of a string literal is completely compiler-dependent. In your case, your two separate programs each compile a single* string literal argument and wind up giving it the same address. In the single-program example, there are two separate literals which get two separate addresses.

When a compiler encounters a string literal, it sets aside room in the binary output file for it (sometimes called the "data segment"). This is a place in the binary file specifically for data instead of executable code. Depending on the decisions the compiler makes, it may choose different places inside the file. But, because the data is inside the file, its address will always be the same every time it is run.

In your first example, you have two different binary files that each have just one string literal, and the compiler happened to make the same decision about where to place the string, so they both give the same answer.

In the second example, you have a single binary file with two different string literals inside it, so of course they have separate addresses.

*Technically there are two and four literals, respectively; I'm focusing on the literals being used as arguments to the function.

Brian A. Henning
  • 1,374
  • 9
  • 24
  • what do you mean when saying compiler-dependent? – A. Ite Jun 20 '16 at 18:13
  • You should do some research and learn how "string literals" work in c++ code. In brief, a string literal is placed in the data segment of a compiled program, and will always have the same address every time the program is run because it is part of the binary file that the compiler creates. The compiler decides where inside the file to place the string. That is different from a variable or heap object, where the OS decides at run time where to place it. – Brian A. Henning Jun 20 '16 at 18:17
  • "Compiler-dependent" means that different compilers, or even the same compiler with different options, may place the string data in a different location inside the binary file. – Brian A. Henning Jun 20 '16 at 18:17
3

C++ places the content of your strings into memory in an implementation-defined way. Typically, all strings of your program would be placed in a segment of memory back-to-back, with '\0' terminators marking their ends. The actual placement depends primarily on the compiler, but also on the presence of other constants that may be placed before the one the address of which you are printing.

That is why the comparison of addresses coming from different programs is meaningless. The compiler is free to place the representation of your string literal at any location.

For example, the address may change as the result of adding another string literal to your program. The address printed by this code

cout << addr("Hello, world!") << endl;

and this code

cout << "Here is the address: " << addr("Hello, world!") << endl;

are different, even though the constant is the same (demo 1, demo 2).

Addresses of different string literals coming from the same program, however, are guaranteed to be different. Moreover, string literals with identical content may have multiple addresses if translation units are compiled separately and then linked into a single program.

Note: Do not cast to unsigned long, it is not guaranteed to work. Use uintptr_t instead.

Community
  • 1
  • 1
Sergey Kalinichenko
  • 714,442
  • 84
  • 1,110
  • 1,523