473,320 Members | 1,722 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,320 software developers and data experts.

Is buf[n]++ a lvalue?

The following code gives error C2105: '++' needs l-value.

char buf[20];
buf[n]++ = 'A';//buf[n]++ isn't a lvalue

Why buf[n]++ isn't a lvalue? Is this according to C Standard or is there
some reason for this?

If buf[n]++ isn't a lvalue, then why the following code works?

void func(char *a, char *b)
{
while(*a++=*b++){}
}
Nov 13 '05 #1
10 5003
Stub <st**@asof.com> spoke thus:
char buf[20];
buf[n]++ = 'A';//buf[n]++ isn't a lvalue Why buf[n]++ isn't a lvalue? Is this according to C Standard or is there
some reason for this? If buf[n]++ isn't a lvalue, then why the following code works? while(*a++=*b++){}


Because *a++ is the same as *(a++). a is a pointer and so it's fine to
increment it. buf[n], however, is a character, which you cannot increment.

--
Christopher Benson-Manica | I *should* know what I'm talking about - if I
ataru(at)cyberspace.org | don't, I need to know. Flames welcome.
Nov 13 '05 #2
Stub wrote:
The following code gives error C2105: '++' needs l-value.

char buf[20];
buf[n]++ = 'A';//buf[n]++ isn't a lvalue

Why buf[n]++ isn't a lvalue? Is this according to C Standard or is there
some reason for this?
Why would you think that these two options are mutually exclusive?
;-). Things in the C standard *are* there for a reason!

Most likely, however, the expression you want is:

buf[n++] = 'A';

If buf[n]++ isn't a lvalue, then why the following code works?

void func(char *a, char *b)
{
while(*a++=*b++){}
}


