开发者

C Duration of strings, constants, compound literals, and why not, the code itself

I didn't remember where I read, that If I pass a string to a function like.

char *string;
string = func ("heyapple!");
char *func (char *string) {
   char *p
   p = string;

return p; } printf ("%s\n", string);

The string pointer continue to be valid because the "heyapple!" is in memory, it IS in the code the I wrote, so it never will be take off, right?

And about constants like 1, 2.10, 'a'?

And compo开发者_如何学JAVAund literals?

like If I do it:

func (1, 'a', "string");

Only the string will be all of my program execution, or the constans will be too?

For example I learned that I can take the address of string doing it

&"string";

Can I take the address of the constants literals? like 1, 2.10, 'a'?

I'm passing theses to functions arguments and it need to have static duration like strings without the word static.

Thanks a lot.


This doesn't make a whole lot of sense.

Values that are not pointers cannot be "freed", they are values, they can't go away.

If I do:

int c = 1;

The variable 'c' is not a pointer, it cannot do anything else than contain an integer value, to be more specific it can't NOT contain an integer value. That's all it does, there are no alternatives.

In practice, the literals will be compiled into the generated machine-code, so that somewhere in the code resulting from the above will be something like

load r0, 1

Or whatever the assembler for the underlying instruction set looks like. The '1' is a part of the instruction encoding, it can't go away.


Make sure you distinguish between values and pointers to memory. Pointers are themselves values, but a special kind of value that contains an address to memory.

With char* hello = "hello";, there are two things happening:

  • the string "hello" and a null-terminator are written somewhere in memory
  • a variable named hello contains a value which is the address to that memory

With int i = 0; only one thing happens:

  • a variable named i contains the value 0

When you pass around variables to functions their values are always copied. This is called pass by value and works fine for primitive types like int, double, etc. With pointers this is tricky because only the address is copied; you have to make sure that the contents of that address remain valid.

Short answer: yes. 1 and 'a' stick around due to pass by value semantics and "hello" sticks around due to string literal allocation.


Stuff like 1, 'a', and "heyapple!" are called literals, and they get stored in the compiled code, and in memory for when they have to be used. If they remain or not in memory for the duration of the program depends on where they are declared in the program, their size, and the compiler's characteristics, but you can generally assume that yes, they are stored somewhere in memory, and that they don't go away.

Note that, depending on the compiler and OS, it may be possible to change the value of literals, inadvertently or purposely. Many systems store literals in read-only areas (CONST sections) of memory to avoid nasty and hard-to-debug accidents.

For literals that fit into a memory word, like ints and chars it doesn't matter how they are stored: one repeats the literal throughout the code and lets the compiler decide how to make it available. For larger literals, like strings and structures, it would be bad practice to repeat, so a reference should be kept.

Note that if you use macros (#define HELLO "Hello!") it is up to the compiler to decide how many copies of the literal to store, because macro expansion is exactly that, a substitution of macros for their expansion that happens before the compiler takes a shot at the source code. If you want to make sure that only one copy exists, then you must write something like:

#define HELLO "Hello!"
char* hello = HELLO;

Which is equivalent to:

char* hello = "Hello!";

Also note that a declaration like:

const char* hello = "Hello!";

Keeps hello immutable, but not necessarily the memory it points to, because of:

char h = (char) hello; h[3] = 'n';

I don't know if this case is defined in the C reference, but I would not rely on it:

char* hello = "Hello!"; char* hello2 = "Hello!"; // is it the same memory?

It is better to think of literals as unique and constant, and treat them accordingly in the code.

If you do want to modify a copy of a literal, use arrays instead of pointers, so it's guaranteed a different copy of the literal (and not an alias) is used each time:

char hello[] = "Hello!";

Back to your original question, the memory for the literal "heyapple!" will be available (will be referenceable) as long as a reference is kept to it in the running code. Keeping a whole module (a loadable library) in memory because of a literal may have consequences on overall memory use, but that's another concern (you could also force the unloading of the module that defines the literal and get all kind of strange results).


First,it IS in the code the I wrote, so it never will be take off, right? my answer is yes. I recommend you to have a look at the structure of ELF or runtime structure of executable. The position that the string literal stored is implementation dependent, in gcc, string literal is store in the .rdata segment. As the name implies, the .rdata is read-only. In your code

   char *p
   p = string;

the pointer p now point to an address in a readonly segment, so even after the end of function call, that address is still valid. But if you try to return a pointer point to a local variable then it is dangerous and may cause hard-to-find bugs:

int *func () {
    int localVal = 100;
    int *ptr = localVal;
    return p;
}
int val = func ();
printf ("%d\n", val);

after the execution of func, as the stack space of func is retrieve by the c runtime, the memory address where localVal was stored will no longer guarantee to hold the original localVal value. It can be overidden by operation following the func.

Back to your question title

-

  1. string literal have static duration.
  2. As for "And about constants like 1, 2.10, 'a'?" my answer is NO, your can't get address of a integer literal using &1. You may be confused by the name 'integer constant', but 1,2.10,'a' is not right value ! They do not identify a memory place,thus, they don't have duration, a variable contain their value can have duration
  3. compound literals, well, I am not sure about this.
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