# a[i] = a[j]... Dangerous?

Discussion in 'C Programming' started by s0suk3@gmail.com, Jul 1, 2008.

1. ### Guest

I'm a bit unclear whether a statement such as 'a = a[j];' causes
undefined behavior or some other abnormalities. A statement such as
'a = a[i++];' would definitely cause problems because of the double
use and side effect of 'i'. But in the former case, will the double
use of the array 'a' cause problems? Or will the right operand
('a[j]') of the assignment be evaluated first and then safely assigned
to the right operand ('a')?

Thanks

, Jul 1, 2008

2. ### Walter RobersonGuest

In article <>,
Kaz Kylheku <> wrote:

>Note that a = a is well-defined, from which it follows that a = a[j]
>is well defined even if i == j.

I don't seem to recall at the moment... if a is an array of
volatile sig_atomic_t and while the statement a = a; is
being executed, there is a signal handler fired which changes
a, what is the "well defined" result?
--
"Eightly percent of the people in the world are fools and the
rest of us are in danger of contamination." -- Walter Matthau

Walter Roberson, Jul 1, 2008

3. ### CBFalconerGuest

wrote:
>
> I'm a bit unclear whether a statement such as 'a = a[j];' causes
> undefined behavior or some other abnormalities. A statement such as
> 'a = a[i++];' would definitely cause problems because of the
> double use and side effect of 'i'. But in the former case, will the
> double use of the array 'a' cause problems? Or will the right
> operand ('a[j]') of the assignment be evaluated first and then
> safely assigned to the right operand ('a')?

Yes. However a pointer to a _may_ be computed before the value
of a[j] is derived. Your expression is safe.

--
[mail]: Chuck F (cbfalconer at maineline dot net)
[page]: <http://cbfalconer.home.att.net>
Try the download section.

CBFalconer, Jul 1, 2008
4. ### August KarlstromGuest

wrote:
> I'm a bit unclear whether a statement such as 'a = a[j];' causes
> undefined behavior or some other abnormalities. A statement such as
> 'a = a[i++];' would definitely cause problems because of the double
> use and side effect of 'i'. But in the former case, will the double
> use of the array 'a' cause problems? Or will the right operand
> ('a[j]') of the assignment be evaluated first and then safely assigned
> to the right operand ('a')?
>
> Thanks

In the assignment

a = a[j];

neither a nor a[j] has any side effects so it is certainly a
well-defined statement.

August

August Karlstrom, Jul 1, 2008
5. ### Guest

On Jul 3, 2:34 am, "Robbie Hatley"
<> wrote:
<snip>
> I use something like the above in production code at work,
> to periodically move the right-most 80% of an array to the
> far left, freeing up space on the right. A FIFO buffer;
> only the most recent data is retained, due to space limitations:
>
> int blat[800];
> ... do some stuff ...
> // shift data left when buffer gets full:
> if (BufferIsFull())
> {
> for ( i = 0 ; i < 700 ; ++i )
> {
> // Discard oldest 100 bytes and shift newest 700 leftward,
> // freeing 100 bytes on right side of array:
> blat = blat[i+100];
> }
>
> }

Just use memmove()

memmove(blat, &blat[100], 700 * sizeof *blat);

, Jul 3, 2008
6. ### santoshGuest

Robbie Hatley wrote:

>
> <> wrote:
>
>> Robbie Hatley wrote:
>> >
>> > int blat[800];
>> > ... do some stuff ...
>> > // shift data left when buffer gets full:
>> > if (BufferIsFull())
>> > {
>> > for ( i = 0 ; i < 700 ; ++i )
>> > {
>> > // Discard oldest 100 bytes and shift newest 700 leftward,
>> > // freeing 100 bytes on right side of array:
>> > blat = blat[i+100];
>> > }
>> > }

>>
>> Just use memmove()
>> memmove(blat, &blat[100], 700 * sizeof *blat);

>
> I'd probably seen "memmove" in the libc header before, but using
> it for that application simply never occurred to me.
>
> And even after reading the instructions for memmove, I like my
> version better, because it's more obvious what's happening:
>
> for ( i = 0; i < 700 ; ++i ) blat = blat[i+1]; // TRANSPARENT
>
> Whereas with memmove, you can't "see under the hood":
>
> memmove(blat, &blat[100], 700 * sizeof *blat); // OPAQUE
>
> I even doubt if the compiled code is faster for memmove.
> I'd guess it just uses a for loop. And if it does any
> error checking, it could even be slower. (Though in
> either case, we're talking maybe about 1 microsecond
> every 20 minutes or so. Cheap.)

