function explanation

D

dominant

What this function does?



void test_function(char *s, char *t) {



while(*s++=*t++)

;



}
 
T

Thomas Stegen

dominant said:
What this function does?



void test_function(char *s, char *t) {

while(*s++=*t++);

Remember that the = operator returns the value that
was assigned. Also remember that thew while loop
terminates when the controlling expression returns
0.

Then consider strings in C. They consist of a bunch of
characters followed by a null character. The null
character has value 0.

(Note that exactly when s and t are incremented is not
a straightforward issue for many beginners so this is
slightly informal, but is probably good enough for you)

First of s and t are incremented, ie. they are made to
point to the next char in the string they are pointing
to. Then their old value is returned for the * operator
to use. This means that value t was (since this is after
the increment) pointing to is now assigned to the position
s was pointing to. This value is then inspected by the while
loop to see if this value is 0 or not. If it is non-zero then
the loop goes again, but this time s and t are pointing
to different positions. So when t is pointing to a null
terminator, this value (aka 0) is assigned to *s and the while
loop gets a 0 and terminates.

The while loop can also be written like this:

while(*s = *t)
{
t++;
s++;
}

Note that the version you posted makes t potentially point
outside the array it is pointing to[1]. This is however legal
as the standard allows this to cater for the above idiom and
friends. You are not allowed to dereference this pointer even
if it is pointing somewhere legal.

[1] It is actually pointing to elements in the array, but you get
my drift.
 
M

Malcolm

dominant said:
void test_function(char *s, char *t)
while(*s++=*t++)
;
}
This is terrible C style. The equals sign is not a equality comparison, as
it looks like give the context, but an assignment. When the result of the
assignment, *s, goes to zero, the loop will terminate. The semicolon
indicates that it is an empty loop.
The ++ operators increment the pointers, and are applied after the
assignment takes place. This you wouldn't know if you didn't know C, but is
idiomatic and therefore just acceptable.
The combination of three quirky C features in one short loop makes this code
very difficult to read and debug.
 
T

Thomas Stegen

Malcolm said:
The combination of three quirky C features in one short loop makes this code
very difficult to read and debug.

Given the fact that it is a well known and accepted idiom
it is neither hard to read or hard to debug. First time I saw
it it took me about 1 minute to figure out what this was
doing.
 
P

pete

Thomas said:
Malcolm said:
"dominant" <[email protected]> wrote in message
[snip]
The combination of three quirky C features
in one short loop makes this code
very difficult to read and debug.

That code is taken directly from page 106, K&R2, section 5.5.
Given the fact that it is a well known and accepted idiom
it is neither hard to read or hard to debug.

"... the idiom should be mastered,
because you will see it frequently in C programs."
 
P

Peter Nilsson

....
"... the idiom should be mastered,
because you will see it frequently in C programs."

I can't speak for anyone else, but it was the extraordinary succinctness of
this paradigm that drew me to C in the first place.

Although, I've since been told that for many architectures, the following is
more likely to generate efficient machine code...

if (*s = *t)
while (*++s = *++t)
;

I guess learning 68000 assembler before I saw C was both an advantage and
disadvantage.
 
M

Malcolm

Peter Nilsson said:
I can't speak for anyone else, but it was the extraordinary succinctness >
of this paradigm that drew me to C in the first place.It shouldn't do. Programs are designed to present a series of instructions
to a computer, but they must also present code to another human programmer.
Generally the cost of a programmmer's time reading and understanding code
far exceeds the cost of computer time executing it. There are exceptions,
such as the inner loops of time-critical programs like games, but as a rule
code should be written so that it is as easy as possible to understand.
You can assume that your reader knows the C basics, and knows how to
program, but you shouldn't necessarily assume that he is comfortable with C
arcana. In particular constructions such as
while(a = b)
which suggest the wrong meaning should be avoided.
 
P

Peter Nilsson

Malcolm said:
It shouldn't do. Programs are designed to present a series of instructions
to a computer, but they must also present code to another human programmer.
Generally the cost of a programmmer's time reading and understanding code
far exceeds the cost of computer time executing it.

The 'understanding' you speak of is an aquired skill and not something
easily quantifiable. Languages like Lisp and Forth are quite often far
from obvious to the lay programmer, but they both offer aesthetic
clarity and elegance in constructs that aren't easily understood by
people for whom the languages haven't 'clicked' yet.

Any C programmer who has difficulty understanding the above
construction should not be let anywhere near anything even remotely
critical. Programs should be written with clarity in mind, but the
whole point of language development is to encapsulate paradigms with
clean syntax.

I've seen people use constructs like...

while (...yadda...)
{
continue;
}

It's my personal opinion obviously, but arguments stating that the
presence of the last three lines in place of a semi-colon aids
readability are an insult to the intelligence of moderately competent
C programmers.
There are exceptions,
such as the inner loops of time-critical programs like games, but as a rule
code should be written so that it is as easy as possible to understand.

What is difficult to understand about...?

while (*s++ = *t++)
;
You can assume that your reader knows the C basics,

No. If you're talking about non toy programs, you can assume that the
reader knows more than the basics. If you don't then you must be
anticipating your code being modified and subsequently distributed by
people not really qualified to so.
and knows how to
program, but you shouldn't necessarily assume that he is comfortable with C
arcana. In particular constructions such as
while(a = b)
which suggest the wrong meaning should be avoided.

I would say 'In contrast...' The meaning of original construct is IMHO
self evident.
 
J

Jarno A Wuolijoki

What is difficult to understand about...?

