473,486 Members | 1,640 Online
Bytes | Software Development & Data Engineering Community
Create Post

Home Posts Topics Members FAQ

--(int)d

yuu
Is this code correct C and C++?

{
enum MyEnum { ME_A, ME_B } d = ME_B;

--(int)d;
/* 'd' should be ME_A now. I added the cast because g++ would not
accept the program without it. */
}

gcc accepts it, but MS Visual C++ says that "--" needs an lvalue.
Which compiler is right according to C and C++ standards?
Nov 14 '05 #1
15 2277
yu*@yyhmail.com (yuu) writes:
{
enum MyEnum { ME_A, ME_B } d = ME_B;

--(int)d;
/* 'd' should be ME_A now. I added the cast because g++ would not
accept the program without it. */
}
Not correct C. The result of a cast is not an lvalue.
gcc accepts it, but MS Visual C++ says that "--" needs an lvalue.


Did you pass -ansi -pedantic to GCC? Otherwise it's not a
conforming compiler.
--
"This is a wonderful answer.
It's off-topic, it's incorrect, and it doesn't answer the question."
--Richard Heathfield
Nov 14 '05 #2


yuu wrote:
Is this code correct C and C++?

{
enum MyEnum { ME_A, ME_B } d = ME_B;

--(int)d;
/* 'd' should be ME_A now. I added the cast because g++ would not
accept the program without it. */
}

gcc accepts it, but MS Visual C++ says that "--" needs an lvalue.
Which compiler is right according to C and C++ standards?


It doesn't really matter. Don't do it as you're opening up a potential
window for a future bug when someone comes along and sticks another enum
value between the existing 2. If you're using enums, don't make any
assumptions in your code about their absolute or relative numeric values
and your code will be more robust.

Ed.

Nov 14 '05 #3
yu*@yyhmail.com (yuu) writes:
Is this code correct C and C++?

{
enum MyEnum { ME_A, ME_B } d = ME_B;

--(int)d;
/* 'd' should be ME_A now. I added the cast because g++ would not
accept the program without it. */
}

gcc accepts it, but MS Visual C++ says that "--" needs an lvalue.
Which compiler is right according to C and C++ standards?


The --(int)d is a GCC extension. If you use the -pendantic option, GCC will
warn you about the use of extensions:

--> gcc -O -S foo.c -pedantic
foo.c: In function `foo':
foo.c:4: warning: ISO C forbids use of cast expressions as lvalues
foo.c:4: warning: ISO C forbids use of cast expressions as lvalues

--
Michael Meissner
email: mr*****@the-meissners.org
http://www.the-meissners.org
Nov 14 '05 #4
Quite possibly the best single way to avoid mysterious bugs is to treat
variables as they are logically intended. C does not provide string
typing, so you should.

Treat numeric variables as numeric; don't do bit operations on them.

Treat boolean variables as boolean; don't do arithmetic and don't compare
them against boolean constants.

Treat enum variables as though they can have no values except the symbolic
ones defined for them; don't increment RED to get BLUE.

Etc. (I also always initialize pointers to NULL, never compare them to
NULL (using if (!ptr)), compile with virtually all warnings turned on, and
don't type cast except when it is absolutely necessary - or to get rid of
a warning after the program is otherwise thoroughly debugged. But this is
a different issue.)

Yes, these are generalizations, and there are times when it's perfectly OK
not to follow them. If you are writing hard real-time code or device
drivers, there are times when it might be useful not to follow these
practices (e.g., a compiler that does a divide to calculate the modulo of
an integer type, and which divide is slower than the boolean masking
operation).

I believe I'm safe in saying that, in general, there's no reason not to
follow these practices. Besides, it helps make your code more portable
and (more importantly) more readable.
--
#include <standard.disclaimer>
_
Kevin D Quitt USA 91387-4454 96.37% of all statistics are made up
Per the FCA, this address may not be added to any commercial mail list
Nov 14 '05 #5
Ed Morton <mo****************@lucent.com> wrote in message news:<br********@netnews.proxy.lucent.com>...
yuu wrote:
Is this code correct C and C++?

{
enum MyEnum { ME_A, ME_B } d = ME_B;

--(int)d;
/* 'd' should be ME_A now. I added the cast because g++ would not
accept the program without it. */
}

gcc accepts it, but MS Visual C++ says that "--" needs an lvalue.
Which compiler is right according to C and C++ standards?


It doesn't really matter. Don't do it as you're opening up a potential
window for a future bug when someone comes along and sticks another enum
value between the existing 2. If you're using enums, don't make any
assumptions in your code about their absolute or relative numeric values
and your code will be more robust.


That depends on what you're doing and why - 'going to the next lowest
value without knowing or caring what it is' may be exactly what you
want to do. For example, an alarm state might be represented by
enum {GREEN, RED}; if I want to go to the lowest alarm state, I would
explicitly go to GREEN. If I know I'm not at the lowest state but want
to go down a state, I'd decrement the current state. As originally
written, these two would be equivalent. When someone changes the alarm
states to enum {GREEN, GREENISH_YELLOW, AMBER, REDISH_ORANGE, RED} my
decrement from RED wouldn't change the state to GREEN, but it would do
exactly what I intended.

In line with your argument, I would never decrement RED if I was trying
to get to GREEN, but it's appropriate to decrement RED if I want to get
to 'whatever comes just before RED'. This is susceptible to someone
explicitly setting the values of the enums and leaving gaps, but that
is reasonably handled by commenting the definition.
Nov 14 '05 #6
yuu
Right, -pedantic warns me about the error. I always use -Wall, but not
-pedantic, because i like some extensions...
Compiling with g++, -pedantic has no effect, the compiler happily
accepts the program...

Well, the cast was unnecessary, i used it to make the program compile
as C++ too. But the remedy was worse than the disease!

As for the "don't use enums as integers" silly rule, i'm sorry to say
that, but i won't follow you. ;-) Even Pascal has ord, pred and succ
that work on enum types!

Anyway let me explain what i was doing: my enum has 4 directions (say,
north, east, south and west). I use -1 (or --) to turn left and +1 to
turn right (%4, obviously). I could change the enum to #defines, but i
would lose the nice 'Direction' type i had defined! Choose your
favorite:

#define EAST 0
#define SOUTH 1
#define WEST 2
#define NORTH 3

// Use the #defines above as Direction (comment needed to make the
code clearer)
typedef int Direction;

// OR //

typedef enum Direction{
EAST, SOUTH, WEST, NORTH
}Direction;
don't increment RED to get BLUE.
What if i'm writing a karate program?
enum BeltColor {WHITE_BELT, /*i don't know the colors in between,*/
BLACK_BELT};

I don't think there is anything wrong in having ordered enums.
Etc. (I also always initialize pointers to NULL, never compare them to
NULL (using if (!ptr))


Again, what's the point of !ptr if ptr is not a boolean, but a
pointer?? Pointers are to be compared to pointers, so ptr == NULL is
OK. I prefer to use ! with booleans, not with pointers (and not with
integers, either)
Nov 14 '05 #7


J. J. Farrell wrote:
Ed Morton <mo****************@lucent.com> wrote in message news:<br********@netnews.proxy.lucent.com>...
yuu wrote:
Is this code correct C and C++?

{
enum MyEnum { ME_A, ME_B } d = ME_B;

--(int)d;
/* 'd' should be ME_A now. I added the cast because g++ would not
accept the program without it. */
}

gcc accepts it, but MS Visual C++ says that "--" needs an lvalue.
Which compiler is right according to C and C++ standards?
It doesn't really matter. Don't do it as you're opening up a potential
window for a future bug when someone comes along and sticks another enum
value between the existing 2. If you're using enums, don't make any
assumptions in your code about their absolute or relative numeric values
and your code will be more robust.

That depends on what you're doing and why - 'going to the next lowest
value without knowing or caring what it is' may be exactly what you
want to do. For example, an alarm state might be represented by
enum {GREEN, RED}; if I want to go to the lowest alarm state, I would
explicitly go to GREEN. If I know I'm not at the lowest state but want
to go down a state, I'd decrement the current state. As originally
written, these two would be equivalent. When someone changes the alarm
states to enum {GREEN, GREENISH_YELLOW, AMBER, REDISH_ORANGE, RED} my
decrement from RED wouldn't change the state to GREEN, but it would do
exactly what I intended.


But the way to do that is to wrap it in a macro or function, e.g.:

color = RAISECOLOR(color);

where you can #define:

#define RAISECOLOR(c) (int)(c) + 1;
#define LOWERCOLOR(c) (int)(c) - 1;

and then if in future you can no longer rely on the a contiguous
ordering of enum values (e.g. by adding a new value in the middle of the
range when it logically belongs at the "end" or by leaving numbering
gaps), you can change it to:

#define RAISECOLOR(c) (c) == GREEN ? YELLOW : .....;

and you can handle any necessary wrapping of values. For example, if
this was speeds of a ceiling fan, then you'd want the fan to start off
running at high speed, then go to medium, then low, then off on
successive chain pulls, so:

enum { OFF, LOW, MED, HIGH } ...
#define CHGSPEED(s) (s) == OFF ? HIGH : (s) - 1;

(ignore the double argument evaluation - it's beside the main point). I
guess the way I should've phrased my statement is that you should never
DIRECTLY perform arithmetic operations on enum values. In all of the
above, if you always just increment, or decrement, then you have to deal
with running off the end of the enum anyway.

Ed.
In line with your argument, I would never decrement RED if I was trying
to get to GREEN, but it's appropriate to decrement RED if I want to get
to 'whatever comes just before RED'. This is susceptible to someone
explicitly setting the values of the enums and leaving gaps, but that
is reasonably handled by commenting the definition.


Nov 14 '05 #8


yuu wrote:
Right, -pedantic warns me about the error. I always use -Wall, but not
-pedantic, because i like some extensions...
Compiling with g++, -pedantic has no effect, the compiler happily
accepts the program...

Well, the cast was unnecessary, i used it to make the program compile
as C++ too. But the remedy was worse than the disease!

As for the "don't use enums as integers" silly rule, i'm sorry to say
that, but i won't follow you. ;-) Even Pascal has ord, pred and succ
that work on enum types!
Exactly the point. You don't increment the variable, you use a diferent
method to get the succeeding or preceeding value. See my later posting
in this thread for more details.
Anyway let me explain what i was doing: my enum has 4 directions (say,
north, east, south and west). I use -1 (or --) to turn left and +1 to
turn right (%4, obviously). I could change the enum to #defines, but i
would lose the nice 'Direction' type i had defined! Choose your
favorite:

#define EAST 0
#define SOUTH 1
#define WEST 2
#define NORTH 3

// Use the #defines above as Direction (comment needed to make the
code clearer)
typedef int Direction;

// OR //

typedef enum Direction{
EAST, SOUTH, WEST, NORTH
}Direction;
Yeah, I guess I was a little hasty saying "don't ever do it". As long as
you wrap it in some pred/succ type of function or macro, then it doesn't
really affect the maintainability of the code whether you use #defines
or enums.
don't increment RED to get BLUE.

What if i'm writing a karate program?
enum BeltColor {WHITE_BELT, /*i don't know the colors in between,*/
BLACK_BELT};


It varies by style and club, but:

white -> yellow -> orange -> green -> blue -> purple -> brown 1 -> brown
2 -> brown 3 -> black

is fairly typical. You can, however, go straight from white to orange,
for example. It's up to whoever is performing the grading to decide what
belt you come out with. You CAN even go down a belt, so this isn't a
great example.
I don't think there is anything wrong in having ordered enums.


No there isn't, just don't rely on them keeping that order, or that
order having specific numeric values, throughout your code. If your
enums have a pred/succ relationship, then encapsulate that.

Ed.

Nov 14 '05 #9
yu*@yyhmail.com (yuu) wrote in message news:<b3**************************@posting.google. com>...
Is this code correct C and C++?

{
enum MyEnum { ME_A, ME_B } d = ME_B;

--(int)d;
/* 'd' should be ME_A now. I added the cast because g++ would not
accept the program without it. */
}

gcc accepts it, but MS Visual C++ says that "--" needs an lvalue.
Which compiler is right according to C and C++ standards?


As far as C is concerned, it's an error. Both the pre- and postfix
forms of "++" and "--" require an lvalue operand, and the result of a
cast expression is not an lvalue.

I'm not sure about C++, but I think the same logic applies.

This may be an extension offered by gcc. Try compiling again with the
flags -ansi -pedantic and see what it says.
Nov 14 '05 #10
On 9 Dec 2003 19:09:50 -0800, yu*@yyhmail.com (yuu) wrote:
As for the "don't use enums as integers" silly rule, i'm sorry to say
that, but i won't follow you. ;-) Even Pascal has ord, pred and succ
that work on enum types!
They're guidelines, not hard rules. There are times not to follow them,
but it's almost never when you think it's useful. These guidelines are
for writing code that works because it's supposed to, as opposed to code
that works by accident.

In general, counting on the order of enums is not a good idea. For your
example, what happens if you turn left from EAST? What if you want to
expand what you have to include SE, NE, SW, NW, and/or points in between?
Your code has to change, and it has to change everywhere.

If you wrap direction changing in functions, then you can be safe. Let
the calling program have a token that has no meaning to it, but that it
can call the wrapper functions to manipulate and interpret (such as
providing the string that represent the current direction, or a degree
count, etc.).

C can't enforce that, though.

I don't think there is anything wrong in having ordered enums.
It's not wrong, it's just that it frequently leads to problems because
your thinking is sloppy. C's enums aren't really enums, they're a
convenient fiction with no protection. Treat them strictly as enums
(except in wrapper routines which have to know better), and you're OK.

Again, what's the point of !ptr if ptr is not a boolean, but a
pointer?? Pointers are to be compared to pointers, so ptr == NULL is OK

-------------8<-----------------
#include <stdio.h>
#include <stdlib.h>

#undef NULL
#define NULL (void *)(123)
char *foo;

int main( void )
{
printf( "foo = %p\n", foo );
if ( foo == NULL )
puts( "foo == NULL\n" );
else
puts( "foo != NULL\n" );

return 0;
}
------------->8-----------------

YMMV. !ptr is guaranteed to be true if ptr is NULL, ptr == NULL is not.
--
#include <standard.disclaimer>
_
Kevin D Quitt USA 91387-4454 96.37% of all statistics are made up
Per the FCA, this address may not be added to any commercial mail list
Nov 14 '05 #11
Kevin D. Quitt <KQ**********@IEEIncUNMUNG.com> writes:
On 9 Dec 2003 19:09:50 -0800, yu*@yyhmail.com (yuu) wrote:

[...]
Again, what's the point of !ptr if ptr is not a boolean, but a
pointer?? Pointers are to be compared to pointers, so ptr == NULL is OK

-------------8<-----------------
#include <stdio.h>
#include <stdlib.h>

#undef NULL
#define NULL (void *)(123)
char *foo;

int main( void )
{
printf( "foo = %p\n", foo );
if ( foo == NULL )n
puts( "foo == NULL\n" );
else
puts( "foo != NULL\n" );

return 0;
}
------------->8-----------------

YMMV. !ptr is guaranteed to be true if ptr is NULL, ptr == NULL is not.


Cute, but if I also add

#define puts(s) printf("%s\n", "foo == NULL")

the program will always report "foo == NULL".

If you need to worry about someone maliciously changing the definition
of NULL behind your back, you've got bigger problems than we can solve
here.

--
Keith Thompson (The_Other_Keith) ks***@mib.org <http://www.ghoti.net/~kst>
San Diego Supercomputer Center <*> <http://www.sdsc.edu/~kst>
Schroedinger does Shakespeare: "To be *and* not to be"
(Note new e-mail address)
Nov 14 '05 #12
In article <43**************************@posting.google.com >
John Bode <jo*******@my-deja.com> writes:
As far as C is concerned, [--(int)d is] an error. Both the
pre- and postfix forms of "++" and "--" require an lvalue operand,
and the result of a cast expression is not an lvalue.
(Right.)
I'm not sure about C++, but I think the same logic applies.
C++ is quite different, largely because C++ has references and
user-defined overloaded operators that can return references. A
reference is, in effect, a special kind of C++ lvalue -- and if an
operator or function returns a reference, that makes the result
of that operator or function OK for further manipulation.

Modern C++ (which is quite different from the C++ I read about in
the original Stroustrup book) has quite a few different kinds of
casts, with subtly (or even blatantly) different meanings, but in
this particular case, the result of a "C-style cast" is a reference.
This [C version] may be an extension offered by gcc.


It is. GCC's "cast as lvalue" extension is defined in a rather
complicated fashion. You may cast on the left side of an assignment
operator (ordinary =, or += -= etc.), or as an operand to the ++
and -- operators. The result is not always consistent; for instance,
if "f" has type float, (int)f = 3.5 is considered OK (it means
(int)(f = (float)(int)3.5)) but &(int)f does not do anything useful.
Of course the cast-assignment to f here is not all that useful
either -- we could just write "(int)(f = 3.0F)", which would work
in any C compiler.
--
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 14 '05 #13
"Kevin D. Quitt" wrote:
On 9 Dec 2003 19:09:50 -0800, yu*@yyhmail.com (yuu) wrote:
As for the "don't use enums as integers" silly rule, i'm sorry
to say that, but i won't follow you. ;-) Even Pascal has ord,
pred and succ that work on enum types!


They're guidelines, not hard rules. There are times not to
follow them, but it's almost never when you think it's useful.
These guidelines are for writing code that works because it's
supposed to, as opposed to code that works by accident.

In general, counting on the order of enums is not a good idea.
For your example, what happens if you turn left from EAST? What
if you want to expand what you have to include SE, NE, SW, NW,
and/or points in between? Your code has to change, and it has to
change everywhere.


Unlike Pascal, C enums are not truly enumerated types, but a handy
mechanism for generating integral constants and a type that
/should/ only hold those values. Consider:

enum foo {one = 2, two, three = 5, five = 4, six = 13} bar;

bar = three;

Now, what would you want bar-- to create? The antecedent
enumeration is two, with the value three. The entry value of bar
is 5, so the integral predecessor is 4, which is the value of
succesor enumeration. I see no solution, so I suggest the easiest
way to handle it is to forbid ++ and -- on enums.

Pascal enumerations have ordinals starting at zero, and are in
strict succession, so the above problem never can arise, and they
are well ordered. Each system has its plusses and minuses.

--
Chuck F (cb********@yahoo.com) (cb********@worldnet.att.net)
Available for consulting/temporary embedded and systems.
<http://cbfalconer.home.att.net> USE worldnet address!
Nov 14 '05 #14
yuu
Chris Torek <no****@torek.net> wrote in message
Modern C++ (which is quite different from the C++ I read about in
the original Stroustrup book) has quite a few different kinds of
casts, with subtly (or even blatantly) different meanings, but in
this particular case, the result of a "C-style cast" is a reference.


Are you saying this --(int)d is correct in C++? Interesting!

/* And to those who flamed me about decrementing that enum: I _do_ use
wrappers! And i _do_ check for -1. I'm not _that_ stupid. */
Nov 14 '05 #15
[Cross posted and followups set to comp.lang.c++]

"yuu" <yu*@yyhmail.com> wrote in message
news:b3*************************@posting.google.co m...

[--(int)d where d is an enum type object]
Chris Torek <no****@torek.net> wrote in message
Modern C++ (which is quite different from the C++ I read about in
the original Stroustrup book) has quite a few different kinds of
casts, with subtly (or even blatantly) different meanings, but in
this particular case, the result of a "C-style cast" is a reference.


Are you saying this --(int)d is correct in C++?


No, he never said that.

I believe the behaviour is undefined if d's type is not compatible with int,
but questions on C++ are best answered in C++ groups...

--
Peter
Nov 14 '05 #16

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

Similar topics

9
1298
by: JustSomeGuy | last post by:
I have a data structure that contains a buffer of character of lenght n. The buffer in this case contains a string that is not null terminated. at the moment to get a null terminated buffer I'm...
5
1929
by: SalimShahzad | last post by:
dear gurus, can any one help me to how to store progrmatically last value in combo box. say i load access form. but in combo box the last value how it will come any ideas...as i need only...
2
2262
by: SalimShahzad | last post by:
Dear Gurus, i had written following codes to auto generate the next claim no Private Const strC = "GCT/02/J/" Private Sub Command1_Click() Dim stra, stre As String Dim intb, intd As Integer...
19
2532
by: n.torrey.pines | last post by:
I have the following tree definition: template<typename T> struct tree { T first; vector<tree<T second; // branches }; which compiles successfully. What I'd like to do though is to use...
1
259
by: JoeC | last post by:
I have a vector of elements, how can I take the first element of a vector and put it in the end and have all the other elements cycle down? Ex: 1, 2, 3, 4... cycle 4, 1, 2 ,3 I still want to...
8
2951
by: Gernot Frisch | last post by:
std::deque<intd; d.push_front(13); int* p13 = &d.begin(); d.push_front(1); d.push_back(2); Can I be safe, that p13 points to 13? I mean, unless I erase the 13, of course.
4
1438
by: flavourofbru | last post by:
Hi, I am storing the name of the text file in a string as string fname = "abc.txt"; string l_mline; vector<string> p_vFileIndices; Then I am trying to read this text file into a vector as...
0
1274
by: Semajthewise | last post by:
Hi all. I'm starting on my next part of my teach myself vb program. What I am trying to do is on button click open a textfile showing the math as it would be done long hand. I started writing the...
4
10805
by: Vince | last post by:
Given a week Number, how do I calculate the date that for the Monday of that week?
6
31439
Rabbit
by: Rabbit | last post by:
INTRODUCTION The Levenshtein Distance algorithm is an algorithm used to calculate the minimum number of edits required to transform one string into another string using addition, deletion, and...
0
7094
marktang
by: marktang | last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However,...
0
7173
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven...
1
6839
by: Hystou | last post by:
Overview: Windows 11 and 10 have less user interface control over operating system update behaviour than previous versions of Windows. In Windows 11 and 10, there is no way to turn off the Windows...
0
7305
tracyyun
by: tracyyun | last post by:
Dear forum friends, With the development of smart home technology, a variety of wireless communication protocols have appeared on the market, such as Zigbee, Z-Wave, Wi-Fi, Bluetooth, etc. Each...
0
5427
agi2029
by: agi2029 | last post by:
Let's talk about the concept of autonomous AI software engineers and no-code agents. These AIs are designed to manage the entire lifecycle of a software development project—planning, coding, testing,...
1
4863
isladogs
by: isladogs | last post by:
The next Access Europe User Group meeting will be on Wednesday 1 May 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 a new...
0
4559
by: conductexam | last post by:
I have .net C# application in which I am extracting data from word file and save it in database particularly. To store word all data as it is I am converting the whole word file firstly in HTML and...
1
598
muto222
php
by: muto222 | last post by:
How can i add a mobile payment intergratation into php mysql website.
0
259
bsmnconsultancy
by: bsmnconsultancy | last post by:
In today's digital era, a well-designed website is crucial for businesses looking to succeed. Whether you're a small business owner or a large corporation in Toronto, having a strong online presence...

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.