The standard library memmove can take advantage of any special block
memory copy instructions that the hardware may have, using assembler.
Your replacement cannot do so.

Having said that I have observed in some tests that a custom written
memmove (also memcpy) is actually faster than the one provided by the
standard library, if the code is compiled with optimisations enabled.
This is because the C library on my machine is compiled to run on all
Intel processors from the 80x386 onwards while my custom memmove is
optimised for the specific processor model in operation. The difference
though is minuscule, and shows up only for large copies or intensive
loops.

santosh, Jul 3, 2008
7. ### Guest

On Jul 3, 10:37 pm, "Robbie Hatley"
<> wrote:
> I'd probably seen "memmove" in the libc header before, but using
> it for that application simply never occurred to me.
>
> And even after reading the instructions for memmove, I like my
> version better, because it's more obvious what's happening:
>
> for ( i = 0; i < 700 ; ++i ) blat = blat[i+1]; // TRANSPARENT
>
> Whereas with memmove, you can't "see under the hood":
>
> memmove(blat, &blat[100], 700 * sizeof *blat); // OPAQUE
>
> I even doubt if the compiled code is faster for memmove.
> I'd guess it just uses a for loop. And if it does any
> error checking, it could even be slower. (Though in
> either case, we're talking maybe about 1 microsecond
> every 20 minutes or so. Cheap.)

What other functions of standard C have you replaced with inline code?
It's bad practise, prone to errors and unproductive.

, Jul 3, 2008
8. ### Guest

On Jul 4, 1:47 am, "Robbie Hatley"
<> wrote:
> "vippstar" wrote:
> > Robbie Hatley wrote:

>
> > > I'd probably seen "memmove" in the libc header before, but using
> > > it for that application simply never occurred to me.

>
> > > And even after reading the instructions for memmove, I like my
> > > version better, because it's more obvious what's happening:

>
> > > for ( i = 0; i < 700 ; ++i ) blat = blat[i+1]; // TRANSPARENT

>
> > > Whereas with memmove, you can't "see under the hood":

>
> > > memmove(blat, &blat[100], 700 * sizeof *blat); // OPAQUE

>
> > > I even doubt if the compiled code is faster for memmove.
> > > I'd guess it just uses a for loop. And if it does any
> > > error checking, it could even be slower. (Though in
> > > either case, we're talking maybe about 1 microsecond
> > > every 20 minutes or so. Cheap.)

>
> > What other functions of standard C have you replaced with inline
> > code?

>
> Misquote. I didn't "replace" memmove with anything. As I said,
> it never occured to me to use that function (at the time I wrote
> the program, about 1 year ago). But even if I had known about
> it at the time, I wouldn't have used it, because the hand-written
> version is just as short and more transparent.
>
> > It's bad practise...

>
> Not necessarily. If it's more clear, I'd call it GOOD practice.
>
> > ... prone to errors ...

>
> Not necessarily. If the hand-written version is simple, it's
> generally no more "prone to error" than a version using a call
> to a library function.
>
> Specifically, in the "for-loop vs memmove" case you quote,
> the library function is more error prone, because you have to
> get three different arguments correct for it to work right.
>
> > ... and unproductive ...

>
> Nonsense. If it's more clear to the reader, then it's MORE
> productive, because it takes the reader less time to understand,
> and REDUCES chance of errors due to reader misunderstanding.
> (Hint: the reader may be someone other than the original author.)
>
> Don't get me wrong, I use std library functions all the time.
> But if I can do the same thing with a single, simple line of
> easy-to-understand home-spun code, i'll use the home-spun
> instead, because it's more TRANSPARENT:

<snip example>

This group is for C discussions. Clearly you need to be taught the
basics of programming, which I don't think I can teach you in a post
or two. I'll ignore the rest of your replies for this particular
matter, it's likely that a flame war will come out of it without
anything important discussed.

, Jul 4, 2008
9. ### Kaz KylhekuGuest

