473,327 Members | 2,069 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,327 software developers and data experts.

A question on string literals

char *str1 = "Hello";
char arr1[] = { "Hello" };
char arr2[] = { 'H', 'e', 'l', 'l', 'o' };

Is it legal to modify str1, arr1 and arr2 ?

Nov 15 '05
52 2974
Keith Thompson <ks***@mib.org> writes:
Tim Rentsch <tx*@alumnus.caltech.edu> writes:
Keith Thompson <ks***@mib.org> writes:
pete <pf*****@mindspring.com> writes:
> Tim Rentsch wrote:
>>
>> Keith Thompson <ks***@mib.org> writes:
>
>> > An array isn't (necessarily) a non-modifiable lvalue.
>>
>> An array is never a modifiable lvalue; 6.3.2.1 p1.
>
> "A modifiable lvalue is an lvalue that does not have array type, "

Right. The comma is critical; there are more criteria. (I mention
that because I mis-read it the first time.)

(I added the "(necessarily)" because I was too lazy to think it
through and/or look it up. It wasn't meant to imply that an array can
sometimes be a modifiable lvalue, though I see that it could be read
that way.)
Ah, now I see what you meant: an array wouldn't *have* to
be a non-modifiable lvalue. I believe that statement is
correct; the standard could have been written so array
expressions were modifiable lvalues, and nothing would
change, because in every place where it might be relevant
the array expression would be converted to a pointer, and so
would be illegal anyway. Probably 6.3.2.1 p1 excludes array
expressions from being modifiable lvalues so as to make it
absolutely clear that arrays can't be used with =, ++, etc.


I'm glad you were able to read into what I wrote something cleverer
than what I intended. In fact, I was just being lazy. If I had spent
a minute or two doing more research, I could have dropped the
"(necessarily)"; I didn't bother because it didn't seem relevant to my
point. I should have realized that irrelevance doesn't prevent long
threads. 8-)}


I usually look for the "smartest" reading in what people
write. It's often right, and it rarely hurts to give
someone the benefit of any doubt. Also I figure looking
for the best possible interpretation benefits me, since
when I do I sometimes find significant points that I
wouldn't otherwise.

Yes, I suppose the "does not have array type" phrase in 6.3.2.1p1 is,
strictly speaking, redundant, but it's a *good* redundancy. Without
it, if arr is an array object, then the name "arr" in "sizeof arr" or
"&arr" would be a modifiable lvalue, but it wouldn't matter because
neither operator modifies its argument. But I think the wording is
cleaner as it is.


Agreed.
Nov 15 '05 #51
>> Chris Torek wrote:
&foo - object context
sizeof foo - object (or maybe even "sizeof") context [snippage] and so on.
Joe Wright <jw*****@comcast.net> writes:
I know you Chris and I love you like a brother but given..
int foo = 2, bar = 3;

&foo - is the address of foo, a 'value' of type (int*)
sizeof foo - is a value (4 at my house) of type (size_t)
++foo - is a value (now 3) of type (int)

None of these have 'object' context as I see it. What are you trying
to tell us here?

In article <ln************@nuthaus.mib.org>
Keith Thompson <ks***@mib.org> wrote:In "&foo", he's talking about the context in which the name "foo"
appears, not the entire expression. The argument to the unary "&"
operator must be an lvalue, so foo is in an "object context". Similarly,
the argument of unary "++" must be an lvalue.
Keith is right about this.
He's mistaken about sizeof, which doesn't require an lvalue.


This is true, and is why I said "or maybe even `sizeof context'".
Sizeof is even more exceptional than unary-&.

Finally, I would like to note that -- while it was never added to
C99 -- there have been various proposals, over the years, to
implement array assignment in C. I suspect that C1X or C2X (if
these ever come about) may eventually do so -- and if so, I believe
the "most natural" way to handle array assignment is to add a rule
that says, in:

a = b

if "a" has type "array N of T", b is converted to a value of type
"pointer to T" (and if it does not match a diagnostic is required);
then the code acts much like a call of the form:

memcpy(&a[0], b, sizeof a)

except that the type of the result is "pointer to T" (rather than
"pointer to void").