while (*s++ = *t++)
;

First, there's an off by one error. Second, it doesn't terminate the
destination string.

;)
 
G

goose

Thomas Stegen said:
Given the fact that it is a well known and accepted idiom
it is neither hard to read or hard to debug. First time I saw
it it took me about 1 minute to figure out what this was
doing.

also, the pattern of "while (*src_ptr++ = *dst_ptr++)" is
fairly common, and I personally find it intuitive these days
when looking at code. it tells you (or rather, it /should/) the
intent of the programmer without needing a single comment.

goose,
 
C

CBFalconer

Jarno said:
First, there's an off by one error. Second, it doesn't terminate
the destination string.

No there isn't (an error). Yes it does (terminate). All assuming
the source is a legitimate string and source and destination do
not overlap.
 
C

Christopher Benson-Manica

No there isn't (an error). Yes it does (terminate). All assuming
the source is a legitimate string and source and destination do
not overlap.

And also that s has space for strlen(t)+1 characters.
 
J

John Bode

Jarno A Wuolijoki said:
First, there's an off by one error.
Where?

Second, it doesn't terminate the destination string.

;)

Only if the source string isn't terminated, either.
 
J

Jarno A Wuolijoki

No there isn't (an error). Yes it does (terminate).

And that's supposed to be easy to understand?


*t++; /* "get()" */
*s++=x; /* "put(x)" */
*s++=*t++; /* "put(get())" */

while (tmp=*t++) *s++=tmp;
/* "as long as we can get data, append it to s" */
*s=0;
/* terminate s; */

while (*t) *s++=*t++;
*s=0;
/* "as long as there's data, copy it." */

while (*s++=*t++) ;
/* "as long as we have copied nonzero data, do nothing. perform extra
copy as a side effect of embedding it in the test" */

(of course if you interpret "*s++=*t++" as a routine which returns 0
when it has finished it makes a whole lot more sense..)
 
P

pete

CBFalconer said:
No there isn't (an error). Yes it does (terminate). All assuming
the source is a legitimate string and source and destination do
not overlap.

It depends on how they overlap.
 
M

Malcolm

Jarno A Wuolijoki said:
And that's supposed to be easy to understand?
Exactly. We have a construct that is supposedly "easy to understand",
perfectly acceptable, idiomatic C, and first a newbie posts with "what does
this do" and then another poster mistakes it for a bug.

Most of C is basically the same as any other programming language. Someone
who knows another language will easily understand

int x = 0;

he will also quickly get

for(i=0;i<100;i++)

even though ++ is a pure C idiom.

When it comes to pointers, he has some learning to do. He can quickly pick
up that * is the indirection operator. A bit more difficult is that
*ptr++ increments ptr, rather than *ptr, despite the fact that the ++ is
applied last.

However when we come to

while(*s++ = *t++);

it is a bridge too far for our experienced programmer who only knows a bit
of C. Unless you know, it is deeply counter intutive that = in this context
means "assign" rather than "compare". If he's lucky he will remember the
pointer incrementing and dereference rules, but only just, and this will
make him uncomfortable and unfamiliar with the whole expression. Finally,
using a semi-colon to denote an empty loop is also something that has few
parallels in other languages, and looks like a syntax error.

In short, this expression will make the code harder to read and is likely to
cause trouble. Even an experienced C programmer, though he will not
misinterpret it, will probably take longer to read and understand the
expression and verify that it is correct. This is particularly the case if
it is embedded in a list of other expressions which are also
counter-intutive and difficult to understand.
 
P

pete

Malcolm said:
Even an experienced C programmer, though he will not
misinterpret it, will probably take longer to read and understand the
expression and verify that it is correct.

"... the idiom should be mastered,
because you will see it frequently in C programs."

Mastering the idiom means, that you will recognize it,
and know at a glance, what it means.

If you have not mastered it, then it may be tough.
But the mastery that particular idiom, is more common than not,
among experienced C programmers.

A few snippets for you:

void copyarray(e_type *s1, e_type *s2, size_t nmemb)
{
while (nmemb--) {
*s1++ = *s2++;
}
}

char *squeeze(char *s1, const char *s2)
{
char const* p2;
char *const p1 = s1;

for (p2 = strtok(s1, s2); p2; p2 = strtok( 0, s2)) {
while (*p2) {
*s1++ = *p2++;
}
}

*s1 = '\0';
return p1;
}

static void merge(e_type *base, e_type *buffer, size_t nmemb)
{
if (nmemb > SMALL_MERGE) {
size_t const half = nmemb / 2;
e_type *const middle = base + half;
e_type *const after_buffer = buffer + half;
e_type *const after_array = base + nmemb;
e_type *mid_ptr = middle;

merge(base, buffer, half);
merge(middle, buffer, nmemb - half);
while (GTE(middle, base) && middle != base) {
++base;
}
buffer = after_buffer;
while (base != mid_ptr) {
*--buffer = *--mid_ptr;
}
mid_ptr = middle;
while (middle != base) {
*base++ = GT(buffer, mid_ptr) ? *mid_ptr++ : *buffer++;
}
while (after_buffer != buffer && after_array != mid_ptr) {
*base++ = GT(buffer, mid_ptr) ? *mid_ptr++ : *buffer++;
}
while (after_buffer != buffer) {
*base++ = *buffer++;
}
} else {
si_sort(base, nmemb);
}
}
 

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,769
Messages
2,569,580
Members
45,055
Latest member
SlimSparkKetoACVReview

Latest Threads

Top