On 2008-07-03, Robbie Hatley <> wrote:
>
> "vippstar" wrote:
>
>> Robbie Hatley wrote:
>>
>> > I'd probably seen "memmove" in the libc header before, but using
>> > it for that application simply never occurred to me.
>> >
>> > And even after reading the instructions for memmove, I like my
>> > version better, because it's more obvious what's happening:
>> >
>> > for ( i = 0; i < 700 ; ++i ) blat = blat[i+1]; // TRANSPARENT
>> >
>> > Whereas with memmove, you can't "see under the hood":
>> >
>> > memmove(blat, &blat[100], 700 * sizeof *blat); // OPAQUE
>> >
>> > I even doubt if the compiled code is faster for memmove.
>> > I'd guess it just uses a for loop. And if it does any
>> > error checking, it could even be slower. (Though in
>> > either case, we're talking maybe about 1 microsecond
>> > every 20 minutes or so. Cheap.)

>>
>> What other functions of standard C have you replaced with inline
>> code?

>
> Misquote. I didn't "replace" memmove with anything. As I said,
> it never occured to me to use that function (at the time I wrote
> the program, about 1 year ago). But even if I had known about
> it at the time, I wouldn't have used it, because the hand-written
> version is just as short and more transparent.
>
>> It's bad practise...

>
> Not necessarily. If it's more clear, I'd call it GOOD practice.
>
>> ... prone to errors ...

>
> Not necessarily. If the hand-written version is simple, it's
> generally no more "prone to error" than a version using a call
> to a library function.
>
> Specifically, in the "for-loop vs memmove" case you quote,
> the library function is more error prone, because you have to
> get three different arguments correct for it to work right.
>
>> ... and unproductive ...

>
> Nonsense. If it's more clear to the reader, then it's MORE
> productive, because it takes the reader less time to understand,
> and REDUCES chance of errors due to reader misunderstanding.
> (Hint: the reader may be someone other than the original author.)
>
> Don't get me wrong, I use std library functions all the time.
> But if I can do the same thing with a single, simple line of
> easy-to-understand home-spun code, i'll use the home-spun
> instead, because it's more TRANSPARENT:

Transparency is a desireable property in computer science, when
it refers to a lack of unwanted interference in data communication,
or storage access.

The kind of transparency you are talking about here simply
refers to an inline expansion of something that is abstract
to one of its possible implementation.

All you are doing is burdening the reader with more responsibility.

> // YES:
> for ( i = 0; i < 700 ; ++i ) blat = blat[i+1];

If we include the declaration of i, this is a 19 node
abstract syntax tree.

Note that we ca make a small change to the above such that
its meaning radically changes.

for ( i = 0; i < 700 ; ++i ) blat += blat[i+1];

Now it's no longer doing a memmove. So you see the reader has
to analyze the code carefully; or else such a little
detail can easily be missed.

> // NO:
> memmove(blat, &blat[100], 700 * sizeof *blat);

This is a 10 node abstract syntax tree. Only 9 if we change
&blat[100] to blat + 100.

You're saying it's okay to bloat up code by a factor of 1.9
to avoid using a library function.

And that's just the increase in raw synactic complexity.
There is an increase in semantic complexity also.

The meaning of the code is ``copy this much data from here
to there''. The memcpy call simply states that meaning!
It's a primitive, well-understood operation.

The expanded algorithm does /not/ just state that meaning;
the meaning emerges from the relationship of the individual
steps of the algorithm, as it unfolds in time.

> I save library functions for things which can NOT be easily
> handled by hand-written code, such as:
>
> // Could do this by hand, but this is MUCH easier:
> if (strcomp(str1, str2)) {......}

The function is called strcmp, not strcomp. (Are you sure you use it?)

The above code can be inlined with a syntactic bloat of over 3.

This, of course, is worse than 1.9, but not much:

// 5 node syntax tree

if (strcmp(s1, s2)) statement;

// 16 node syntax tree

while (*s1 && *s2)
if (*s1++ != *s2++) {
statement;
break;
}

The professional programmer won't tolerate any increase in syntactic
complexity for the sake of avoiding the use of a standard library function.
The exception would be when he is optimizing.

Kaz Kylheku, Jul 6, 2008
10. ### WillemGuest

Kaz Kylheku wrote:
) The function is called strcmp, not strcomp. (Are you sure you use it?)

Perhaps he's speaking of some non-standard function that compares
case-insensitively (similar to the also non-standard strcasecmp)

) The professional programmer won't tolerate any increase in syntactic
) complexity for the sake of avoiding the use of a standard library function.
) The exception would be when he is optimizing.

In which case he should (IMO) keep the library function call that he's
replacing in a comment.