If this *were* added to C, the left side of a simple asignment
operator would join the ranks of the "exceptions" for the
array-to-pointer conversion rule.

Of course, there are also "obvious" and "natural" (to me anyway)
interpretations for:

arr += arithmetic_type;
arr -= arithmetic_type;
arr++; /* same as arr += 1 */
arr--; /* same as arr -= 1 */
/* and so on for all arithmetic and logical operators */

which involve replicated arithmetic applying the right-hand-side
value (or implied 1, for ++ and --) to each element of the array,
with the value of the expression as a whole again being "pointer
to first element of array". (Some might object that this renders
identical values for arr++ and ++arr, to which I say: "so what?" :-) )

All of these interpretations arise from one single central idea:
naming an array always just names the entire array, but the "value"
of an array (when a value is needed) is computed by finding a
pointer to its first element. If a value is *not* needed, the
array still names the entire array.

Again, this is not quite what the actual C standards (C89 and C99
both) say, but it delivers the same result, in what I think is a
simpler, yet ultimately more powerful, way.
--
In-Real-Life: Chris Torek, Wind River Systems
Salt Lake City, UT, USA (40°39.22'N, 111°50.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 15 '05 #52
Chris Torek <no****@torek.net> writes:
[snip]

Finally, I would like to note that -- while it was never added to
C99 -- there have been various proposals, over the years, to
implement array assignment in C. I suspect that C1X or C2X (if
these ever come about) may eventually do so -- and if so, I believe
the "most natural" way to handle array assignment is to add a rule
that says, in:

a = b

if "a" has type "array N of T", b is converted to a value of type
"pointer to T" (and if it does not match a diagnostic is required);
then the code acts much like a call of the form:

memcpy(&a[0], b, sizeof a)

except that the type of the result is "pointer to T" (rather than
"pointer to void").
One would hope [0] that for an array assignment 'a = b' both
'a' and 'b' would have to be array expressions (and perhaps
even of identical numbers of elements). The chance of
memory being illegally accessed if b were allowed to be just
a pointer (which is implied, although not actually stated,
in Chris's comments), seems like too big a risk to allow
without needing an overt effort from the programmer. If a
pointer value were present for the right hand side, it could
always be cast to a suitable array type.

Also, to be consistent, the result of the array assignment
expression would still be of array type, so

a = b = c;

could be done.
[0] In the sense that at least one would hope because I
would, and I also would hope others would also.

If this *were* added to C, the left side of a simple asignment
operator would join the ranks of the "exceptions" for the
array-to-pointer conversion rule.
Likewise the right hand side of an assignment expression where
the left hand side has array type.

Of course, there are also "obvious" and "natural" (to me anyway)
interpretations for:

arr += arithmetic_type;
arr -= arithmetic_type;
arr++; /* same as arr += 1 */
arr--; /* same as arr -= 1 */
/* and so on for all arithmetic and logical operators */

which involve replicated arithmetic applying the right-hand-side
value (or implied 1, for ++ and --) to each element of the array,
with the value of the expression as a whole again being "pointer
to first element of array". (Some might object that this renders
identical values for arr++ and ++arr, to which I say: "so what?" :-) )
If extensions like these were going to be made, it seems
like it would be important to preserve the semantic
properties that C developers are used to for scalar
variables. In particular, for

a = b++;
a = ++b;

with both sides being arrays, it would be strange if the
two statements above had identical behavior. Certainly
it violates "The Law of Least Astonishment".

I don't know how useful (or non-useful) these kinds of
operators would be for array types, but certainly it seems
like there's a strong possibility of semantic confusion.
(Also programmer confusion, but who cares about that? :)

All of these interpretations arise from one single central idea:
naming an array always just names the entire array, but the "value"
of an array (when a value is needed) is computed by finding a
pointer to its first element. If a value is *not* needed, the
array still names the entire array.
Perhaps this needs to be said differently. An expression
of array type remains an array when the context where it's
used needs an array; otherwise the array-type expression
is converted into a pointer to the array's first element,
as usual.

