By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
426,034 Members | 1,672 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 426,034 IT Pros & Developers. It's quick & easy.

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

P: n/a
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?
Nov 14 '05 #1
Share this Question
Share on Google+
13 Replies


P: n/a
ba*********@gmail.com wrote:
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

--
\ Jens Thoms Toerring ___ Je***********@physik.fu-berlin.de
\__________________________ http://www.toerring.de
Nov 14 '05 #2

P: n/a
[newbie answer]
ba*********@gmail.com wrote:
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
--
USENET would be a better place if everybody read: | to mail me: simply |
http://www.catb.org/~esr/faqs/smart-questions.html | "reply" to this post, |
http://www.netmeister.org/news/learn2quote2.html | *NO* MIME, plain text |
http://www.expita.com/nomime.html | and *NO* attachments. |
Nov 14 '05 #3

P: n/a
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.

Nov 14 '05 #4

P: n/a
On 8 Nov 2004 16:02:38 -0800, ba*********@gmail.com wrote:
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>>
Nov 14 '05 #5

P: n/a
[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.
Nov 14 '05 #6

P: n/a


Endymion Ponsonby-Withermoor III wrote:
[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
--
E-Mail: Mine is a gmx dot de address.

Nov 14 '05 #7

P: n/a

"Endymion Ponsonby-Withermoor III"
<m_a_r_v_i_n@para----and----.want-to-do.coe.ukk> wrote in message
news:cm**********@newsg1.svr.pol.co.uk...
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.
</quote>
What would happen if a file fragment had two different
string variables pointing to different (but identical)
strings, like this:
<snip code>
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).
Nov 14 '05 #8

P: n/a
In article <news:cm**********@newsg1.svr.pol.co.uk>
Endymion Ponsonby-Withermoor III
<m_a_r_v_i_n@para----and----.want-to-do.coe.ukk> wrote:
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.)
--
In-Real-Life: Chris Torek, Wind River Systems
Salt Lake City, UT, USA (4039.22'N, 11150.29'W) +1 801 277 2603
email: forget about it http://web.torek.net/torek/index.html
Reading email is like searching for food in the garbage, thanks to spammers.
Nov 14 '05 #9

P: n/a
On 8 Nov 2004 16:02:38 -0800, in comp.lang.c , ba*********@gmail.com wrote:
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.
p[0] = 'b'; is ok?
why?
Because the C standard says so.
what's difference between the two declaration + definition?


one points to a string literal, the other to an array.

--
Mark McIntyre
CLC FAQ <http://www.eskimo.com/~scs/C-faq/top.html>
CLC readme: <http://www.ungerhu.com/jxh/clc.welcome.txt>

----== Posted via Newsfeeds.Com - Unlimited-Uncensored-Secure Usenet News==----
http://www.newsfeeds.com The #1 Newsgroup Service in the World! 120,000+ Newsgroups
----= East and West-Coast Server Farms - Total Privacy via Encryption =----
Nov 14 '05 #10

P: n/a
Mark McIntyre wrote:

On 8 Nov 2004 16:02:38 -0800, in comp.lang.c , ba*********@gmail.com wrote:
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.


&p points to an array of char.

--
pete
Nov 14 '05 #11

P: n/a
On Wed, 10 Nov 2004 22:50:17 UTC, Mark McIntyre
<ma**********@spamcop.net> wrote:
On 8 Nov 2004 16:02:38 -0800, in comp.lang.c , ba*********@gmail.com wrote:
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.
what's difference between the two declaration + definition?


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.

--
Tschau/Bye
Herbert

Visit http://www.ecomstation.de the home of german eComStation

Nov 14 '05 #12

P: n/a
pete wrote:

Mark McIntyre wrote:

On 8 Nov 2004 16:02:38 -0800, in comp.lang.c ,
ba*********@gmail.com wrote:
when define
char *p = " can not modify";


p points to a string literal.


p points to a string.

--
pete
Nov 14 '05 #13

P: n/a
On Mon, 08 Nov 2004 19:35:46 -0500, "hari4063"
<za**************@pmf.unsa.ba> wrote:
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
Nov 14 '05 #14

This discussion thread is closed

Replies have been disabled for this discussion.