473,406 Members | 2,217 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,406 software developers and data experts.

*str++ is undefined?

I have some code:

*str++ = tolower(*str);

that gcc is complaining about:

warning: operation on `str' may be undefined

I'm getting similar warnings for 'di' and 'bi' in:

di = ++di % dn;

and

bi = ++bi % BUFSIZ;

I take it incrementing and evaluating together is undefined
bahavior? What's the rule?

Thanks,
Mike

$ gcc -v
Reading specs from /usr/libexec/gcc/darwin/ppc/3.3/specs
Thread model: posix
gcc version 3.3 20030304 (Apple Computer, Inc. build 1666)
Nov 14 '05 #1
10 4005
Michael B Allen wrote:

*str++ = tolower(*str);

that gcc is complaining about:

warning: operation on `str' may be undefined

I'm getting similar warnings for 'di' and 'bi' in:

di = ++di % dn;

and

bi = ++bi % BUFSIZ;

I take it incrementing and evaluating together is undefined
bahavior? What's the rule?


No. You are using an undefined value, because the ++ may actually
take effect either before or after the other use of the same
variable. The same thing would be fine for separate strings:

*s1++ = tolower((unsigned char) *s2++);

Note that you need the cast here unless s2 is already of type
unsigned char. char won't do.

--
"If you want to post a followup via groups.google.com, don't use
the broken "Reply" link at the bottom of the article. Click on
"show options" at the top of the article, then click on the
"Reply" at the bottom of the article headers." - Keith Thompson
Nov 14 '05 #2
On Sat, 19 Mar 2005 01:30:23 -0500, CBFalconer wrote:

*str++ = tolower(*str);

that gcc is complaining about:

warning: operation on `str' may be undefined


No. You are using an undefined value, because the ++ may actually take
effect either before or after the other use of the same variable.


That's stupid. The right side of the expression must be evaluated before
an assignment can be made. Where is the ambiguity exactly?

Mike
Nov 14 '05 #3
Michael B Allen wrote:
On Sat, 19 Mar 2005 01:30:23 -0500, CBFalconer wrote:

*str++ = tolower(*str);

that gcc is complaining about:

warning: operation on `str' may be undefined


No. You are using an undefined value, because the ++ may actually take
effect either before or after the other use of the same variable.


That's stupid. The right side of the expression must be evaluated before
an assignment can be made.
...


That's true. But the act of actual assignment consists of one and only
one action: storing the [suitable converted] result of the 'tolower'
call in the destination object of type 'char'. But the process of
_locating_ the destination object is not a part of the act of
assignment. The compiler is free to determine the destination object
_before_ the right-hand side is evaluated, and then perform the actual
assignment after the right hand side is evaluated. For example, the
above expression can be evaluated in accordance with the following schedule

// Determine the destination
char* dst = str++;

// Prepare the operand
char op = *str;

// Call the function
char res = tolower(op);

// Perform the assignment
*dst = res;

Or it can be evaluated in accordance with a different schedule

// Prepare the operand
char op = *str;

// Call the function
char res = tolower(op);

// Determine the destination
char* dst = str++;

// Perform the assignment
*dst = res;

Note, that both schedules are completely legal, i.e. they don't violate
any sequencing requirements imposed by the language specification. In
both cases the actual assignment is performed at the very end (i.e. "the
right side of the expression is evaluated before the assignment" as you
said). But the outcomes are completely different.

(One can easily come up with yet more possible schedules with yet more
possible outcomes).

--
Best regards,
Andrey Tarasevich

Nov 14 '05 #4
Michael B Allen wrote:
On Sat, 19 Mar 2005 01:30:23 -0500, CBFalconer wrote:
*str++ = tolower(*str);

that gcc is complaining about:

warning: operation on `str' may be undefined


No. You are using an undefined value, because the ++ may actually take
effect either before or after the other use of the same variable.


That's stupid. The right side of the expression must be evaluated before
an assignment can be made. Where is the ambiguity exactly?


But not before the computation of the address where the result will
be stored.

--
"If you want to post a followup via groups.google.com, don't use
the broken "Reply" link at the bottom of the article. Click on
"show options" at the top of the article, then click on the
"Reply" at the bottom of the article headers." - Keith Thompson
Nov 14 '05 #5
On Sat, 19 Mar 2005 03:29:14 -0500, Michael B Allen
<mb*****@ioplex.com> wrote:
On Sat, 19 Mar 2005 01:30:23 -0500, CBFalconer wrote:

*str++ = tolower(*str);

that gcc is complaining about:

warning: operation on `str' may be undefined


No. You are using an undefined value, because the ++ may actually take
effect either before or after the other use of the same variable.


That's stupid. The right side of the expression must be evaluated before
an assignment can be made. Where is the ambiguity exactly?

