Question regarding array assignment

S

somenath

According to comp.lang.c FAQ list Question 1.32,

char *p = "string literal";
"string literal” is unnamed, static array of characters, and this unnamedarray may be stored in read-only memory, and which therefore cannot necessarily be modified. In an expression context, the array is converted at onceto a pointer, so declaration initializes p to point to the unnamed array's first element.

Then why we can not do the following?

char a[14];
a = "Hello, world!";

So using the above logic "Hello, world!" is unnamed, static array of characters, and this unnamed array may be stored in read-only memory, and which therefore cannot necessarily be modified. In an expression context, the array is converted at once to a pointer, so declaration initializes “a” which is ( except in case of operand of sizeof and & ) converted to pointer to the first element of char[14] i.e to &a[0].
So why the “a” can not be assigned to the pointer to the unnamed array's first element?
 
B

Ben Bacarisse

somenath said:
According to comp.lang.c FAQ list Question 1.32,

char *p = "string literal";
"string literal†is unnamed, static array of characters, and this
unnamed array may be stored in read-only memory, and which therefore
cannot necessarily be modified. In an expression context, the array is
converted at once to a pointer, so declaration initializes p to point
to the unnamed array's first element.

Then why we can not do the following?

char a[14];
a = "Hello, world!";

So using the above logic "Hello, world!" is unnamed, static array of
characters, and this unnamed array may be stored in read-only memory,
and which therefore cannot necessarily be modified. In an expression
context, the array is converted at once to a pointer, so declaration
initializes “a†which is ( except in case of operand of sizeof and & )
converted to pointer to the first element of char[14] i.e to &a[0].

Not really, no. It's not an initialisation -- 'a' simply names an
array. Most uses of that that name will be converted to a pointer to
the first element, but that conversion happens every time an
array-valued expression is used, not once due to some hidden
initialisation of a pointer-like object.
So why the “a†can not be assigned to the pointer to the unnamed
array's first element?

Well one answer is just that that the language specification says you
can't. Just after the text which you are nearly quoting:

Except when it is the operand of the sizeof operator, the _Alignof
operator, or the unary & operator, or is a string literal used to
initialize an array, an expression that has type "array of type" is
converted to an expression with type "pointer to type" that points
to the initial element of the array object and is not an lvalue.

The last bit is the key. An assignment needs a modifiable lvalue on the
left hand side and the expression 'a' is not an lvalue.

There is, of course, another explanation that emerges from the way C
evolved. In C's predecessors, array names are simply address constants,
and C did not want to change that view because of the simplicity that it
provides in most cases.
 
A

August Karlstrom

According to comp.lang.c FAQ list Question 1.32,

char *p = "string literal";

You want to make this a constant pointer:

const char *p = "string literal";
Then why we can not do the following?

char a[14]; a = "Hello, world!";

Because you cannot assign a pointer to an array.


-- August
 
B

BartC

somenath said:
According to comp.lang.c FAQ list Question 1.32,

char *p = "string literal";
"string literal” is unnamed, static array of characters, and this unnamed
array may be stored in read-only memory, and which therefore cannot
necessarily be modified. In an expression context, the array is converted
at once to a pointer, so declaration initializes p to point to the
unnamed array's first element.

Then why we can not do the following?

char a[14];
a = "Hello, world!";

So using the above logic "Hello, world!" is unnamed, static array of
characters, and this unnamed array may be stored in read-only memory, and
which therefore cannot necessarily be modified. In an expression context,
the array is converted at once to a pointer, so declaration initializes
“a” which is ( except in case of operand of sizeof and & ) converted to
pointer to the first element of char[14] i.e to &a[0].
So why the “a” can not be assigned to the pointer to the unnamed array's
first element?

Try:

strcpy(a,"Hello, World");

C doesn't do array or string assignments directly. If you want to use
pointers, then the code needs to be:

char *a;

a= "Hello, World!";

but this just copies a pointer; a will end up pointing to the same, possibly
read-only, block of memory. If you allocate separate memory for a, for
example:

char *a = malloc(...);

you'd then still need to explicitly copy the contents of the string:
strcpy(a,"Hello, World!").

You can do this however:

char a[14]="Hello, World!";

because this is not an assignment..
 
B

Ben Bacarisse

August Karlstrom said:
According to comp.lang.c FAQ list Question 1.32,

char *p = "string literal";

You want to make this a constant pointer:

const char *p = "string literal";
Then why we can not do the following?

char a[14]; a = "Hello, world!";

Because you cannot assign a pointer to an array.

