why char *p = "can not modiy"; char p[] = "can modify"

B

baumann.Pan

when define
char *p = " can not modify";

p[0] ='b' ;is not allowed,

but if you declare p as
char p[] = "can modify";

p[0] = 'b'; is ok?
why?
what's difference between the two declaration + definition?
 
J

Jens.Toerring

when define
char *p = " can not modify";

This defines nothing more than a single pointer that is initialized
to point to a literal string, i.e. a string that resides in memory
that you're not allowed to modify.
p[0] ='b' ;is not allowed,
but if you declare p as
char p[] = "can modify";

This definition is quite different. It gives you an array of chars,
(just large enough to hold as many characters as the string "can
modify" has, plus one extra for the trailing '\0' character) and
that is initialized to that string. So that second declaration is
basically an abbreviation for

char p[ sizeof "can modify" ];
strcpy( p, "can modify" );

while the first definition does not involve any implicit strcpy()
but just assigns an address in non-modifiable memory to the pointer.

Regards, Jens
 
P

Pedro Graca

[newbie answer]
when define
char *p = " can not modify";

p[0] ='b' ;is not allowed,

p contains the address of the string " can not modify".
This string can be anywhere -- even in ROM.

You can change 'p' itself, not its contents.
but if you declare p as
char p[] = "can modify";

'p' is created here, the same way as a int would;
Its contents are then /copied/ from the string "can modify" which
can be anywhere -- even on ROM.
p[0] = 'b'; is ok?
why?

You're changing a copy of the constant, and that copy is changeable.
what's difference between the two declaration + definition?


With the first 'p' you allocate space for a pointer.

With the second 'p' you allocate as much space as needed for all the
characters (including the terminating '\0') in the string.



HTH
 
H

hari4063

With: char *p = "something", You declare pointer that points to string
"something", and many compilers will place string in const section, so
changing this data is not good. Some compilers just put string in data
section (I think all Borland compilers, but not for sure) and changin this
data is OK. But, this source will not be portable.

With: char p[] = "something", You declare array, not pointer to string.
Becuase p is array it is logical that You can change value of array.

P.S.
Even MinGW does not issue any warning about this, but code will not work.
 
B

Barry Schwarz

when define
char *p = " can not modify";

p[0] ='b' ;is not allowed,

but if you declare p as
char p[] = "can modify";

p[0] = 'b'; is ok?
why?
what's difference between the two declaration + definition?

The first declares a pointer which points to a string literal. The
string literal has static duration and the language standard says that
any attempt to modify it invokes undefined behavior.

The second declares an array which is initialized with the specified
characters (including the terminating '\0'). Whether or not the
string literal actually exists in your program is an implementation
issue not relevant to this newsgroup. Since your array is not defined
const, it is legal to modify it.


<<Remove the del for email>>
 
E

Endymion Ponsonby-Withermoor III

[Picking a post at random]
char *p = " can not modify";

p[0] ='b' ;is not allowed,

[Various people say that it shouldn't/won't work]

I have very vague recollections that there was (is?)a
Unix library function (probably several) for generating
temporary filenames:

extern void mktemp(char *s);

The idea was that you gave it a base name, such as
"abcdef0000000" and it would replace all the terminal
digits with a sequential number, or something. Anyway,
all the examples of its use that I saw, passed it
a quoted (i.e. constant) string. Calling the function
then overwrote that string.

Did I remember this right ?


What would happen if a file fragment had two different
string variables pointing to different (but identical)
strings, like this:

#include <stdio.h>

static void f1(void)
{
char *aa = "Bugger";
fprintf(stdout,"aa=%d\n",(int)aa);
mktemp(aa);
}

static void f2(void)
{
char *bb = "Bugger";
fprintf(stdout,"bb=%d\n",(int)bb);
mktemp(bb);
}


extern void main(void)
{
f1();
f2();
}

I thought all identical string constants were replaced by
a single copy at compile time, so the two printfs above
would yield the same number.
 
M

Michael Mair

Endymion said:
[Picking a post at random]

char *p = " can not modify";

p[0] ='b' ;is not allowed,


[Various people say that it shouldn't/won't work]

I have very vague recollections that there was (is?)a
Unix library function (probably several) for generating
temporary filenames:

extern void mktemp(char *s);

The idea was that you gave it a base name, such as
"abcdef0000000" and it would replace all the terminal
digits with a sequential number, or something. Anyway,
all the examples of its use that I saw, passed it
a quoted (i.e. constant) string. Calling the function
then overwrote that string.

Did I remember this right ?

This, I do not know. I just use C99's tmpnam() and
tmpfile() functions (which gives you a valid file
name/path which clashes with nothing or opens a
temporary file which will be removed when closed).

What would happen if a file fragment had two different
string variables pointing to different (but identical)
strings, like this:

#include <stdio.h>

static void f1(void)
{
char *aa = "Bugger";
fprintf(stdout,"aa=%d\n",(int)aa);
mktemp(aa);
}

static void f2(void)
{
char *bb = "Bugger";
fprintf(stdout,"bb=%d\n",(int)bb);
mktemp(bb);
}


extern void main(void)
{
f1();
f2();
}

I thought all identical string constants were replaced by
a single copy at compile time, so the two printfs above
would yield the same number.

This is not determined by the standard. A good compiler
probably will do this. Apart from that, it is a Bad Idea
to use a mere (int) cast for pointer output.
And void is no longer a valid return type for main().
It seems you have been out of business for over fifteen
years.
<OT>
Just had a look at 'man 3 mktemp'; your above code
will not work and is dangerous. Maybe this helps you:
--------------------------------------------------------
mktemp - make a unique temporary file name

SYNOPSIS
#include <stdlib.h>

char *mktemp(char *template);

DESCRIPTION
The mktemp() function generates a unique temporary file name
from template. The last
six characters of template must be XXXXXX and these are replaced
with a string that
makes the filename unique. Since it will be modified, template
must not be a string constant, but should be declared as a
character array.

RETURN VALUE
The mktemp() function returns NULL on error (template did not
end in XXXXXX) and template otherwise. If the call was
successful, the last six bytes of template will have
been modified in such a way that the resulting name is unique
(does not exist already).
If the call was unsuccessful, template is made an empty string.

ERRORS
EINVAL The last six characters of template were not XXXXXX.

CONFORMING TO
BSD 4.3. POSIX dictates tmpnam(3).

NOTE
The prototype is in <unistd.h> for libc4, libc5, glibc1; glibc2
follows the Single Unix Specification and has the prototype in
<stdlib.h>.

BUGS
Never use mktemp(). Some implementations follow BSD 4.3 and
replace XXXXXX by the current process id and a single letter,
so that at most 26 different names can be returned.
Since on the one hand the names are easy to guess, and on the
other hand there is a race between testing whether the name
exists and opening the file, every use of mktemp() is a
security risk. The race is avoided by mkstemp(3).
--------------------------------------------------------
</OT>


Cheers
Michael
 
D

dandelion

I have very vague recollections that there was (is?)a
Unix library function (probably several) for generating
temporary filenames:

extern void mktemp(char *s);

The idea was that you gave it a base name, such as
"abcdef0000000" and it would replace all the terminal
digits with a sequential number, or something. Anyway,
all the examples of its use that I saw, passed it
a quoted (i.e. constant) string. Calling the function
then overwrote that string.

Did I remember this right ?

Yes.

<quote
http://www.manpage.org/cgi-bin/man/man2html/usr/share/man/man3/mktemp.3.gz>
The mktemp() function generates a unique temporary file name from template.
The last six characters of template must be XXXXXX and these are replaced
with a string that makes the filename unique. Since it will be modified,
template must not be a string constant, but should be declared as a
character array.
What would happen if a file fragment had two different
string variables pointing to different (but identical)
strings, like this:

I thought all identical string constants were replaced by
a single copy at compile time, so the two printfs above
would yield the same number.

For many compilers that's true, but IIRC that's compiler-dependent. So do
not rely on it. It's (IIRC, again) not prescribed by The Standard. However,
i'd be the last to consider myself an
expert on The Standard (she said modestly).
 
C

Chris Torek

I have very vague recollections that there was (is?)a
Unix library function (probably several) for generating
temporary filenames:

extern void mktemp(char *s);

The idea was that you gave it a base name, such as
"abcdef0000000" and it would replace all the terminal
digits with a sequential number, or something. Anyway,
all the examples of its use that I saw, passed it
a quoted (i.e. constant) string. Calling the function
then overwrote that string.

Did I remember this right ?

There were indeed some old Unix programs that had code of the form:

char *p = mktemp("/tmp/progXXXXXX");

When we switched to ANSI C, they broke.

We fixed them:

static char buf[] = "/tmp/progXXXXXX";
char *p = mktemp(buf);

and now they work. (In general, when we fixed them we tried to
stop using mktemp() in the first place, as the entire concept of
mktemp() was flawed. But the above sufficed as a first pass, if
necessary.)
 
H

Herbert Rosenau

when define
char *p = " can not modify";

p points to a string literal.
but if you declare p as
char p[] = "can modify";

p points to an array of char.

No it points nowhere as p is not a pointer. p is an array of char in
the length of the given string including a null byte.
p[0] = 'b'; is ok?
why?

Because the C standard says so.

No, not really. p[0] is the first byte of an array of char, not a
string literal.
one points to a string literal, the other to an array.
No, one is a string literal, the other is an array of char. There is
no pointer in sight.

A string literal is NOT a pointer - but can be handled as if it were
in assignents.
An array is NOT a pointer - but can be handled as if it were in
assignments.

Even as the compiler will decide to handle the name of an array
without subscription to handle as a pointer - it is NOT a pointer.

A pointer is not an array but can point to a member of one.
 
D

Dave Thompson

With: char *p = "something", You declare pointer that points to string
"something", and many compilers will place string in const section, so
changing this data is not good. Some compilers just put string in data
section (I think all Borland compilers, but not for sure) and changin this
data is OK. But, this source will not be portable.

With: char p[] = "something", You declare array, not pointer to string.
Becuase p is array it is logical that You can change value of array.

P.S.
Even MinGW does not issue any warning about this, but code will not work.

(assuming "this" is writing into a string literal value)

It (actually GCC, which is the compiler mingw includes) does warn if
you use -Wwrite-strings. More specifically it (nonstandardly) makes
the string literal value officially const and so warns about losing
const qualification on the pointer; if you fix that by qualifying the
pointer, it warns about any attempt to store through it, unless you
cast away the const somewhere or cheat (by punning, or strchr etc.)


- David.Thompson1 at worldnet.att.net
 

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
473,731
Messages
2,569,432
Members
44,832
Latest member
GlennSmall

Latest Threads

Top