++ is an operator. Unless optimized away (obviously not the case
here), the compiler generates code to perform the evaluation specified
by the operator. The result of evaluating a post ++ is the current
value of the operand.

But ++ also has a side effect. In this case it will increment the
value of its operand. The only thing you know about when this side
effect occurs is that it will occur at or before next sequence point.

There are two sequence points in the statement. One is when the
function tolower() is called. (Obviously, the argument must be
evaluated before the function can be called.) The second is at the
semi-colon.

Since there is no dependency/relationship between the evaluation of
the ++ and the function call, they can occur in either order.
(Consider the expression a+b+tolower(c). a+b can be evaluated before
or after tolower is called.)

If the function call occurs first, then the ++ will be evaluated
after the argument and there is no confusion.

If the ++ is evaluated first, then it could be evaluated before or
after the argument.

While unlikely, it is possible for the generated code to
evaluate the argument, then evaluate the ++, and then call the
function. Again in this case there is no confusion.

In the more likely case, the ++ will be evaluated before the
argument. Now the problem is we do not know when the side effect
occurs. Does it occur before or after the argument is evaluated?

To eliminate this ambiguity and to avoid restricting compilers that
generate code for parallel machines or other advanced architectures,
the standard states:

"Between the previous and next sequence point an object shall have its
stored value modified at most once by the evaluation of an expression.
Furthermore, the prior value shall be accessed only to determine the
value to be stored."

(It is the second sentence that the statement in question violates
since str is accessed for two purposes. On the left it is used to
determine the current value but on the right it is dereferenced to
provide the argument to tolower.)

The standard also provides two examples:

"This paragraph renders undefined statement expressions such as

i = ++i + 1;
a[i++] = i;

while allowing

i = i + 1;
a[i] = i;"
<<Remove the del for email>>
Nov 14 '05 #6
On Sat, 19 Mar 2005 04:01:38 -0500, Andrey Tarasevich wrote:
*str++ = tolower(*str);

that gcc is complaining about:

warning: operation on `str' may be undefined

No. You are using an undefined value, because the ++ may actually
take effect either before or after the other use of the same variable.


That's stupid. The right side of the expression must be evaluated
before an assignment can be made.
...


That's true. But the act of actual assignment consists of one and only
one action: storing the [suitable converted] result of the 'tolower'
call in the destination object of type 'char'. But the process of
_locating_ the destination object is not a part of the act of
assignment. The compiler is free to determine the destination object
_before_ the right-hand side is evaluated, and then perform the actual
assignment after the right hand side is evaluated.


Ok, so I guess I just have to use another variable like:

int ch = *str;
*str++ = toupper(ch)

In practice if I don't do this is it really possible for such a simple
case to do the wrong thing here?

Mike
Nov 14 '05 #7
Michael B Allen wrote:
On Sat, 19 Mar 2005 04:01:38 -0500, Andrey Tarasevich wrote:
> *str++ = tolower(*str);
>
>that gcc is complaining about:
>
> warning: operation on `str' may be undefined
[...]

Ok, so I guess I just have to use another variable like:

int ch = *str;
*str++ = toupper(ch)


More simply,

*str = toupper(*str);
++str;