Because here the *pointers* are dereferenced (*a is an lvalue,
yes?), the assignment is performed (yielding the expression's value)
and finally each pointer is incremented.

HTH,
--ag

--
Artie Gold -- Austin, Texas
Oh, for the good old days of regular old SPAM.

Nov 13 '05 #3
Christopher Benson-Manica wrote:
buf[n], however, is a character, which you cannot
increment.


Yes, you can.
#include <stdio.h>

int main(void)
{
char buf[] = "3.1415926";
int n = 0;
buf[n]++;
printf("%s\n", buf);
return 0;
}

--
Richard Heathfield : bi****@eton.powernet.co.uk
"Usenet is a strange place." - Dennis M Ritchie, 29 July 1999.
C FAQ: http://www.eskimo.com/~scs/C-faq/top.html
K&R answers, C books, etc: http://users.powernet.co.uk/eton
Nov 13 '05 #4
"Stub" <st**@asof.com> writes:
The following code gives error C2105: '++' needs l-value.

char buf[20];
buf[n]++ = 'A';//buf[n]++ isn't a lvalue

Why buf[n]++ isn't a lvalue? Is this according to C Standard or is there
some reason for this?
Suppose buf[n]++ were an lvalue. Then buf[n]++ = 'A'; would
invoke undefined behavior because it would modify buf[n] twice
between sequence points: both the ++ and the = operator would
modify buf[n]. So you really don't want buf[n]++ to be an
lvalue.
If buf[n]++ isn't a lvalue, then why the following code works?

void func(char *a, char *b)
{
while(*a++=*b++){}
}


*a++ is equivalent to *(a++). a++ isn't an lvalue, but *(a++)
is.
--
"It wouldn't be a new C standard if it didn't give a
new meaning to the word `static'."
--Peter Seebach on C99
Nov 13 '05 #5
Stub wrote:
The following code gives error C2105: '++' needs l-value.

char buf[20];
buf[n]++ = 'A';//buf[n]++ isn't a lvalue

Why buf[n]++ isn't a lvalue?


because buf[n]++ evaluates to the byte value contained in buf[n]. You
are essentially saying something like:

'x' = 'A'

and that just doesn't fly.

NR

Nov 13 '05 #6
Christopher Benson-Manica wrote:

Stub <st**@asof.com> spoke thus:
char buf[20];
buf[n]++ = 'A';//buf[n]++ isn't a lvalue

Why buf[n]++ isn't a lvalue? Is this according to C Standard or is there
some reason for this?

If buf[n]++ isn't a lvalue, then why the following code works?

while(*a++=*b++){}


Because *a++ is the same as *(a++). a is a pointer and so it's fine to
increment it. buf[n], however, is a character, which you cannot increment.


Er, no: it's perfectly possible to increment a character.
Here's a silly way to output the decimal digits:

char c;
for (c = '0'; c <= '9'; ++c)
putchar (c);

The problem in the O.P.'s code is that the thing on the
left of the assignment is a value, not a variable (I'm using
loose terminology here; words like "lvalue" are Standardese,
used in a very precise but possibly confusing way). The
O.P.'s attempted assignment makes as much sense as

a + b = 'A';
sin(x) = 'A';
rand() = 'A';
x++ = 'A';

.... where all share the same characteristic: the thing on the
left produces a value, not a reference to something storable.

--
Er*********@sun.com
Nov 13 '05 #7
(Note: the quick answer to the question in the subject is "no".)

In article <vB*********************@bgtnsc05-news.ops.worldnet.att.net>
Stub <st**@asof.com> writes:
The following code gives error C2105: '++' needs l-value.

char buf[20];
buf[n]++ = 'A';//buf[n]++ isn't a lvalue

Why buf[n]++ isn't a lvalue?
The term "lvalue" has a somewhat bizarre set of definitions depending
on which C standard you use, but in any case, the expression:

buf[n]++

parses the same way as:

(buf[n])++

which means "find the object named buf[n], obtain its current value,
add 1 to that value, arrange to store the new sum back into buf[n]
by the next sequence point, and produce as the value of the expression
the value buf[n] had before any update occurs". The resulting value
is purely a value -- it does not name an object.

Note that buf[n] in turn is defined as *(buf + n); this will matter
in a moment...
If buf[n]++ isn't a lvalue, then why the following code works?

void func(char *a, char *b)
{
while(*a++=*b++){}
}


The expression:

*a++

is parsed the same way as:

*(a++)

Note: I am avoiding the term "precedence" as it leads people into
the trap of thinking: "precedence, that means the same as precede,
so that must mean that the whole `preceding' thing is done first,
then the whole `following' thing, in exactly that order". This is
not the case: "operator precedence" merely determines a "parse" at
compile time. In effect, it says where the parentheses would be
if there were parentheses. The actual *runtime* order of evaluation
is much less constrained.

Now, *(a++) is made up of two main pieces, one being "a++" and the
other being "*(expression)". The first piece -- "a++" -- works
pretty much the same as "buf[n]++": it locates the object named
"a", finds a's current value, computes a+1, schedules a+1 to be
stuffed back into the object by the next sequence point, and
produces the old value of "a". This is the value (not an object,
not an lvalue) handed to the unary "*" operator. The unary "*"
operator requires a pointer value -- which is the kind of value
"a++" produced -- and is defined to mean "follow that pointer to
the object to which it points".

It is this last step -- the "follow the pointer" step -- that
locates an object, or in the Standard's terms, gives you an "lvalue".
In other words, the unary * operator only needs a value, and produces
an object (or "lvalue"). This is just the opposite of "++", which
needs an object but produces a mere value. Objects hold values;
values are wispy, evanescent things that usually have to be stored
back into objects right away, before they evaporate.

Now, if buf[n] "means" *(buf + n), and if "*" just needs a value,
then as long as buf+n produces a suitable value, all is good. The
buf+n part of course uses the "+" operator, which needs *two*
values, but again, it just needs values, not actual objects. If
you want buf and/or n to change by the next sequence point, you can
embed one or more "++" operators here:

*(buf + n++)

which parses as:

*((buf) + ((n)++))

which tells the compiler to find the value of "buf", find the value
of "n", compute n+1, schedule n+1 to be stuffed back into n, compute
"value of buf plus original value of n", and give that to the "*"
operator as a pointer to follow. Exactly when "n" changes is never
specified -- it might even change *first*, by doing something like:

n++;
*(buf + (n - 1))

-- but you are assured that n will be updated by the next sequence
point. (This is why "sequence points" are such a big deal; for
more about them, consult the FAQ.)

And, since a[b] always "means" *((a) + (b)), you can rewrite
*(buf + n++) as buf[n++], which is no doubt what you intended to
use way back at the beginning. If you want to confuse the next
person to maintain your code, you can even use the commutative
property of addition to change *(buf + n++) into *(n++ + buf),
and rewrite that as n++[buf].
--
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://67.40.109.61/torek/index.html (for the moment)
Reading email is like searching for food in the garbage, thanks to spammers.
Nov 13 '05 #8

On Fri, 7 Nov 2003, Eric Sosman wrote:

Here's a silly way to output the decimal digits:

char c;
for (c = '0'; c <= '9'; ++c)
putchar (c);


Here's a silly nitpick:

#define SCHAR_MAX '9'
#define CHAR_MAX SCHAR_MAX

Undefined behavior upon integer overflow.

#define UCHAR_MAX '9'
#define CHAR_MAX UCHAR_MAX

Infinite loop.
:-)

-Arthur,
non-ASCII Fridays!
Nov 13 '05 #9
"Arthur J. O'Dwyer" wrote:

On Fri, 7 Nov 2003, Eric Sosman wrote:

Here's a silly way to output the decimal digits:

char c;
for (c = '0'; c <= '9'; ++c)
putchar (c);


Here's a silly nitpick:

#define SCHAR_MAX '9'
#define CHAR_MAX SCHAR_MAX

Undefined behavior upon integer overflow.

#define UCHAR_MAX '9'
#define CHAR_MAX UCHAR_MAX

Infinite loop.
:-)


I'm ashamed to admit it, but I actually thought
of this possibility when writing the code shown. That
means I've been hanging around comp.lang.c *much* too
long, and my once-mighty brain is now merely a dusty
attic over-filled with pedantic quibbles and nitpicks.

There was once a regular on c.l.c. who signed himself
"The Human Lint." Arthur and I seem to be in danger of
becoming clones of "The Human DeathStar 9000."

--
Er*********@sun.com
Nov 13 '05 #10
Richard Heathfield <do******@address.co.uk.invalid> spoke thus:
buf[n], however, is a character, which you cannot
increment.
Yes, you can.


Oops :( Sorry!

--
Christopher Benson-Manica | I *should* know what I'm talking about - if I
ataru(at)cyberspace.org | don't, I need to know. Flames welcome.
Nov 13 '05 #11

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

Similar topics

15
by: Michael Baehr | last post by:
I recently upgraded my Arch Linux system to GCC 3.4, and found out that a previously accepted behavior (cast-as-lvalue) is now marked as deprecated, and will cease to function in GCC 3.5. This has...
14
by: Michael B Allen | last post by:
I just noticed that doing something like the following may fail because it can overwrite u->size before it's evaluated. memcpy(u, buf, u->size); Is it legit that this is a macro as opposed to...
5
by: jab3 | last post by:
(again :)) Hello everyone. I'll ask this even at risk of being accused of not researching adequately. My question (before longer reasoning) is: How does declaring (or defining, whatever) a...
24
by: Romeo Colacitti | last post by:
Hi, Does anyone here have a strong understanding for the meanings of the terms "lvalue" and "rvalue" as it pertains to C, objects, and different contexts? If so please share. I've been...
33
by: baumann.Pan | last post by:
hi all, i want to get the address of buf, which defined as char buf = "abcde"; so can call strsep(address of buf, pointer to token);
2
by: ajikoe | last post by:
Hi, I tried to follow the example in swig homepage. I found error which I don't understand. I use bcc32, I already include directory where my python.h exist in bcc32.cfg. /* File : example.c...
12
by: George2 | last post by:
Hello everyone, Suppose we defined a string buffer (array), like this, char array = "hello world"; char buf Sometimes, I noticed that we either use,
6
by: Khookie | last post by:
Hi everyone Out of curiosity, would this be a valid implementation of a string copy function? int copy(char* to, char* from) { while (*to++ = *from++); } It's just that, I notice in...
23
by: sophia.agnes | last post by:
Dear all, I was going through a C book written by an indian author the following are the questions given in that book 1) consider the following statement: s1 : an operator may require an...
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...
0
by: ryjfgjl | last post by:
ExcelToDatabase: batch import excel into database automatically...
0
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: Vimpel783 | last post by:
Hello! Guys, I found this code on the Internet, but I need to modify it a little. It works well, the problem is this: Data is sent from only one cell, in this case B5, but it is necessary that data...
1
by: PapaRatzi | last post by:
Hello, I am teaching myself MS Access forms design and Visual Basic. I've created a table to capture a list of Top 30 singles and forms to capture new entries. The final step is a form (unbound)...
1
by: CloudSolutions | last post by:
Introduction: For many beginners and individual users, requiring a credit card and email registration may pose a barrier when starting to use cloud servers. However, some cloud server providers now...
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
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.