SaSW, Willem
--
Disclaimer: I am in no way responsible for any of the statements
made in the above text. For all I know I might be
drugged or something..
No I'm not paranoid. You all think I'm paranoid, don't you !
#EOT

Willem, Jul 7, 2008
11. ### Ben BacarisseGuest

"Robbie Hatley" <> writes:

> "Willem" <> wrote:
>
>> ... he [Robbie Hatley] should (IMO) keep the library function
>> call that he's replacing in a comment....

>
> Misquote. I never replaced any library function call. I wrote
> the code in question from scratch, electing not to use any
> library function calls.

I did not read it as you have edited it. The exchange was:

| ) The professional programmer won't tolerate any increase in syntactic
| ) complexity for the sake of avoiding the use of a standard library function.
| ) The exception would be when he is optimizing.
|
| In which case he should (IMO) keep the library function call that he's
| replacing in a comment.

To me, the "he" refers to "the professional programmer" not to you in
person as your edit of the quote seems to suggest. The discussion had
drifted into a general exchange about what to do ("keep the original")
in the (now hypothetical) case where one *has* replaced a library
call. At any rate, when I read the message you replied to, I did not
read it a referring to your code anymore.

--
Ben.

Ben Bacarisse, Jul 8, 2008
12. ### jacob naviaGuest

Mark McIntyre wrote:
[big snip]
>
> But surely you must agree that
> memmove(a,b);
> is quicker and clearer to read than 100 lines of hand-crafted code.
>

It is quicker and clearer but also completely wrong.

The prototype for memmove is:
void * memmove(void *, const void *, size_t);

You missed the size_t argument.

Should I deduce that writing library functions is as error prone
as inlining the code?

--
jacob navia
jacob at jacob point remcomp point fr
logiciels/informatique
http://www.cs.virginia.edu/~lcc-win32

jacob navia, Jul 8, 2008
13. ### Kaz KylhekuGuest

On 2008-07-04, Kaz Kylheku <> wrote:
> On 2008-07-03, Robbie Hatley <> wrote:
>> Specifically, in the "for-loop vs memmove" case you quote,
>> the library function is more error prone, because you have to
>> get three different arguments correct for it to work right.

>
> All three arguments are also present in the inline code.

Wow, Friday article appears out of Teranews black hole the following Wednesday!

Strangly, it's still not visible on their server!

Kaz Kylheku, Jul 9, 2008
14. ### CBFalconerGuest

Kaz Kylheku wrote:
> Kaz Kylheku <> wrote:
>> Robbie Hatley <> wrote:
>>
>>> Specifically, in the "for-loop vs memmove" case you quote,
>>> the library function is more error prone, because you have to
>>> get three different arguments correct for it to work right.

>>
>> All three arguments are also present in the inline code.

>
> Wow, Friday article appears out of Teranews black hole the
> following Wednesday!
>
> Strangly, it's still not visible on their server!

Teranews has that habit. It appears about every two weeks or so.
Then they propagate the whole schmeer after a three to five day
delay. Recently they had even more failings, so I switched to
motzarella, and all seems fine so far. When I first used Teranews
they didn't have that delay problem.

--
[mail]: Chuck F (cbfalconer at maineline dot net)
[page]: <http://cbfalconer.home.att.net>
Try the download section.

CBFalconer, Jul 9, 2008
15. ### CBFalconerGuest

CBFalconer wrote:
> Kaz Kylheku wrote:
>> Kaz Kylheku <> wrote:
>>> Robbie Hatley <> wrote:
>>>
>>>> Specifically, in the "for-loop vs memmove" case you quote,
>>>> the library function is more error prone, because you have to
>>>> get three different arguments correct for it to work right.
>>>
>>> All three arguments are also present in the inline code.

>>
>> Wow, Friday article appears out of Teranews black hole the
>> following Wednesday!
>>
>> Strangly, it's still not visible on their server!

>
> Teranews has that habit. It appears about every two weeks or so.
> Then they propagate the whole schmeer after a three to five day
> delay. Recently they had even more failings, so I switched to
> motzarella, and all seems fine so far. When I first used
> Teranews they didn't have that delay problem.

PS: Teranews has also taken to stealing the Organization slot in
the headers. A further nuisance.

--
[mail]: Chuck F (cbfalconer at maineline dot net)
[page]: <http://cbfalconer.home.att.net>
Try the download section.

CBFalconer, Jul 10, 2008

### Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.