String pointers and string arrays

S

santosh

In following code
char str[] = "asdf" ;
str[0] = 's' ;
is possible.

But char *str = "asdf" ;
str[0] = 's' ;
is an run-time error.

What i understand is *str = "asdf" is stored in Read-only-Memory. Where
as str[] is stored in stack.

Does any body has any better explanation for that?
 
T

tmp123

santosh said:
In following code
char str[] = "asdf" ;
str[0] = 's' ;
is possible.

But char *str = "asdf" ;
str[0] = 's' ;
is an run-time error.

What i understand is *str = "asdf" is stored in Read-only-Memory. Where
as str[] is stored in stack.

Does any body has any better explanation for that?

str[] is a copy of the data "asdf"
*str points to "asdf" itself.
 
?

=?ISO-8859-1?Q?=22Nils_O=2E_Sel=E5sdal=22?=

tmp123 said:
santosh said:
In following code
char str[] = "asdf" ;
str[0] = 's' ;
is possible.

But char *str = "asdf" ;
str[0] = 's' ;
is an run-time error.

What i understand is *str = "asdf" is stored in Read-only-Memory. Where
as str[] is stored in stack.

Does any body has any better explanation for that?

str[] is a copy of the data "asdf"
*str points to "asdf" itself.

And in addition to that, it's undefined behavior to modify
a string litteral - which is what he did in the pointer
case.
 
C

Chris Dollin

santosh said:
In following code
char str[] = "asdf" ;
str[0] = 's' ;
is possible.

But char *str = "asdf" ;
str[0] = 's' ;
is an run-time error.

.... on some implementations ...
What i understand is *str = "asdf" is stored in Read-only-Memory. Where
as str[] is stored in stack.

Does any body has any better explanation for that?

It is Not Allowed to update string literals, so if you do it, anything
may happen. Some machines will crash, some will alter the literal, some
will overwrite [pseudo] random memory, some will write libellous emails
to your local head of state.

Some implementations have a stack, but `str[]` need not be on it.
Some implementations have read-only memory, but "" need not be in it.

But it is Not Allowed to update string literals.
 
R

Roka100

As you said I did a test of memory access:

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <malloc.h> /* ptrdiff_t */
#include <alloca.h> /* only test alloca */
#include <string.h>

extern void afunc(void);

int bss_var; /* Auto init to 0 ,should be in BSS */
int data_var = 42; /* Init is not 0, should be in Data Sigment */

int main(int argc,char **argv){
char *p,*b,*nb;
char *str ="aaa";
char s[] = "aaa";
char *pt =NULL;

pt = (char *)malloc(sizeof(char *) * 5);

strcpy(pt,"aaa");

printf("Text locations:\n");
printf("\tAddress of main:%p\n",main);
printf("\tAddress of afunc:%p\n",afunc);

printf("Stack Locations:\n");
afunc();

p = (char *)alloca(32);
if(p != NULL){
printf("\tStart of alloca()'ed array : %p\n",p);
printf("\tEnd of alloca()'ed array : %p\n",p+31);
}

printf("Data Locations:\n");
printf("\tAddress of data_var : %p\n", & data_var);

printf("BSS Locations:\n");
printf("\tAddress of bss_var : %p\n", & bss_var);

b = sbrk((ptrdiff_t) 32); /* increase mem size */
nb = sbrk((ptrdiff_t) 0); /* get mem end address */
printf("Heap Locations: \n");
printf("\tInitial end of heap: %p\n",b);
printf("\tNew end of heap: %p\n",nb);

b = sbrk((ptrdiff_t) -16); /* decrease mem size */
nb = sbrk((ptrdiff_t) 0);
printf("\tFinal end of heap : %p\n",nb);

printf("str:%p\n",str);
printf("s:%p\n",s);
printf("pt:%p\n",pt);
return 0;
}

void afunc(void){
static int level = 0;
auto int stack_var;

if(++level == 5){
return;
}
printf("\tStack level %d: address of stack_var: %p\n",level, &
stack_var);

afunc(); /* cycle */
}
-----------------------------------------------
And result is:

Text locations:
Address of main:0x80483c4
Address of afunc:0x80485a8
Stack Locations:
Stack level 1: address of stack_var: 0xbfffe124
Stack level 2: address of stack_var: 0xbfffe114
Stack level 3: address of stack_var: 0xbfffe104
Stack level 4: address of stack_var: 0xbfffe0f4
Start of alloca()'ed array : 0xbfffe110
End of alloca()'ed array : 0xbfffe12f
Data Locations:
Address of data_var : 0x804989c
BSS Locations:
Address of bss_var : 0x80499a8
Heap Locations:
Initial end of heap: 0x804b000
New end of heap: 0x804b020
Final end of heap : 0x804b010

str:0x80486c0
s:0xbfffe134
pt:0x8049a00
-----------------------------------------------------------------------------------

If you want to do that I guess source will be :

#include <stdio.h>
#include <string.h>

int main(void){
char *str = NULL;

str = (char *)malloc(sizeof(char *)*5);
strcpy(str,"abcd");
str[0] = 's' ;

printf("%s\n",str);
free(str);
return 0;
}
In following code
char str[] = "asdf" ;
str[0] = 's' ;
is possible.

But char *str = "asdf" ;
str[0] = 's' ;
is an run-time error.

What i understand is *str = "asdf" is stored in Read-only-Memory. Where
as str[] is stored in stack.

Does any body has any better explanation for that?
 
A

Arndt Jonasson

santosh said:
In following code
char str[] = "asdf" ;
str[0] = 's' ;
is possible.

But char *str = "asdf" ;
str[0] = 's' ;
is an run-time error.

What i understand is *str = "asdf" is stored in Read-only-Memory. Where
as str[] is stored in stack.

Does any body has any better explanation for that?

Where they are stored, and whether the program is allowed to change
them according to C semantics, and whether it can actually do so, are
different things. Consider the keywords "static" and "const" too.

Some compilers can give you warnings when you try to change values
illegally:

int main()
{
char s1[] = "asfd";
const char s2[] = "asfd";
static char s3[] = "asfd";
static const char s4[] = "asfd";

s1[0] = 'b';
s2[0] = 'b'; /* line 9 */
s3[0] = 'b';
s4[0] = 'b'; /* line 11 */

return 0;
}

