Stack query

N

Ned

char *foo(int idx)
{
switch (idx)
{
case 0:return "Hello";
case 1:return "Goodbye";
}
return "world";
}
Newby question.

I asked another question a few weeks ago about something similar. At that
time I wondered whether the memory allocated by a similar function for the
returned strings was ever disposed of during the lifetime of the program and
was told it wouldn't be.
I'd spotted some code like this in our application and wanted to get my
facts right before suggesting changes so that the fn returned pointers to
const char*s defined elsewhere.

Im just wondering about stacks. Was this memory allocated on the stack
(there's no heap available on our end system so I assume so)? If so, and
this memory's not removed, then how will the stack push and pops work for
items placed in the stack before the string?

(Ive no idea if this is a true ansii c question. Please dont tell me off if
it isnt, or at least point me nicely in a direction of a ng that can)

thanks
 
D

Derk Gwen

# char *foo(int idx)
# {
# switch (idx)
# {
# case 0:return "Hello";
# case 1:return "Goodbye";
# }
# return "world";
# }

# Im just wondering about stacks. Was this memory allocated on the stack

String literals are allocated statickally. This code is the same as

char *foo(int idx) {
static char A[] = "Hello";
static char B[] = "Goodbye";
static char C[] = "world";
switch (idx) {
case 0: return A;
case 1: return B;
}
return C;
}
 
N

Ned

# Im just wondering about stacks. Was this memory allocated on the stack

String literals are allocated statickally. This code is the same as

char *foo(int idx) {
static char A[] = "Hello";
static char B[] = "Goodbye";
static char C[] = "world";
switch (idx) {
case 0: return A;
case 1: return B;
}
return C;
}

Thanks Derk, that makes far more sense!
 
C

Chris Torek

# char *foo(int idx)
# {
# switch (idx)
# {
# case 0:return "Hello";
# case 1:return "Goodbye";
# }
# return "world";
# }

# Im just wondering about stacks. Was this memory allocated on the stack

(It is not really clear what "this" memory is supposed to refer to,
although as it turns out, the most obvious guess -- the memory
holding the text of the string literals -- is what Ned meant.)

String literals are allocated statickally. This code is the same as

char *foo(int idx) {
static char A[] = "Hello";
static char B[] = "Goodbye";
static char C[] = "world";
switch (idx) {
case 0: return A;
case 1: return B;
}
return C;
}

It is indeed "the same" with respect to storage duration. It is,
however, different in some other respects:

- The original version has three anonymous arrays, rather than
three named arrays. The new version has named arrays (A, B,
and C) whose names are visible inside foo(). This change is
unlikely to matter.

- The anonymous arrays in the original may or may not (at the
compiler's discretion) be placed in read-only memory. If so,
this has much the same effect as if the named arrays were "static
const char A[]" and so on. The *type* of the anonymous arrays
is "array N of char" but the storage itself *may* be read-only.
C does this rather bizarre thing mainly for historical reasons
("const" did not exist before C89). This change might well
matter, because it means that:

char *p = foo(n);
p = new_value;

is invalid in the original, but valid in the replacement.

- Finally, the contents of the anonymous arrays in the original
may or may not (again at the compiler's discretion) be shared
with other string literals, while the contents of the named
arrays in the replacement are certainly not shared. Again, this
change might well matter. Given the replacement code, and a
(valid) assignment to p as in the second difference above,
a later call to the replacement foo() will return the modified
string, but no other strings in the program will be modified.
On the other hand, if the compiler chooses not to place string
literals in read-only memory, yet *does* share string literals,
then something like the code below might produce the output
shown below (although technically the effect is undefined):

char *p = foo(0);
p[0] = 'J';
printf("I expect Jello here: %s\n", p);
printf("And here we print %s\n", "Hello");

[output]

I expect Jello here: Jello
And here we print Jello

In short, using an actual explicit array (of type "char [N]") has
the fundamentally different property of being a known, separate,
well-behaved ordinary array, which you can modify with predictable
behavior. Using the anonymous array (of type char [N]) produced
by a string literal gives you an array that *may* be read-only and
*may* share storage with other string literals in the program.
The storage duration is the same, but the accessibility and uniqueness
may change. As long as you do not attempt to overwrite string
literals -- in effect, treating them as arrays of "const char" --
this will not matter. In that respect, it would be nice if string
literals had type "const char [N]", but since "const" is rather
broken in C, and did not exist before 1989, they cannot have such
a type.
 
D

Derk Gwen

# - The anonymous arrays in the original may or may not (at the
# compiler's discretion) be placed in read-only memory. If so,
# this has much the same effect as if the named arrays were "static
# const char A[]" and so on. The *type* of the anonymous arrays
# is "array N of char" but the storage itself *may* be read-only.

Primal scope is primal scope regardless of the page protection. Since the
question was about scope and not about read/write protections, why drag
in extraneous issues? The programs are still the same with respect to the
question asked.
 
M

Mark Gordon

# char *foo(int idx)
# {
# switch (idx)
# {
# case 0:return "Hello";
# case 1:return "Goodbye";
# }
# return "world";
# }

# Im just wondering about stacks. Was this memory allocated on the
stack

String literals are allocated statickally. This code is the same as

char *foo(int idx) {
static char A[] = "Hello";
static char B[] = "Goodbye";
static char C[] = "world";
switch (idx) {
case 0: return A;
case 1: return B;
}
return C;
}

It isn't the same. The compiler is at liberty to only have one string
"Goodbye" however many times you use the literal "Googbye" in your
program. However, with static arrays each one is a separate object.
e.g.

markg@heather markg $ cat t.c
#include <stdio.h>
char *fun1(void) { return "Hello"; }
char *fun2(void) { return "Hello"; }
int main(void)
{
static char A[]="Hello";
static char B[]="Hello";
if (A==B) fprintf(stderr,"Somethings gone drastically wrong!\n");
if (fun1()==fun2()) printf("Same string literal used, but OK\n");
return 0;
}
markg@heather markg $ gcc -ansi -pedantic -Wall -O t.c
markg@heather markg $ ./a.out
Same string literal used, but OK
markg@heather markg $
 
E

Emmanuel Delahaye

Ned said:
char *foo(int idx)
{
switch (idx)
{
case 0:return "Hello";
case 1:return "Goodbye";
}
return "world";
}

This code is valid. I suggest a better implementation :

char const *foo (int idx)
{
switch (idx)
{
case 0:
return "Hello";
case 1:
return "Goodbye";
}
return "world";
}

Because the pointed memory doesn't have to be modifiable.
I'd spotted some code like this in our application and wanted to get my
facts right before suggesting changes so that the fn returned pointers
to const char*s defined elsewhere.

Agreed.
Im just wondering about stacks. Was this memory allocated on the stack

What does have to do with your code? BTW, the C-language doesn't define the
word 'stack'. It's an implementation issue.

FWI, the string literals are allocated statically, and have a program-life
duration.
 
B

bd

char *foo(int idx)
{
switch (idx)
{
case 0:return "Hello";
case 1:return "Goodbye";
}
return "world";
}
Newby question.

I asked another question a few weeks ago about something similar. At that
time I wondered whether the memory allocated by a similar function for the
returned strings was ever disposed of during the lifetime of the program and
was told it wouldn't be.
I'd spotted some code like this in our application and wanted to get my
facts right before suggesting changes so that the fn returned pointers to
const char*s defined elsewhere.

Im just wondering about stacks. Was this memory allocated on the stack
(there's no heap available on our end system so I assume so)? If so, and
this memory's not removed, then how will the stack push and pops work for
items placed in the stack before the string?

First, C does not define a 'stack'. A 'stack' is one efficient way of
implementing local variables, but there are other legal ways. That said,
string literals are (somehow) allocated at program startup, and (somehow)
deallocated at program exit. Note that modifying a string literal invoked
undefined behavior.

If you place at file scope:
const char *foo = "bar";

Then the string literal is allocated in the same way as in your original
code - but you need to store the pointer as well.
 
C

Chris Torek

using string literals was not, in fact, "the same" as one using
named, string-literal-initialized, static-duration block-scope char
arrays. (This was in response to previous articles whose referents
were deleted by some sort of unusual posting software. This software
also apparently uses the nonstandard "#" quoting convention below.)

# - The anonymous arrays in the original may or may not (at the
# compiler's discretion) be placed in read-only memory. If so,
# this has much the same effect as if the named arrays were "static
# const char A[]" and so on. The *type* of the anonymous arrays
# is "array N of char" but the storage itself *may* be read-only.

Primal scope is primal scope regardless of the page protection. Since the
question was about scope and not about read/write protections, why drag
in extraneous issues? The programs are still the same with respect to the
question asked.

Actually, the question was probably about storage durations, not
scope. You -- Derk Gwen -- then made a blanket "same as" claim,
without qualifying it. Since the original question was not terribly
well specified, your answer might be interpreted by many readers
as "the same in all respects".

In other words, I believe I can argue that it was you, not I, who
"drag[ged] in extraneous issues", by leaving out qualifying conditions
in the statement:
This code is the same as [your example].

You may not think you "dragged them in", and you may not have
intended to do so, but I believe that others who read your article
may have taken the wrong message, namely, "same in all respects"
instead of "same in one respect". Given the technical nature of
this newsgroup (and the pedantic nature of many regulars here,
including myself :) ), you should have expected this sort of
followup.
 
D

Derk Gwen

# Actually, the question was probably about storage durations, not
# scope. You -- Derk Gwen -- then made a blanket "same as" claim,

My apologies.

I didn't realise you were another asshole. You needn't worry about me bothering
you again.
 
C

Chris Dollin

Derk said:
# Actually, the question was probably about storage durations, not
# scope. You -- Derk Gwen -- then made a blanket "same as" claim,

My apologies.

I didn't realise you were another asshole. You needn't worry about me
bothering you again.

Goshwow.

One hundred /and/ eighty.

*plonk*
 
C

CBFalconer

Derk said:
# Actually, the question was probably about storage durations, not
# scope. You -- Derk Gwen -- then made a blanket "same as" claim,

My apologies.

I didn't realise you were another asshole. You needn't worry about
me bothering you again.

Having been absent over a month, and seeing some sane responses
from you quoted, albeit still using the foolish non-standard quote
marks, I unplonked you yesterday. I now see that my judgement was
seriously flawed. re-PLONK.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
474,077
Messages
2,570,566
Members
47,202
Latest member
misc.

Latest Threads

Top