Maybe that's enough, but you cut out the reason the OP gave for being
confused which is that the expression on the left hand side of the
assignment has pointer type not array type so it looks as if you are
assigning to a pointer. "You can't assign to an array" is a useful
summary, so maybe I was making too much of it.
 
A

Alan Curry

There is, of course, another explanation that emerges from the way C
evolved. In C's predecessors, array names are simply address constants,
and C did not want to change that view because of the simplicity that it
provides in most cases.

I never used these predecessor languages, but in my reading of the B
tutorial at http://cm.bell-labs.com/cm/cs/who/dmr/btut.ps one of the
surprising things was that array names actually were lvalues. (They're
called vectors instead of arrays)

The example given in section 22:

auto u[10], v[10];

u = v;
v[0] = ...
v[1] = ...

Is accompanied by an explanation that the assignment to u copies the
address, not the 10 values. So those old vector declarations would
translate into modern C as something like

int *u = (int[10]){0};

or if you have alloca

int *u = alloca(10*sizeof *u);

As far as I can tell from the tutorial and the reference (bref.ps), there
was never any name attached to the fixed address of what we would now call
the actual array.

In other words, a lot of the people who show up with confusion about the
relationship between pointers and arrays have intuitive ideas aligned more
with B than C.
 
P

Philip Lantz

somenath said:
According to comp.lang.c FAQ list Question 1.32,

char *p = "string literal";
"string literal? is unnamed, static array of characters, and this unnamed array may be stored in read-only memory, and which therefore cannot necessarily be modified. In an expression context, the array is converted at once to a pointer, so declaration initializes p to point to the unnamed array's first element.

Then why we can not do the following?

char a[14];
a = "Hello, world!";

So using the above logic "Hello, world!" is unnamed, static array of characters, and this unnamed array may be stored in read-only memory, and which therefore cannot necessarily be modified. In an expression context, the array is converted at once to a pointer, so declaration initializes ?a? which is ( except in case of operand of sizeof and & ) converted to pointer to the first element of char[14] i.e to &a[0].
So why the ?a? can not be assigned to the pointer to the unnamed array's first element?

Because the pointer (that 'a' is converted to) is a constant, so you
can't assign to it.

(I know there have been other answers; this is just another way of
looking at the situation that might be helpful.)
 
S

Seebs

Then why we can not do the following?
char a[14];
a = "Hello, world!";

For the same reason you can't do:
int i, j;

&j = &i;

While the expression "a" has pointer type, there is no object which holds
that pointer; the storage reserved is for 14 characters, not one pointer.

-s
 
B

Ben Bacarisse

There is, of course, another explanation that emerges from the way C
evolved. In C's predecessors, array names are simply address constants,
and C did not want to change that view because of the simplicity that it
provides in most cases.

I never used these predecessor languages, but in my reading of the B
tutorial at http://cm.bell-labs.com/cm/cs/who/dmr/btut.ps one of the
surprising things was that array names actually were lvalues. (They're
called vectors instead of arrays)

The example given in section 22:

auto u[10], v[10];

u = v;
v[0] = ...
v[1] = ...

Is accompanied by an explanation that the assignment to u copies the
address, not the 10 values.

Interesting. I have used B and I'd forgotten that (mind you, it was 35
years ago). Thanks for reminding me (of the facts, not of the elapsed
time!).

It's also true of BCPL, and I should have remembered that, having used
BCPL way more than B.

LET v = VEC 10;

makes a variable v whose content is a pointer to the vector (i.e. 11
locations are needed). v is not simply bound to the address of the
vector, it's a real, assignable, pointer to the vector's first element.

In other words, a lot of the people who show up with confusion about the
relationship between pointers and arrays have intuitive ideas aligned more
with B than C.

Yes. It would seem that having an array name actually refer to the
array is a purely C invention. What was inherited from B and BCPL is
using pointers and arrays interchangeably, which required C to invent
the "arrays decay to pointers" rule.

It's interesting speculate what the language would be like if C had
either dumped that equivalence (so that arrays could be denoted in their
entirety) or if C had adopted the B/BCPL idea that array names really
are pointers -- assignable pointer variables.

Anyway, thanks for the correction and the trip down memory lane.
 
K

Keith Thompson

Ben Bacarisse said:
(e-mail address removed) (Alan Curry) writes: [...]
In other words, a lot of the people who show up with confusion about the
relationship between pointers and arrays have intuitive ideas aligned more
with B than C.

Yes. It would seem that having an array name actually refer to the
array is a purely C invention. What was inherited from B and BCPL is
using pointers and arrays interchangeably, which required C to invent
the "arrays decay to pointers" rule.