% gcc -c const.c
const.c: In function `main':
const.c:9: warning: assignment of read-only location
const.c:11: warning: assignment of read-only location
 
S

stathis gotsis

santosh said:
In following code
char str[] = "asdf" ;
str[0] = 's' ;
is possible.

That means: str is an array of char, its length is 4 and it is initialized
to "asdf". Initial value can be changed later on.
But char *str = "asdf" ;
str[0] = 's' ;
is an run-time error.

That means: str points to the string literal "asdf". So what you are trying
to to is something like: "asdf"[0]='s'; I do not think that is generally
allowed.
 
C

CBFalconer

As you said I did a test of memory access:

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

Not a standard include file
#include <malloc.h> /* ptrdiff_t */

Not a standard include file. ptrdiff_t is defined in stddef.h.
#include <alloca.h> /* only test alloca */

Not a standard include file

Please do not post non-standard code here. It is off-topic. Also,
please do not top-post. Your reply should follow, or be intermixed
with, the material you quote (after snipping of non-relevant
material).

--
"If you want to post a followup via groups.google.com, don't use
the broken "Reply" link at the bottom of the article. Click on
"show options" at the top of the article, then click on the
"Reply" at the bottom of the article headers." - Keith Thompson
More details at: <http://cfaj.freeshell.org/google/>
Also see <http://www.safalra.com/special/googlegroupsreply/>
 
V

Vladimir S. Oka

santosh said:
In following code
char str[] = "asdf" ;

This as equivalent to:

char str[] = {'a', 's', 'd', 'f', \0};

A normal way to initialise arrays.
str[0] = 's' ;
is possible.

But char *str = "asdf" ;

This creates a nameless /constant/ string literal "asdf", and you're
not allowed to modify constants, as it invokes Undefined Behaviour, and
you /know/ what /that/ means (close your eyes, and imagine demons
flying out your nose -- pink ones)!
What i understand is *str = "asdf" is stored in Read-only-Memory. Where
as str[] is stored in stack.

No, see above.
 
E

Emmanuel Delahaye

santosh a écrit :
In following code
char str[] = "asdf" ;

Here is an initialized array of char.
str[0] = 's' ;
is possible.

Sure. An array of char is mutable (unless it is qualified 'const').
But char *str = "asdf" ;

Here is a pointer to a string literal.
str[0] = 's' ;

Undefine behaviour. A string literal is not portably mutable. You'd
better code this :

char const *str = "asdf" ;

It makes things clear. Any attempt to modify the string :

str[0] = 's' ;

will ring a bell.

Much better. If you have gcc, add the -Wwrite-strings flag on the
command line.
is an run-time error.

It's possible. An undefined behaviour can produce anything at all event
nothing visible (today).
What i understand is *str = "asdf" is stored in Read-only-Memory. Where

It's compiler dependent.
as str[] is stored in stack.

If you meant 'automatic memory', yes, possibly, or 'static memory'...
who knows. We need more code...
Does any body has any better explanation for that?

No, but the standard surely has one:

http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1124.pdf
 
V

Vladimir S. Oka

Vladimir said:
In following code
char str[] = "asdf" ;

This as equivalent to:

char str[] = {'a', 's', 'd', 'f', \0};

A normal way to initialise arrays.
str[0] = 's' ;
is possible.

But char *str = "asdf" ;

This creates a nameless /constant/ string literal "asdf", and you're
not allowed to modify constants, as it invokes Undefined Behaviour,
and you /know/ what /that/ means (close your eyes, and imagine demons
flying out your nose -- pink ones)!

I forgot to add: the address of the string literal is then assigned to
the pointer `str`. No arrays in sight there...
What i understand is *str = "asdf" is stored in Read-only-Memory.
Where as str[] is stored in stack.

No, see above.
 
P

pete

Vladimir S. Oka wrote:
I forgot to add: the address of the string literal is then assigned to
the pointer `str`. No arrays in sight there...

The string literal represents an array.
The type of "abcd", is an array of 5 char.
 
K

Keith Thompson

santosh said:
In following code
char str[] = "asdf" ;
str[0] = 's' ;
is possible.

But char *str = "asdf" ;
str[0] = 's' ;
is an run-time error.

What i understand is *str = "asdf" is stored in Read-only-Memory. Where
as str[] is stored in stack.

Does any body has any better explanation for that?

Yes, Steve Summit does. This is question 1.32 in the comp.lang.c FAQ,
<http://www.c-faq.com/>.

A note to the comp.lang.c regulars: I think we need to make better use
of the FAQ. I see a lot of people spending time answering FAQs
without referring to the FAQ list. Often a simple reference to the
FAQ list is all that's required.
 
J

Jack Klein

In following code
char str[] = "asdf" ;

This as equivalent to:

char str[] = {'a', 's', 'd', 'f', \0};

A normal way to initialise arrays.
str[0] = 's' ;
is possible.

But char *str = "asdf" ;

This creates a nameless /constant/ string literal "asdf", and you're

[snip]

No, it does not. The type of a string literal in C is "array of
char", and most specifically not "array of const char".

Attempting to modify a string literal in C is undefined behavior
because the standard explicitly states that it is, not because the
string literal exists in an array of const chars.
 
W

websnarf

santosh said:
In following code
char str[] = "asdf" ;
str[0] = 's' ;
is possible.

But char *str = "asdf" ;
str[0] = 's' ;
is an run-time error.

What i understand is *str = "asdf" is stored in Read-only-Memory. Where
as str[] is stored in stack.

Does any body has any better explanation for that?

In the first, you are specifying an array with storage pegged to the
scope of where you are declaring it. So its storage is either in
function scope or file scope. The ="asdf"; part specifies how the
initial storage is initialized. Modifying str[0] is modifying its base
storage, and since its not declared const, there is no problem doing
this.

The second is a declaration of the pointer in which no specific storage
is specified. So "asdf" is given *implicit* storage in some unknown
but static location. The compiler is allowed to reuse this memory and
can assume it is never modified if it likes, so trying to modify it at
runtime is undefined. So the ="asdf"; part has a different meaning
here than it did in the prior declaration.

Note also that: char str[10] = NULL; is also illegal, however char *
str = NULL; is not. The reason is that in the first, the initializer
must specify contents for what is being stored in str[10], while in the
second you are not specifying storage at all, which is fine for a
pointer.
 
C

CBFalconer

Keith said:
.... snip ...

A note to the comp.lang.c regulars: I think we need to make better
use of the FAQ. I see a lot of people spending time answering
FAQs without referring to the FAQ list. Often a simple reference
to the FAQ list is all that's required.

I agree in principle, but not in practice. The problem is that
most of the questioners never heard of the FAQ, and almost
certainly don't have it at their fingertips. That is their fault,
not ours. But one of our campaigns here must be to defeat
ignorance.

--
"If you want to post a followup via groups.google.com, don't use
the broken "Reply" link at the bottom of the article. Click on
"show options" at the top of the article, then click on the
"Reply" at the bottom of the article headers." - Keith Thompson
More details at: <http://cfaj.freeshell.org/google/>
Also see <http://www.safalra.com/special/googlegroupsreply/>
 
O

Old Wolf

santosh said:
What i understand is *str = "asdf" is stored in Read-only-Memory. Where
as str[] is stored in stack.

Does any body has any better explanation for that?

In the first, you are specifying an array with storage pegged to the
scope of where you are declaring it. So its storage is either in
function scope or file scope.

Storage is not in any scope. "Scope" refers to the parts of a
program where an identifier is visible. That identifier could have
any sort of storage (or even none at all).
The ="asdf"; part specifies how the initial storage is initialized.
Modifying str[0] is modifying its base storage,

There is no such thing as "initial storage" and "base storage".
Each variable only has one storage area and I think it is
confusing to give it extra labels like that.
and since its not declared const, there is no problem doing this.
The second is a declaration of the pointer in which no specific storage
is specified. So "asdf" is given *implicit* storage in some unknown
but static location.

"asdf" is an array of char that has storage just like any other array.
Again, giving storage labels like "specific" and "implicit" is just
confusing, IMHO.

Whether or not a pointer gets pointed to this, makes no difference
as to how or where it is allocated (or what name we should call it!)
The compiler is allowed to reuse this memory and
can assume it is never modified if it likes, so trying to modify it at
runtime is undefined. So the ="asdf"; part has a different meaning
here than it did in the prior declaration.

The "asdf" part has the same meaning and the '=' have
the same meaning. In both cases, the array "asdf" is being
used to initialize the variable on the left.

But arrays are initialized by another objects which are
copied into them (to cut a long story short), whereas pointers
are initialized by pointing them to an object.
Note also that: char str[10] = NULL; is also illegal,

This is legal and initializes str to contain null characters.
(A null pointer constant can be converted to an integer).
However it's bad style.
however char * str = NULL; is not. The reason is that in
the first, the initializer must specify contents for what is
being stored in str[10], while in the second you are not
specifying storage at all, which is fine for a pointer.

Pointers, just like any other variable, have storage.
In both examples the storage is being initailized.
 
K

Keith Thompson

CBFalconer said:
I agree in principle, but not in practice. The problem is that
most of the questioners never heard of the FAQ, and almost
certainly don't have it at their fingertips. That is their fault,
not ours. But one of our campaigns here must be to defeat
ignorance.

My point is that I often see regulars, people who know about the FAQ,
posting lengthy (and usually correct) explanations that duplicate the
information that's already in the FAQ. (I've probably done this
myself.) The regulars aren't making as much use of the FAQ as we
could.
 
P

pete

Old said:
Storage is not in any scope. "Scope" refers to the parts of a
program where an identifier is visible. That identifier could have
any sort of storage (or even none at all).

Identifiers have scope, objects have storage.
static and automatic declared objects,
have identifiers which are also primary expressions.

"asdf" is an array of char that has storage just like any other array.
Again, giving storage labels like "specific" and "implicit" is just
confusing, IMHO.

Whether or not a pointer gets pointed to this, makes no difference
as to how or where it is allocated (or what name we should call it!)

"reserved" is a better word to apply to storage than "allocated",
since "allocated" is one of the 3 kinds of duration.
The "asdf" part has the same meaning and the '=' have
the same meaning.

The meaning is different.
When initializing an array like:

char array[] = "";

.... the "" means the exact same thing as {'\0'}
and the = is used here in a way that can't be used
with an array anywhere else except in a declaration.

When initializing a pointer like:

char *array = "";

The "" is an expression of array type
which gets converted to a pointer to its first member.
The = is used here in a way that is very similar
to assignment, as in an assignment expression.
Note also that: char str[10] = NULL; is also illegal,

This is legal and initializes str to contain null characters.

It is not legal.
Initialization of aggregate types requires {braces}.
 

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

No members online now.

Forum statistics

Threads
473,756
Messages
2,569,535
Members
45,008
Latest member
obedient dusk

Latest Threads

Top