To be the most useful, it seems like array "assignment"
would also need to extend to passing of function parameters
and function results. There might be some difficulties
here. That's not to say that they couldn't be worked out,
but it's easy to imagine that there would be some unexpected
consequences.

Again, this is not quite what the actual C standards (C89 and C99
both) say, but it delivers the same result, in what I think is a
simpler, yet ultimately more powerful, way.


I believe C would benefit from having arrays be more
completely integrated into the language, including at least
assignment and parameter/result passing. However, I suspect
the effort required for working out all the details for that
is more than many C experts might guess.

Nov 15 '05 #53

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

16
by: Don Starr | last post by:
When applied to a string literal, is the sizeof operator supposed to return the size of the string (including nul), or the size of a pointer? For example, assuming a char is 1 byte and a char *...
7
by: al | last post by:
char s = "This string literal"; or char *s= "This string literal"; Both define a string literal. Both suppose to be read-only and not to be modified according to Standard. And both have...
17
by: Janice | last post by:
char* line = "abcd"; How to convert the line to upper case and print? Any option for printf to do this? Thanx
8
by: junky_fellow | last post by:
what would be the output for the following piece of code ? if ( "hello" == "hello" ) printf("True\n"); else printf("False\n"); What is the reason for that ?
6
by: copx | last post by:
Can you / are you supposed to free() string literals which are no longer needed? In my case I've menu construction code that looks like this: menu_items = list_new(); list_add(menu_items,...
41
by: Dead Loop | last post by:
Hi all, I'm a beginner and my question is: Are there any differences between char *p = "Hello, world!"; and const char *p = "Hello, world!"; ?
8
by: arnuld | last post by:
i tried to output these 2 to the std. output: const std::string hello = "Hello"; const std::string message = hello + ", world" + "!"; const std::string exclam = "!"; const std::string...
4
by: =?ISO-8859-15?Q?Jean=2DFran=E7ois?= Lemaire | last post by:
Hello all, I'm learning C and I still am struggling to understand some basic concepts. For example, I read in the standard that with functions such as strcpy, 'If copying takes place between...
5
by: polas | last post by:
Good morning, I have a quick question to clear up some confusion in my mind. I understand that using a string literal in a declaration such as char *p = "string literal" declares a pointer to...
7
by: lithiumcat | last post by:
Hi, I'm not yet very confident in my use of standard terminology, so please be kind if I'm mis-calling something, I will do my best no to make it again once pointed out. I'm wondering what is...
0
by: DolphinDB | last post by:
Tired of spending countless mintues downsampling your data? Look no further! In this article, you’ll learn how to efficiently downsample 6.48 billion high-frequency records to 61 million...
1
isladogs
by: isladogs | last post by:
The next Access Europe meeting will be on Wednesday 6 Mar 2024 starting at 18:00 UK time (6PM UTC) and finishing at about 19:15 (7.15PM). In this month's session, we are pleased to welcome back...
0
by: jfyes | last post by:
As a hardware engineer, after seeing that CEIWEI recently released a new tool for Modbus RTU Over TCP/UDP filtering and monitoring, I actively went to its official website to take a look. It turned...
0
by: ArrayDB | last post by:
The error message I've encountered is; ERROR:root:Error generating model response: exception: access violation writing 0x0000000000005140, which seems to be indicative of an access violation...
1
by: Defcon1945 | last post by:
I'm trying to learn Python using Pycharm but import shutil doesn't work
1
by: Shællîpôpï 09 | last post by:
If u are using a keypad phone, how do u turn on JavaScript, to access features like WhatsApp, Facebook, Instagram....
0
by: af34tf | last post by:
Hi Guys, I have a domain whose name is BytesLimited.com, and I want to sell it. Does anyone know about platforms that allow me to list my domain in auction for free. Thank you
0
by: Faith0G | last post by:
I am starting a new it consulting business and it's been a while since I setup a new website. Is wordpress still the best web based software for hosting a 5 page website? The webpages will be...
0
isladogs
by: isladogs | last post by:
The next Access Europe User Group meeting will be on Wednesday 3 Apr 2024 starting at 18:00 UK time (6PM UTC+1) and finishing by 19:30 (7.30PM). In this session, we are pleased to welcome former...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.