It's interesting speculate what the language would be like if C had
either dumped that equivalence (so that arrays could be denoted in their
entirety) or if C had adopted the B/BCPL idea that array names really
are pointers -- assignable pointer variables.

The latter wasn't really a possibility. I believe that early C also
created an actual pointer object for an array declaration, so that

int array[10];

would allocate 11 words of storage, and `array` would be the
pointer object. This broke down when Dennis Ritchie decided to
permit arrays as members of structs; when copying one structure
to another, it would have been impractical to keep the pointer
consistent in the original and in the copy. (I suppose other
solutions might have been possible.)
 
K

Keith Thompson

August Karlstrom said:
You want to make this a constant pointer:

const char *p = "string literal";

const, not constant. Despite the similarity of names, "const"
and "constant" are two different things. A "constant expression",
for example, is one that can be evaluated at compile time. "const"
arguably should have been called "readonly"; for example this:

const int r = rand();

is perfectly legal. And given:

const char *p = "string literal";

you can assign a new value to p:

p = "another string literal";

The `const` means that the object p points to, not p itself, is
read-only (it's a "pointer to const char", not a "const pointer
to char").
 
S

somenath

Then why we can not do the following?


char a[14];
a = "Hello, world!";



For the same reason you can't do:

int i, j;



&j = &i;



While the expression "a" has pointer type, there is no object which holds

that pointer; the storage reserved is for 14 characters, not one pointer.
So in the following expressing

a = "Hello, world!";
"a" is a pointer type (char*) and "Hello World" has the type char[14].
And we can not assign array to pointer. That's the reason the code is in correct.
But when I look at the following error message

gcc -ansi -pedantic -Wall test.c
test.c: In function ‘main’:
test.c:4:7: error: incompatible types when assigning to type ‘char[14]’from type ‘char *’

It sounds like "a" is still char[14] and type of "Hello, world!" is char *
That's the reason compiler is saying "when assigning *to* type ‘char[14]"i.e to "a" "form type ‘char *’" that is type "Hello, world!" is not compatible.
 
G

glen herrmannsfeldt

Keith Thompson said:
The latter wasn't really a possibility. I believe that early C also
created an actual pointer object for an array declaration, so that
int array[10];
would allocate 11 words of storage, and `array` would be the
pointer object. This broke down when Dennis Ritchie decided to
permit arrays as members of structs; when copying one structure
to another, it would have been impractical to keep the pointer
consistent in the original and in the copy. (I suppose other
solutions might have been possible.)

Maybe different operators for pointer assignment and array assignment,
as Fortran has. Being used to C, I still find it confusing, along with
the lack of arrays of pointers. (Fortran allows arrays of structures
containing pointers, but not otherwise arrays of pointers.)

Does seem like there might be times when array assignment, and array
expressions in general, might have been a nice addition to the
C language.

-- glen
 
J

jacob navia

Le 09/12/2013 02:09, glen herrmannsfeldt a écrit :
Does seem like there might be times when array assignment, and array
expressions in general, might have been a nice addition to the
C language.

Yes, and the lcc-win compiler does exactly that. You can define
array operations with operator overloading.

It is a nice addition since it allows to add an array to
another compatible array using the new instructions for
array handling that most processors have nowadays but
nobody uses.

Operator overloading is a nice addition to C.
 
K

Kenny McCormack

Le 09/12/2013 02:09, glen herrmannsfeldt a écrit :

Yes, and the lcc-win compiler does exactly that. You can define
array operations with operator overloading.

It is a nice addition since it allows to add an array to
another compatible array using the new instructions for
array handling that most processors have nowadays but
nobody uses.

Operator overloading is a nice addition to C.

You'll never get that claim past the ghouls of CLC.

--
"The smart way to keep people passive and obedient is to strictly limit the
spectrum of acceptable opinion, but allow very lively debate within that
spectrum...."

- Noam Chomsky, The Common Good -
 
J

jacob navia

Le 09/12/2013 02:21, Kenny McCormack a écrit :
You'll never get that claim past the ghouls of CLC.

Hi,

you still there?

How are you doing?

I am doing fine, thank you!

:)
 
K

Keith Thompson

somenath said:
Then why we can not do the following?
char a[14];
a = "Hello, world!";

For the same reason you can't do:
int i, j;
&j = &i;
While the expression "a" has pointer type, there is no object which holds
that pointer; the storage reserved is for 14 characters, not one pointer.
So in the following expressing