.... or more likely (if `str' is a `char*')

*str = toupper((unsigned char)*str);
++str;
In practice if I don't do this is it really possible for such a simple
case to do the wrong thing here?


No. It cannot do the "wrong" thing because there is no
"right" or "wrong" when the behavior is undefined. The original
statement *has no meaning* in C; it is nonsense. Grammatically
correct nonsense, but nonsense nonetheless ("Colorless green
ideas sleep furiously"). Whatever the implementation does with
such stuff is both forgivable and forgiven; you have not told it
what you want, so you have no complaint if it does the unwanted.

Is it possible that an implementation might do something
different with the original statement than it does with the
various alternatives? Yes. I don't recall having trouble with
this exact case (perhaps because it's so obviously wrong, and
experienced programmers avoid writing it), but I certainly
have encountered problems with code that violated the same rule.
In one case, the meaningless code behaved as intended when compiled
without optimization but failed mysteriously when optimization was
turned up for the "production" build. After considerable detective
work (the failure was subtle, and this was a two-million-line
program), the troublesome function was identified. The engineer
recompiled it with debugging flags on and optimization off, and
tried to figure out what was wrong -- except, of course, nothing
was wrong any more ... My engineer spent almost a full day hunting
down the bad code; she might instead have devoted that day to
something more productive than cleaning up after a nincompoop.

--
Eric Sosman
es*****@acm-dot-org.invalid
Nov 14 '05 #8
Michael B Allen <mb*****@ioplex.com> writes:
> *str++ = tolower(*str);
Ok, so I guess I just have to use another variable like:

int ch = *str;
*str++ = toupper(ch)

In practice if I don't do this is it really possible for such a simple
case to do the wrong thing here?


Yes. Different compilers will do different things.
--
"This is a wonderful answer.
It's off-topic, it's incorrect, and it doesn't answer the question."
--Richard Heathfield
Nov 14 '05 #9
On Sat, 19 Mar 2005 14:32:26 -0500, Michael B Allen
<mb*****@ioplex.com> wrote:
On Sat, 19 Mar 2005 04:01:38 -0500, Andrey Tarasevich wrote:

That's true. But the act of actual assignment consists of one and only
one action: storing the [suitable converted] result of the 'tolower'
call in the destination object of type 'char'. But the process of
_locating_ the destination object is not a part of the act of
assignment. The compiler is free to determine the destination object
_before_ the right-hand side is evaluated, and then perform the actual
assignment after the right hand side is evaluated.
Ok, so I guess I just have to use another variable like:

int ch = *str;
*str++ = toupper(ch)


There's an easy way with no extra variable. Since what you want is for
str to be incremented after the assignment, what's wrong with:

*str = toupper(*str);
++str;

Or if you need it as a single expression you could write it:

*str = toupper(*str), ++str

Either way, it's likely to be just as efficient as your original but
with a well defined effect.
In practice if I don't do this is it really possible for such a simple
case to do the wrong thing here?


Well, not the 'wrong' thing since whatever the compiler does with it is
just as right or wrong as any other, but it's certainly possible for it
to not do what you want. It may even do different things when just
changing the optimisation level, or depending on what code is around it.

Chris C
Nov 14 '05 #10
Barry Schwarz wrote:
Michael B Allen wrote:
CBFalconer wrote:

*str++ = tolower(*str);

[Actually, Michael B Allan wrote that]
There are two sequence points in the statement. One is when the
function tolower() is called. (Obviously, the argument must be
evaluated before the function can be called.) The second is at the
semi-colon.


A minor nit: tolower() could be a macro, so there would be
no sequence point. (The behaviour is still undefined, of course).

Nov 14 '05 #11

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

Similar topics

3
by: Tuxtrax | last post by:
Hi all. I have need of assistance on something that should be very simple, and is driving me absolutely batty. This is a code snippet from a short program that downloads news headers via...
11
by: Brent | last post by:
I'd like to subclass the built-in str type. For example: -- class MyString(str): def __init__(self, txt, data): super(MyString,self).__init__(txt) self.data = data
12
by: Brian | last post by:
I want to use regxp to check that a form input contains at least 1 non-space charcter. I'd like to only run this if the browser supports it. For DOM stuff, I'd use if (documentGetElementById) {}...
2
by: Neil Schemenauer | last post by:
python-dev@python.org.] The PEP has been rewritten based on a suggestion by Guido to change str() rather than adding a new built-in function. Based on my testing, I believe the idea is...
9
by: John Smith | last post by:
I understand that C identifiers beginning with str are reserved for future implementations. Do variable and function names beginning with str in my existing code, which is for my own use only,...
12
by: Robert J. Hansen | last post by:
While writing some code to demonstrate different local search strategies, I found something kind of unusual. I suspect it's a bug in my understanding rather than a bug in GCC, and I'm hoping...
2
by: ma740988 | last post by:
Consider: bool transmit ( const char* pch, size_t len ) { int const val = strcmp( pch, "who_am_i" ); if ( val == 0 ) return ( true ); return ( false ); }
13
by: 7stud | last post by:
I can't get the str() method to work in the following code(the last line produces an error): ============ class test: """class test""" def __init__(self): """I am init func!""" self.num = 10...
19
by: est | last post by:
From python manual str( ) Return a string containing a nicely printable representation of an object. For strings, this returns the string itself. The difference with repr(object) is that...
0
by: Charles Arthur | last post by:
How do i turn on java script on a villaon, callus and itel keypad mobile phone
0
by: emmanuelkatto | last post by:
Hi All, I am Emmanuel katto from Uganda. I want to ask what challenges you've faced while migrating a website to cloud. Please let me know. Thanks! Emmanuel
0
BarryA
by: BarryA | last post by:
What are the essential steps and strategies outlined in the Data Structures and Algorithms (DSA) roadmap for aspiring data scientists? How can individuals effectively utilize this roadmap to progress...
0
by: Hystou | last post by:
There are some requirements for setting up RAID: 1. The motherboard and BIOS support RAID configuration. 2. The motherboard has 2 or more available SATA protocol SSD/HDD slots (including MSATA, M.2...
0
by: Hystou | last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can...
0
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers,...
0
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
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,...
0
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...

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.