a = "Hello, world!";
"a" is a pointer type (char*) and "Hello World" has the type char[14].

No, both a and "Hello, world!" are arrays, and they both decay to
pointers. The assignment is invalid because the LHS is not an lvalue.
(And once you have a constraint violation, that analysys pretty much
goes out the window anyway.)
And we can not assign array to pointer. That's the reason the code is in correct.
But when I look at the following error message

gcc -ansi -pedantic -Wall test.c
test.c: In function ‘main’:
test.c:4:7: error: incompatible types when assigning to type ‘char[14]’ from type ‘char *’

It sounds like "a" is still char[14] and type of "Hello, world!" is
char * That's the reason compiler is saying "when assigning *to* type
‘char[14]" i.e to "a" "form type ‘char *’" that is type "Hello,
world!" is not compatible.

The error message is slightly misleading, but once the compiler has
issued a diagnostic it's done its job.
 
S

somenath

somenath writes:


On 2013-12-08, somenath wrote:
Then why we can not do the following?
char a[14];
a = "Hello, world!";

For the same reason you can't do:
int i, j;
&j = &i;
While the expression "a" has pointer type, there is no object which holds
that pointer; the storage reserved is for 14 characters, not one pointer.
So in the following expressing

a = "Hello, world!";
"a" is a pointer type (char*) and "Hello World" has the type char[14].



No, both a and "Hello, world!" are arrays, and they both decay to

pointers. The assignment is invalid because the LHS is not an lvalue.

(And once you have a constraint violation, that analysys pretty much

goes out the window anyway.)
I am failing to understand why "a" is not providing lvalue here.
If I change the code follows
char *a;
a = "Hello, world!";
Compiler does not complain.

But it complain for


char a[14];
a = "Hello, world!";
If both "a" and "Hello, world!" decays to pointer type then why we can not assign one pointer to other?

What is primary difference between the following if both the places "a" is pointer ?

char *a;
a = "Hello, world!";
Here "a" is char * and "Hello, world!" also decays to char * and we are able to assign "a" to another character pointer.

and

char a[14];
a = "Hello, world!";
Here also "a" decays to char* and "Hello, world!" also decays to char* .
Then why we can not assign "a" to another char*?

And we can not assign array to pointer. That's the reason the code is in correct.
But when I look at the following error message

gcc -ansi -pedantic -Wall test.c
test.c: In function ‘main’:
test.c:4:7: error: incompatible types when assigning to type ‘char[14]’ from type ‘char *’
It sounds like "a" is still char[14] and type of "Hello, world!" is
char * That's the reason compiler is saying "when assigning *to* type
‘char[14]" i.e to "a" "form type ‘char *’" that is type "Hello,
world!" is not compatible.



The error message is slightly misleading, but once the compiler has

issued a diagnostic it's done its job.
Ok. But it makes life bit harder for learner like me. Who tries to understand what going wrong from compiler's error message.
 
B

Ben Bacarisse

somenath said:
On 2013-12-08, somenath wrote:
Then why we can not do the following?
char a[14];
a = "Hello, world!";
[...] both a and "Hello, world!" are arrays, and they both decay to
pointers. The assignment is invalid because the LHS is not an lvalue.
(And once you have a constraint violation, that analysys pretty much

goes out the window anyway.)
I am failing to understand why "a" is not providing lvalue here.

One answer (as I said before) is that the language standard says so:

Except when it is the operand of the sizeof operator, the _Alignof
operator, or the unary & operator, or is a string literal used to
initialize an array, an expression that has type "array of type" is
converted to an expression with type "pointer to type" that points
to the initial element of the array object and is not an lvalue.

The "operative" explanation is that the array name just specifies a
location. The pointer value to which it "decays" does not exist in an
object in it's own right -- it is purely a value -- so there is nowhere
to assign to.

<snip>
 
G

glen herrmannsfeldt

(snip, someone wrote)
One answer (as I said before) is that the language standard says so:
Except when it is the operand of the sizeof operator, the _Alignof
operator, or the unary & operator, or is a string literal used to
initialize an array, an expression that has type "array of type" is
converted to an expression with type "pointer to type" that points
to the initial element of the array object and is not an lvalue.
The "operative" explanation is that the array name just specifies a
location. The pointer value to which it "decays" does not exist in an
object in it's own right -- it is purely a value -- so there is nowhere
to assign to.

I usually think of array names as pointer constants. You can't change
them for the same reason you can't change 1.23.

-- glen
 

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,744
Messages
2,569,484
Members
44,904
Latest member
HealthyVisionsCBDPrice

Latest Threads

Top