Discussion:
And they say C is obscure
(too old to reply)
Peabody
2017-04-09 03:59:40 UTC
Permalink
Raw Message
Sorry, but I just can't find it.

Could someone please explain this:

for(linepos= 0;
linepos < linelen-3; linepos+= 3, dataframelen++)

So this is parsing a TI-TXT file, which looks like this:

@FFE0
FF FF FF FF 14 FC FF FF FF FF 5E FD FF FF FF FF
0E FD E6 F9 28 FD FF FF FF FF FF FF FF FF C2 FC
q

into binary values. So the 3's make sense.

I understand it up until the ", dataframelen++" which seems to have nothing
to do with the FOR loop. It's like "increment linepos by 3, and while you're
at it, go ahead and increment dataframelen too." Am I reading that right?
is that structure allowed in C? Well, obviously it is, but how does anyone
ever get up to speed in this language. More important, how does anyone check
for errors trying to read stuff like this?

And while I'm at it, let me ask how you would create an unsigned byte array
exactly 2048 bytes long, and fill it with FFs.

I guess I need to go to school for this, or give it up and go back to
assembler. It's just really hard trying to understand someone else's code.

Thanks for any help.
Joe Pfeiffer
2017-04-09 04:17:25 UTC
Permalink
Raw Message
Post by Peabody
Sorry, but I just can't find it.
for(linepos= 0;
linepos < linelen-3; linepos+= 3, dataframelen++)
@FFE0
FF FF FF FF 14 FC FF FF FF FF 5E FD FF FF FF FF
0E FD E6 F9 28 FD FF FF FF FF FF FF FF FF C2 FC
q
into binary values. So the 3's make sense.
I understand it up until the ", dataframelen++" which seems to have nothing
to do with the FOR loop. It's like "increment linepos by 3, and while you're
at it, go ahead and increment dataframelen too." Am I reading that right?
is that structure allowed in C? Well, obviously it is, but how does anyone
ever get up to speed in this language. More important, how does anyone check
for errors trying to read stuff like this?
And while I'm at it, let me ask how you would create an unsigned byte array
exactly 2048 bytes long, and fill it with FFs.
I guess I need to go to school for this, or give it up and go back to
assembler. It's just really hard trying to understand someone else's code.
Thanks for any help.
Hazarding a guess since there really isn't enough context to be sure, I
imagine the body of the loop ends up doing some transformation on the
characters at line[linepos] and putting the result in
dataframe[dateframelen] (where the variable names I guessed are almost
certainly wrong, but hopefully helpful in explaining what's happening).

I'm guessing the (not shown) body of the loop is translating a buffer of
hexadecimal values represented in ASCII and separated by spaces into a
buffer of binary bytes.

Filling the buffer you've asked for would look something like

#define BUFSIZ 2048
unsigned char buf[BUFSIZ];
for (int i = 0; i < BUFSIZ; i++)
buf[i] = 0xff;

And the way to come up to speed on the language is, sorry, don't start
with code written by someone trying to be clever.
Peabody
2017-04-09 12:42:05 UTC
Permalink
Raw Message
Joe Pfeiffer says...
Post by Joe Pfeiffer
Post by Peabody
for(linepos= 0;
linepos < linelen-3; linepos+= 3, dataframelen++)
I'm guessing the (not shown) body of the loop is
translating a buffer of hexadecimal values represented
in ASCII and separated by spaces into a buffer of binary
bytes.
Yes, that's exactly what it does. But I found nothing from
searching online that described what C permits in the
inc/dec field of a FOR loop. It appears you can do multiple
things there, but do they have to be increments or
decrements, or could you do anything after the comma?
Post by Joe Pfeiffer
#define BUFSIZ 2048
unsigned char buf[BUFSIZ];
for (int i = 0; i < BUFSIZ; i++)
buf[i] = 0xff;
Thanks. I just thought there might be a shorthand way of
doing that in C.
Post by Joe Pfeiffer
And the way to come up to speed on the language is,
sorry, don't start with code written by someone trying
to be clever.
I guess so. I just thought that code from TI itself for
parsing TI-TXT would be a good source. And I'm sure it is,
but just difficult to follow sometimes.

Thanks for your help.
Barry Schwarz
2017-04-09 14:46:16 UTC
Permalink
Raw Message
On Sun, 09 Apr 2017 07:42:05 -0500, Peabody
Post by Peabody
Yes, that's exactly what it does. But I found nothing from
searching online that described what C permits in the
inc/dec field of a FOR loop. It appears you can do multiple
things there, but do they have to be increments or
decrements, or could you do anything after the comma?
Google for and download n1570, a free and reasonably current copy of
the C11 draft and study the sections that deals with the comma
operator and the for statement.
--
Remove del for email
David Brown
2017-04-09 14:47:21 UTC
Permalink
Raw Message
Post by Peabody
Joe Pfeiffer says...
Post by Joe Pfeiffer
Post by Peabody
for(linepos= 0;
linepos < linelen-3; linepos+= 3, dataframelen++)
I'm guessing the (not shown) body of the loop is
translating a buffer of hexadecimal values represented
in ASCII and separated by spaces into a buffer of binary
bytes.
Yes, that's exactly what it does. But I found nothing from
searching online that described what C permits in the
inc/dec field of a FOR loop. It appears you can do multiple
things there, but do they have to be increments or
decrements, or could you do anything after the comma?
Post by Joe Pfeiffer
#define BUFSIZ 2048
unsigned char buf[BUFSIZ];
for (int i = 0; i < BUFSIZ; i++)
buf[i] = 0xff;
Thanks. I just thought there might be a shorthand way of
doing that in C.
Post by Joe Pfeiffer
And the way to come up to speed on the language is,
sorry, don't start with code written by someone trying
to be clever.
I guess so. I just thought that code from TI itself for
parsing TI-TXT would be a good source. And I'm sure it is,
but just difficult to follow sometimes.
Don't be too sure about that. Often code like this can be very badly
written - unclear, fragile (i.e., highly dependent on specific compilers
and specific settings), and generally written in a hurry by
non-experts. It is common that this sort of thing is written by
beginners at a hardware company like TI - the experts are the people
designing chips, writing deeply embedded firmware, etc. It certainly
will be not be written with "helping beginners" in mind.
Post by Peabody
Thanks for your help.
James Kuyper
2017-04-09 18:42:28 UTC
Permalink
Raw Message
Post by Peabody
Joe Pfeiffer says...
Post by Joe Pfeiffer
Post by Peabody
for(linepos= 0;
linepos < linelen-3; linepos+= 3, dataframelen++)
I'm guessing the (not shown) body of the loop is
translating a buffer of hexadecimal values represented
in ASCII and separated by spaces into a buffer of binary
bytes.
Yes, that's exactly what it does. But I found nothing from
searching online that described what C permits in the
inc/dec field of a FOR loop. It appears you can do multiple
things there, but do they have to be increments or
decrements, or could you do anything after the comma?
The comma is not part of the for-statement, it's part of a comma
expression. "first, second" is an expression that causes "first" to be
executed, then causes "second" to be executed. The expression has a
value which is the same as the value resulting from the execution of
"second". You can use a comma expression almost anywhere in a C program
(though you need to use parenthesis to prevent confusion with any of the
several other ways that commas are used in C). However, in most contexts
it's simpler to replace "result = (first, second)" with "first; result =
second;". A for statement is one of the few locations where it sometimes
actually makes sense to use a comma expression.

The grammar for a for statement is as follows:

for ( clause-1 ; expression-2 ; expression-3 ) statement


clause-1 can be either a declaration or an expression. expression-2 and
expression-3 can be any expression. There are no other restrictions on
clause-1, expression-2, expression-3, or statement. In particular,
there's no requirement that an increment or a decrement appear anywhere
in a for statement.

A for-statement is essentially equivalent to the following code:

{
clause-1;
while(expression-2)
{
statement;
expression-3;
}
}

Both clause-1 and expression-3 are completely optional. If expression-2
is omitted, it is replaced by a non-zero constant. statement is the only
variable part that cannot be omitted. However, it could be the empty
statement ";", which is pretty much the same thing as omitting the
statement.

Among other odd ways I've seen for statements used:
for(unsigned mask = 1; mask; mask <<= 1)

for(struct node *p = start_node; p; p = p->next)

for(double scale = 1.0; scale < MAX_SCALE; scale *= 2.0)
Stefan Ram
2017-04-09 18:48:59 UTC
Permalink
Raw Message
Post by James Kuyper
for ( clause-1 ; expression-2 ; expression-3 ) statement
clause-1 can be either a declaration or an expression.
Unlike in Java, in C, a declaration already /includes/
the final semicolon:

6.7 Declarations
declaration:
declaration-specifiers init-declarator-list_(opt) ;

So, the syntax of the loop is

for ( expression_(opt) ; expression_(opt) ; expression_(opt) ) statement

or

for ( declaration expression_(opt) ; expression_(opt) ) statement

/without/ a semicolon following the declaration.

(This is yet another advantage of function calls:
Their syntax is simpler.)
Keith Thompson
2017-04-09 20:25:20 UTC
Permalink
Raw Message
James Kuyper <***@verizon.net> writes:
[...]
Post by James Kuyper
for ( clause-1 ; expression-2 ; expression-3 ) statement
clause-1 can be either a declaration or an expression. expression-2 and
expression-3 can be any expression. There are no other restrictions on
clause-1, expression-2, expression-3, or statement. In particular,
there's no requirement that an increment or a decrement appear anywhere
in a for statement.
That's not *quite* the actual grammar, but it's probably easier to
understand than the syntax specified in the standard.

The standard's syntax has to be a bit more convoluted to deal with
the semicolon between the first and second clauses; if the first
claus is a declaration, then the semicolon is syntactically part
of the declaration.

Another way to think about it is that the first clause can be either
an expression or a declaration with the semicolon removed.

Bottom line: There are always exactly two semicolons.
--
Keith Thompson (The_Other_Keith) kst-***@mib.org <http://www.ghoti.net/~kst>
Working, but not speaking, for JetHead Development, Inc.
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"
James Kuyper
2017-04-10 02:56:44 UTC
Permalink
Raw Message
Post by Keith Thompson
[...]
Post by James Kuyper
for ( clause-1 ; expression-2 ; expression-3 ) statement
clause-1 can be either a declaration or an expression. expression-2 and
expression-3 can be any expression. There are no other restrictions on
clause-1, expression-2, expression-3, or statement. In particular,
there's no requirement that an increment or a decrement appear anywhere
in a for statement.
That's not *quite* the actual grammar,
That's an exact quote from 6.8.5.3p1. I didn't notice that it differs
from the syntax provided in 6.8.5p1:

for ( expression opt ; expression opt ; expression opt ) statement
for ( declaration expression opt ; expression opt ) statement

6.8.5.3p1 also says "If clause-1 is a declaration ...", implying that
clause-1 could be a declaration, which would necessarily include it's
own semicolon in addition to the one separating clause-1 from
expression-2. That comment is therefore incompatible with the syntax
specified in 6.8.5p1.
Stefan Ram
2017-04-10 04:21:39 UTC
Permalink
Raw Message
Post by James Kuyper
That comment is therefore incompatible with the syntax
specified in 6.8.5p1.
The subject of this thread is:
»And they say C is obscure«;
they may have a point there!

(6.8.5.3 is not a comment in the sense of a non-normative
comment, but seems to be part of the normative text.)
Joe Pfeiffer
2017-04-09 21:18:55 UTC
Permalink
Raw Message
Post by Peabody
Joe Pfeiffer says...
Post by Joe Pfeiffer
Post by Peabody
for(linepos= 0;
linepos < linelen-3; linepos+= 3, dataframelen++)
I'm guessing the (not shown) body of the loop is
translating a buffer of hexadecimal values represented
in ASCII and separated by spaces into a buffer of binary
bytes.
Yes, that's exactly what it does. But I found nothing from
searching online that described what C permits in the
inc/dec field of a FOR loop. It appears you can do multiple
things there, but do they have to be increments or
decrements, or could you do anything after the comma?
Other people have talked about the syntax of the for-loop; the thing to
keep in mind here is that the the clause and expressions in the
parentheses can to all intents and purposes be pretty much anything.
You mentioned the inc/dec field -- not, that's just an arbitrary
expression. You can do virtually anything in there; you can increment,
you can decrement, you can move to the next element of a linked list,
you can call a function that computes pi (which would be a stupid thing
to have there, but the point is you can have anything).
Post by Peabody
Post by Joe Pfeiffer
#define BUFSIZ 2048
unsigned char buf[BUFSIZ];
for (int i = 0; i < BUFSIZ; i++)
buf[i] = 0xff;
Thanks. I just thought there might be a shorthand way of
doing that in C.
Other people have pointed out that calling memset() would be a better
solution than this. They're right.
Post by Peabody
Post by Joe Pfeiffer
And the way to come up to speed on the language is,
sorry, don't start with code written by someone trying
to be clever.
I guess so. I just thought that code from TI itself for
parsing TI-TXT would be a good source. And I'm sure it is,
but just difficult to follow sometimes.
Thanks for your help.
Some of the most horrifying code I've ever come across has been
manufacturers' own code for their own devices. A lot of it is clearly
written by an EE who is an expert at the device, but whose only
knowledge of programming came from a two week boot camp.
Ken Brody
2017-04-10 16:57:40 UTC
Permalink
Raw Message
On 4/9/2017 8:42 AM, Peabody wrote:
[...]
Post by Peabody
Post by Peabody
for(linepos= 0;
linepos < linelen-3; linepos+= 3, dataframelen++)
[...]
Post by Peabody
Yes, that's exactly what it does. But I found nothing from
searching online that described what C permits in the
inc/dec field of a FOR loop. It appears you can do multiple
things there, but do they have to be increments or
decrements, or could you do anything after the comma?
[...]

I think your problem is thinking it's an "increment/decrement field".

The "for" statement simply takes three expressions[1], all of which are
optional. The first is evaluated before the first time through, and the
result discarded; the second is evaluated at the start of each time through,
and if non-zero, the loop is executed; and the third is evaluated at the end
of each time through, with its result being discarded.

While the third expression is typically used to increment/decrement values,
there is no restriction on what the expression can do.

Note, too, that, since all three parts are optional, an omitted "second
expression" is treated as "always true".


[1] Note that the first "expression" can also be a declaration, as in:

for ( int i=0 ; i < 10 ; i++ )
--
Kenneth Brody
Scott Lurndal
2017-04-10 14:46:48 UTC
Permalink
Raw Message
Post by Joe Pfeiffer
Post by Peabody
Sorry, but I just can't find it.
for(linepos= 0;
linepos < linelen-3; linepos+= 3, dataframelen++)
@FFE0
FF FF FF FF 14 FC FF FF FF FF 5E FD FF FF FF FF
0E FD E6 F9 28 FD FF FF FF FF FF FF FF FF C2 FC
q
into binary values. So the 3's make sense.
I understand it up until the ", dataframelen++" which seems to have nothing
to do with the FOR loop. It's like "increment linepos by 3, and while you're
at it, go ahead and increment dataframelen too." Am I reading that right?
is that structure allowed in C? Well, obviously it is, but how does anyone
ever get up to speed in this language. More important, how does anyone check
for errors trying to read stuff like this?
And while I'm at it, let me ask how you would create an unsigned byte array
exactly 2048 bytes long, and fill it with FFs.
I guess I need to go to school for this, or give it up and go back to
assembler. It's just really hard trying to understand someone else's code.
Thanks for any help.
Hazarding a guess since there really isn't enough context to be sure, I
imagine the body of the loop ends up doing some transformation on the
characters at line[linepos] and putting the result in
dataframe[dateframelen] (where the variable names I guessed are almost
certainly wrong, but hopefully helpful in explaining what's happening).
I'm guessing the (not shown) body of the loop is translating a buffer of
hexadecimal values represented in ASCII and separated by spaces into a
buffer of binary bytes.
Filling the buffer you've asked for would look something like
#define BUFSIZ 2048
unsigned char buf[BUFSIZ];
for (int i = 0; i < BUFSIZ; i++)
buf[i] = 0xff;
Although I'd generally write 'memset(buf, 0xff, sizeof(buf));'
luser droog
2017-04-09 14:26:41 UTC
Permalink
Raw Message
Post by Peabody
Sorry, but I just can't find it.
for(linepos= 0;
linepos < linelen-3; linepos+= 3, dataframelen++)
@FFE0
FF FF FF FF 14 FC FF FF FF FF 5E FD FF FF FF FF
0E FD E6 F9 28 FD FF FF FF FF FF FF FF FF C2 FC
q
into binary values. So the 3's make sense.
I understand it up until the ", dataframelen++" which seems to have nothing
to do with the FOR loop. It's like "increment linepos by 3, and while you're
at it, go ahead and increment dataframelen too." Am I reading that right?
is that structure allowed in C? Well, obviously it is, but how does anyone
ever get up to speed in this language. More important, how does anyone check
for errors trying to read stuff like this?
There are 2 things going on here, both of which can be
understood by using the C grammar.

The syntax for a for loop looks like this (ignoring the
distracting complication of using a declaration):

for ( expression; expression; expression )
statement

And an expression can make use of the comma operator
to sequence two sub-expressions:

expression := expression1 , expression2

So, just like you guessed, it's doing 2 things where
/normally/ you might have a single expression that
does just one thing.

HTH
James Kuyper
2017-04-09 18:18:02 UTC
Permalink
Raw Message
On 04/08/2017 11:59 PM, Peabody wrote:
...
Post by Peabody
And while I'm at it, let me ask how you would create an unsigned byte array
exactly 2048 bytes long, and fill it with FFs.
#include <string.h>

unsigned char array[2048];

memset(array, 0xFF, sizeof array);

Note: the #include should be at file scope. The call to memset() must
occur inside a function. The declaration for array could occur either
inside or outside a function.

Functionally, this is identical to the loop that Joe Pfeiffer showed
you. However, it's possible (but not guaranteed) that the call to
memset() may execute significantly faster than that loop - it's quite
unlikely to execute significantly slower.
Stefan Ram
2017-04-09 18:28:54 UTC
Permalink
Raw Message
Post by James Kuyper
Functionally, this is identical to the loop that Joe Pfeiffer showed
you. However, it's possible (but not guaranteed) that the call to
memset() may execute significantly faster than that loop - it's quite
unlikely to execute significantly slower.
In C++, AFAIK function calls are preferred to loops. IIRC,
one reason is that loops are more error prone (they might have
off-by-one errors, or unsigned-loops might never terminate).

Also, a function name can convey the intent of the author,
while a loop has to be analyzed by the reader to understand
what it does.

When one uses a function, OTOH, one has to carefully read
the documentation before writing the call.
Keith Thompson
2017-04-09 20:52:14 UTC
Permalink
Raw Message
Post by Stefan Ram
Post by James Kuyper
Functionally, this is identical to the loop that Joe Pfeiffer showed
you. However, it's possible (but not guaranteed) that the call to
memset() may execute significantly faster than that loop - it's quite
unlikely to execute significantly slower.
In C++, AFAIK function calls are preferred to loops. IIRC,
one reason is that loops are more error prone (they might have
off-by-one errors, or unsigned-loops might never terminate).
Also, a function name can convey the intent of the author,
while a loop has to be analyzed by the reader to understand
what it does.
When one uses a function, OTOH, one has to carefully read
the documentation before writing the call.
There's nothing specific to C++ about any of that.

A call to memset() is generally preferred to an equivalent for loop,
because it's simpler and likely to be faster. Of course you have to
understand what a function does if you're going to call it. Similarly,
if you write an explicit loop you have to understand how the loop works,
including both the syntax and semantics of a "for" loop and the code
used in the body of the loop. Functions are just one case of the need
to understand the code you're writing.
--
Keith Thompson (The_Other_Keith) kst-***@mib.org <http://www.ghoti.net/~kst>
Working, but not speaking, for JetHead Development, Inc.
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"
Richard Bos
2017-04-14 11:48:46 UTC
Permalink
Raw Message
Post by Keith Thompson
Post by Stefan Ram
In C++, AFAIK function calls are preferred to loops. IIRC,
one reason is that loops are more error prone (they might have
off-by-one errors, or unsigned-loops might never terminate).
Also, a function name can convey the intent of the author,
while a loop has to be analyzed by the reader to understand
what it does.
When one uses a function, OTOH, one has to carefully read
the documentation before writing the call.
There's nothing specific to C++ about any of that.
A call to memset() is generally preferred to an equivalent for loop,
because it's simpler and likely to be faster. Of course you have to
understand what a function does if you're going to call it.
It's also relevant, here, that memset() is a Standard function, and one
that can usually be optimised very agressively. If the function is user
code, or less fundamental, the equation can change drastically.

Richard
Ken Brody
2017-04-14 17:36:12 UTC
Permalink
Raw Message
[...]
Post by Richard Bos
Post by Keith Thompson
A call to memset() is generally preferred to an equivalent for loop,
because it's simpler and likely to be faster. Of course you have to
understand what a function does if you're going to call it.
It's also relevant, here, that memset() is a Standard function, and one
that can usually be optimised very agressively. If the function is user
code, or less fundamental, the equation can change drastically.
I have also seem smallish memset() calls inlined to things like a simple
"store a 4-byte zero here, then another 4-byte zero, and then a 2-byte
zero". Much more efficient than any function call plus loop could ever be.
--
Kenneth Brody
Richard Bos
2017-04-20 13:24:45 UTC
Permalink
Raw Message
Post by Ken Brody
[...]
Post by Richard Bos
Post by Keith Thompson
A call to memset() is generally preferred to an equivalent for loop,
because it's simpler and likely to be faster. Of course you have to
understand what a function does if you're going to call it.
It's also relevant, here, that memset() is a Standard function, and one
that can usually be optimised very agressively. If the function is user
code, or less fundamental, the equation can change drastically.
I have also seem smallish memset() calls inlined to things like a simple
"store a 4-byte zero here, then another 4-byte zero, and then a 2-byte
zero". Much more efficient than any function call plus loop could ever be.
Yes, that's exactly the kind of thing I meant with "optimised very
aggressively". Good luck getting your compiler to manage that with your
own functions...

Richard
s***@casperkitty.com
2017-04-20 15:05:13 UTC
Permalink
Raw Message
Post by Richard Bos
Post by Ken Brody
[...]
Post by Richard Bos
Post by Keith Thompson
A call to memset() is generally preferred to an equivalent for loop,
because it's simpler and likely to be faster. Of course you have to
understand what a function does if you're going to call it.
It's also relevant, here, that memset() is a Standard function, and one
that can usually be optimised very agressively. If the function is user
code, or less fundamental, the equation can change drastically.
I have also seem smallish memset() calls inlined to things like a simple
"store a 4-byte zero here, then another 4-byte zero, and then a 2-byte
zero". Much more efficient than any function call plus loop could ever be.
Yes, that's exactly the kind of thing I meant with "optimised very
aggressively". Good luck getting your compiler to manage that with your
own functions...
The godbolt compiler tester doesn't have any gcc versions for the ARM past
5.4.1, but given:

#include <string.h>
#include <stdint.h>
void test1(uint16_t *p)
{
p=(uint16_t*)(uint32_t*)p;
memset(p, 0, 8);
}
void test2(uint16_t *p)
{
for (int i=0; i<4; i++)
p[i]=0;
}

it produces better code for the second than the first. If the object is
known to be suitably aligned, it can produce even better code in the
-fno-strict-aliasing dialect, given:

void test3(uint16_t *p)
{
*(uint64_t*)p = 0;
}

On a typical current production ARM (e.g. Cortex-M0 or M3), the first
version of the code would take 7 half-words of code space and make a call
to memset. The second would take 6 half-words of code space with no
branches, calls, or loops, save for the return at the end). The third
would take four half-words of code space, again with no branches, calls,
or loops.

Perhaps there are newer versions of gcc for the ARM which would do something
decent given the first version of the code, but I've not seen any.
Scott Lurndal
2017-04-20 15:32:35 UTC
Permalink
Raw Message
Post by s***@casperkitty.com
Post by Richard Bos
Post by Ken Brody
[...]
Post by Richard Bos
Post by Keith Thompson
A call to memset() is generally preferred to an equivalent for loop,
because it's simpler and likely to be faster. Of course you have to
understand what a function does if you're going to call it.
It's also relevant, here, that memset() is a Standard function, and one
that can usually be optimised very agressively. If the function is user
code, or less fundamental, the equation can change drastically.
I have also seem smallish memset() calls inlined to things like a simple
"store a 4-byte zero here, then another 4-byte zero, and then a 2-byte
zero". Much more efficient than any function call plus loop could ever be.
Yes, that's exactly the kind of thing I meant with "optimised very
aggressively". Good luck getting your compiler to manage that with your
own functions...
The godbolt compiler tester doesn't have any gcc versions for the ARM past
#include <string.h>
#include <stdint.h>
void test1(uint16_t *p)
{
p=(uint16_t*)(uint32_t*)p;
memset(p, 0, 8);
}
void test2(uint16_t *p)
{
for (int i=0; i<4; i++)
p[i]=0;
}
GCC 6.1 for arm64 produces:

0000000000000000 <test1>:
0: a9be7bfd stp x29, x30, [sp,#-32]!
4: 910003fd mov x29, sp
8: f9000fa0 str x0, [x29,#24]
c: d2800102 mov x2, #0x8 // #8
10: 52800001 mov w1, #0x0 // #0
14: f9400fa0 ldr x0, [x29,#24]
18: 94000000 bl 0 <memset>
1c: d503201f nop
20: a8c27bfd ldp x29, x30, [sp],#32
24: d65f03c0 ret

0000000000000028 <test2>:
28: d10083ff sub sp, sp, #0x20
2c: f90007e0 str x0, [sp,#8]
30: b9001fff str wzr, [sp,#28]
34: 14000009 b 58 <test2+0x30>
38: b9801fe0 ldrsw x0, [sp,#28]
3c: d37ff800 lsl x0, x0, #1
40: f94007e1 ldr x1, [sp,#8]
44: 8b000020 add x0, x1, x0
48: 7900001f strh wzr, [x0]
4c: b9401fe0 ldr w0, [sp,#28]
50: 11000400 add w0, w0, #0x1
54: b9001fe0 str w0, [sp,#28]
58: b9401fe0 ldr w0, [sp,#28]
5c: 71000c1f cmp w0, #0x3
60: 54fffecd b.le 38 <test2+0x10>
64: d503201f nop
68: 910083ff add sp, sp, #0x20
6c: d65f03c0 ret

changing the call to 'memset' -> '__builtin_memset' produces:

0000000000000000 <test1>:
0: d10043ff sub sp, sp, #0x10
4: f90007e0 str x0, [sp,#8]
8: f94007e0 ldr x0, [sp,#8]
c: f900001f str xzr, [x0]
10: d503201f nop
14: 910043ff add sp, sp, #0x10
18: d65f03c0 ret

000000000000001c <test2>:
1c: d10083ff sub sp, sp, #0x20
20: f90007e0 str x0, [sp,#8]
24: b9001fff str wzr, [sp,#28]
28: 14000009 b 4c <test2+0x30>
2c: b9801fe0 ldrsw x0, [sp,#28]
30: d37ff800 lsl x0, x0, #1
34: f94007e1 ldr x1, [sp,#8]
38: 8b000020 add x0, x1, x0
3c: 7900001f strh wzr, [x0]
40: b9401fe0 ldr w0, [sp,#28]
44: 11000400 add w0, w0, #0x1
48: b9001fe0 str w0, [sp,#28]
4c: b9401fe0 ldr w0, [sp,#28]
50: 71000c1f cmp w0, #0x3
54: 54fffecd b.le 2c <test2+0x10>
58: d503201f nop
5c: 910083ff add sp, sp, #0x20
60: d65f03c0 ret
Post by s***@casperkitty.com
it produces better code for the second than the first.
Not if you use __builtin_memset instead of memset.
Post by s***@casperkitty.com
Perhaps there are newer versions of gcc for the ARM which would do something
decent given the first version of the code, but I've not seen any.
see above. Can't speak to ARMv7 object code, but ARMv8 gcc can easily
optimize out the memset.
s***@casperkitty.com
2017-04-20 16:48:19 UTC
Permalink
Raw Message
...
Post by Scott Lurndal
0: d10043ff sub sp, sp, #0x10
4: f90007e0 str x0, [sp,#8]
8: f94007e0 ldr x0, [sp,#8]
c: f900001f str xzr, [x0]
10: d503201f nop
14: 910043ff add sp, sp, #0x10
18: d65f03c0 ret
ARM64 may accommodate unaligned reads, but Cortex-M0 (which is very much
a current-production part) doesn't. I'm not familiar with the ARM64
architecture, but I have no idea why it should be needing to do anything
with the stack.

Here's what gcc 5.4.1 for ARM-32 produces:
[supercat]
Post by Scott Lurndal
Post by s***@casperkitty.com
it produces better code for the second than the first.
Not if you use __builtin_memset instead of memset.
I tried changing memset to __builtin_memset and the 5.4.1 for ARM32 still
generates a call to memset.

test1:
stmfd sp!, {r4, lr}
mov r2, #8
mov r1, #0
bl memset
ldmfd sp!, {r4, lr}
bx lr
test2:
mov r3, #0
strh r3, [r0] @ movhi
strh r3, [r0, #2] @ movhi
strh r3, [r0, #4] @ movhi
strh r3, [r0, #6] @ movhi
bx lr
test3:
mov r2, #0
mov r3, #0
stmia r0, {r2-r3}
bx lr

GCC may work decently on architectures that support unaligned loads and
stores, but manual optimizations seem better on those that don't.
Scott Lurndal
2017-04-20 18:00:31 UTC
Permalink
Raw Message
Post by s***@casperkitty.com
...
Post by Scott Lurndal
0: d10043ff sub sp, sp, #0x10
4: f90007e0 str x0, [sp,#8]
8: f94007e0 ldr x0, [sp,#8]
c: f900001f str xzr, [x0]
10: d503201f nop
14: 910043ff add sp, sp, #0x10
18: d65f03c0 ret
ARM64 may accommodate unaligned reads, but Cortex-M0 (which is very much
a current-production part) doesn't. I'm not familiar with the ARM64
architecture, but I have no idea why it should be needing to do anything
with the stack.
I didn't use -O2. With -O2:

Disassembly of section .text:

0000000000000000 <test1>:
0: f900001f str xzr, [x0]
4: d65f03c0 ret
8: d503201f nop
c: d503201f nop

0000000000000010 <test2>:
10: 7900001f strh wzr, [x0]
14: 7900041f strh wzr, [x0,#2]
18: 7900081f strh wzr, [x0,#4]
1c: 79000c1f strh wzr, [x0,#6]
20: d65f03c0 ret
s***@casperkitty.com
2017-04-20 18:34:49 UTC
Permalink
Raw Message
0000000000000000 <test1>:
0: f900001f str xzr, [x0]
4: d65f03c0 ret
8: d503201f nop
c: d503201f nop

0000000000000010 <test2>:
10: 7900001f strh wzr, [x0]
14: 7900041f strh wzr, [x0,#2]
18: 7900081f strh wzr, [x0,#4]
1c: 79000c1f strh wzr, [x0,#6]
20: d65f03c0 ret

Those are in line with what I'd expect. On architectures where a compiler
can use long stores without considering alignment it's easy to replace
memset/memcpy/memmove with in-line code. Architectures with alignment
restrictions seem to be another story, however. Such things are hardly
uncommon in the embedded world (the Cortex M0 seems to be quite popular, for
example) and I've not seen gcc apply effective chunking optimizations on
such platforms.
Scott Lurndal
2017-04-20 18:41:13 UTC
Permalink
Raw Message
Post by Scott Lurndal
0: f900001f str xzr, [x0]
4: d65f03c0 ret
8: d503201f nop
c: d503201f nop
10: 7900001f strh wzr, [x0]
14: 7900041f strh wzr, [x0,#2]
18: 7900081f strh wzr, [x0,#4]
1c: 79000c1f strh wzr, [x0,#6]
20: d65f03c0 ret
Those are in line with what I'd expect.
And it generated the above code if I used 'memset' instead of '__builtin_memset'
when compiling with -O2.
Gareth Owen
2017-04-09 19:53:54 UTC
Permalink
Raw Message
Post by James Kuyper
...
Post by Peabody
And while I'm at it, let me ask how you would create an unsigned byte array
exactly 2048 bytes long, and fill it with FFs.
#include <string.h>
unsigned char array[2048];
memset(array, 0xFF, sizeof array);
Note: the #include should be at file scope. The call to memset() must
occur inside a function. The declaration for array could occur either
inside or outside a function.
*Warning for Peabody*

void set_to_0xff(char array[2048])
{
memset(array, 0xFF, sizeof array);
}

main()
{
char my_arr[2048];
set_to_0xff(my_arr);
}

will not work. A (IMHO truly horrible but mostly forgiveable)
historical anomaly of the language design.
Malcolm McLean
2017-04-09 20:18:10 UTC
Permalink
Raw Message
Post by Peabody
Sorry, but I just can't find it.
for(linepos= 0;
linepos < linelen-3; linepos+= 3, dataframelen++)
@FFE0
FF FF FF FF 14 FC FF FF FF FF 5E FD FF FF FF FF
0E FD E6 F9 28 FD FF FF FF FF FF FF FF FF C2 FC
q
into binary values. So the 3's make sense.
I understand it up until the ", dataframelen++" which seems to have nothing
to do with the FOR loop. It's like "increment linepos by 3, and while you're
at it, go ahead and increment dataframelen too." Am I reading that right?
is that structure allowed in C? Well, obviously it is, but how does anyone
ever get up to speed in this language. More important, how does anyone check
for errors trying to read stuff like this?
And while I'm at it, let me ask how you would create an unsigned byte array
exactly 2048 bytes long, and fill it with FFs.
I guess I need to go to school for this, or give it up and go back to
assembler. It's just really hard trying to understand someone else's code.
Thanks for any help.
The C for loop is too flexible.

The form is

for(<initialiser expression>; <termination expression>; <loop counter expression>)

almost anything can appear in the expressions, including blanks and
the packaging of several levels of logic.


However most for loops are of the form

for(i=0;i<1<N;i++)

if you break that pattern you should have a very good reason, and
normally you should not use a for (wrap the logic in a while loop
instead). However there is no way of enforcing that style guide.
Keith Thompson
2017-04-09 21:03:26 UTC
Permalink
Raw Message
Malcolm McLean <***@btinternet.com> writes:
[...]
Post by Malcolm McLean
The C for loop is too flexible.
I believe that's a minority opinion.
Post by Malcolm McLean
The form is
for(<initialiser expression>; <termination expression>; <loop counter expression>)
almost anything can appear in the expressions, including blanks and
the packaging of several levels of logic.
That's one of the two forms; the other has a declaration as the first
clause. Yes, each of the three expressions can be any arbitrary
expression, or can be omitted.
Post by Malcolm McLean
However most for loops are of the form
for(i=0;i<1<N;i++)
(Typo: "i<1<N" should be "i<N".)

I'd probably write that loop as:
for (int i = 0; i < N; i ++)
unless I had to worry about pre-C99 compilers that don't support it.

It's likely that most for loops are of a form similar to that. There's
no particular reason *all* of them should be.
Post by Malcolm McLean
if you break that pattern you should have a very good reason, and
normally you should not use a for (wrap the logic in a while loop
instead). However there is no way of enforcing that style guide.
The flexibility means, for example, that you can use the same construct
to iterate over a linked list:

for (node *ptr = head; node != NULL; node = node->next)

that you'd use to iterate over an array. It follows the same general
pattern: an initialization to start the iteration, a condition that
tests whether you've finished, and code to step to the next iteration.
Changing it to a while loop would not be an improvement.
--
Keith Thompson (The_Other_Keith) kst-***@mib.org <http://www.ghoti.net/~kst>
Working, but not speaking, for JetHead Development, Inc.
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"
bartc
2017-04-09 21:56:22 UTC
Permalink
Raw Message
Post by Keith Thompson
[...]
Post by Malcolm McLean
The C for loop is too flexible.
I believe that's a minority opinion.
A minority of at least two then.
Post by Keith Thompson
The flexibility means, for example, that you can use the same construct
for (node *ptr = head; node != NULL; node = node->next)
that you'd use to iterate over an array.
That's the trouble: it can be practically anything. If trying to
understand code (or transcribe into a generic algorithm or whatever) you
have to stop and analyse a for-statement. The header tends to be written
on one line so you also have to scan it looking for commas and
semicolons to properly identify the different parts.

Here's a nice selection from sample code:

for (x0 = 8; x0; --x0) {
for (i = 0, c = nj.comp; i < nj.ncomp; ++i, ++c) {
for (mbx = mby = 0;;) {
for (;*zTok;zTok++){
for(n=1; z[n] && z[n]!=':' && !sqlite3Isspace(z[n]); n++){}
for(i=0, n=1; zFmt[i]; i++, n++){
for(i=j=0; zFmt[i]; i++){
for(i=*pRoot; i>0; i=iNext){
for(toFree=nBlock*16; toFree<(mem3.nPool*16); toFree *= 2){
for(iFullSz=mem5.szAtom, iLogsize=0; iFullSz<nByte; iFullSz *= 2,
iLogsize++){}
for(n=0, j=mem5.aiFreelist[i]; j>=0; j = MEM5LINK(j)->next, n++){}
for(; (x=(*pre))!=0; pre++) *(--bufpt) = x;
for(idx=precision&0xfff, rounder=0.5; idx>0; idx--, rounder*=0.1){}
for(i=n=0; k!=0 && (ch=escarg[i])!=0; i++, k--){
for (workp2 = workp + coll_symbol_length ; workp < workp2 ;)
for (i = 0, j = 0; i < len0 && ! ISALPHA ((unsigned char)mangled[i]);
i += 1, j += 1)
for (acount = 0;; acount++)
for (result = &node->value.answers; *result; result = &(*result)->next)
for (; ; i--, mask >>= 1)
for (; !fake ;)
for (p = &pfile->free_buffs;; p = &(*p)->next)
for (map = &set->maps[set->used - 1]; ! MAIN_FILE_P (map);
map = INCLUDED_FROM (set, map))


Most of these are far better expressed using while, so:

for(n=0, j=mem5.aiFreelist[i]; j>=0; j = MEM5LINK(j)->next, n++){}

becomes:

n=0;
j=mem5.aiFreelist[i];

while (j>=0) {
j=MEM5LINK(j)->next;
++n;
}
--
bartc
David Brown
2017-04-10 07:12:47 UTC
Permalink
Raw Message
Post by bartc
Post by Keith Thompson
[...]
Post by Malcolm McLean
The C for loop is too flexible.
I believe that's a minority opinion.
A minority of at least two then.
Post by Keith Thompson
The flexibility means, for example, that you can use the same construct
for (node *ptr = head; node != NULL; node = node->next)
that you'd use to iterate over an array.
That's the trouble: it can be practically anything. If trying to
understand code (or transcribe into a generic algorithm or whatever) you
have to stop and analyse a for-statement. The header tends to be written
on one line so you also have to scan it looking for commas and
semicolons to properly identify the different parts.
for (x0 = 8; x0; --x0) {
for (i = 0, c = nj.comp; i < nj.ncomp; ++i, ++c) {
for (mbx = mby = 0;;) {
for (;*zTok;zTok++){
for(n=1; z[n] && z[n]!=':' && !sqlite3Isspace(z[n]); n++){}
for(i=0, n=1; zFmt[i]; i++, n++){
for(i=j=0; zFmt[i]; i++){
for(i=*pRoot; i>0; i=iNext){
for(toFree=nBlock*16; toFree<(mem3.nPool*16); toFree *= 2){
for(iFullSz=mem5.szAtom, iLogsize=0; iFullSz<nByte; iFullSz *= 2,
iLogsize++){}
for(n=0, j=mem5.aiFreelist[i]; j>=0; j = MEM5LINK(j)->next, n++){}
for(; (x=(*pre))!=0; pre++) *(--bufpt) = x;
for(idx=precision&0xfff, rounder=0.5; idx>0; idx--, rounder*=0.1){}
for(i=n=0; k!=0 && (ch=escarg[i])!=0; i++, k--){
for (workp2 = workp + coll_symbol_length ; workp < workp2 ;)
for (i = 0, j = 0; i < len0 && ! ISALPHA ((unsigned char)mangled[i]);
i += 1, j += 1)
for (acount = 0;; acount++)
for (result = &node->value.answers; *result; result = &(*result)->next)
for (; ; i--, mask >>= 1)
for (; !fake ;)
for (p = &pfile->free_buffs;; p = &(*p)->next)
for (map = &set->maps[set->used - 1]; ! MAIN_FILE_P (map);
map = INCLUDED_FROM (set, map))
for(n=0, j=mem5.aiFreelist[i]; j>=0; j = MEM5LINK(j)->next, n++){}
n=0;
j=mem5.aiFreelist[i];
while (j>=0) {
j=MEM5LINK(j)->next;
++n;
}
I agree here - I would prefer to see that last one as a while loop. And
the examples you picked are mostly pretty horrible - but then, they were
cherry-picked to be horrible.

The flexibility of C's for loop can be a useful thing, but it can also
be seriously abused. That does not mean the language would have been
better with a "for" syntax restricted to something like BASIC's - it
means people should stop abusing it.
Keith Thompson
2017-04-10 15:22:07 UTC
Permalink
Raw Message
Post by bartc
Post by Keith Thompson
[...]
Post by Malcolm McLean
The C for loop is too flexible.
I believe that's a minority opinion.
A minority of at least two then.
Post by Keith Thompson
The flexibility means, for example, that you can use the same construct
for (node *ptr = head; node != NULL; node = node->next)
that you'd use to iterate over an array.
That's the trouble: it can be practically anything. If trying to
understand code (or transcribe into a generic algorithm or whatever)
you have to stop and analyse a for-statement. The header tends to be
written on one line so you also have to scan it looking for commas and
semicolons to properly identify the different parts.
for (x0 = 8; x0; --x0) {
for (i = 0, c = nj.comp; i < nj.ncomp; ++i, ++c) {
for (mbx = mby = 0;;) {
for (;*zTok;zTok++){
for(n=1; z[n] && z[n]!=':' && !sqlite3Isspace(z[n]); n++){}
for(i=0, n=1; zFmt[i]; i++, n++){
for(i=j=0; zFmt[i]; i++){
for(i=*pRoot; i>0; i=iNext){
for(toFree=nBlock*16; toFree<(mem3.nPool*16); toFree *= 2){
for(iFullSz=mem5.szAtom, iLogsize=0; iFullSz<nByte; iFullSz *= 2,
iLogsize++){}
for(n=0, j=mem5.aiFreelist[i]; j>=0; j = MEM5LINK(j)->next, n++){}
for(; (x=(*pre))!=0; pre++) *(--bufpt) = x;
for(idx=precision&0xfff, rounder=0.5; idx>0; idx--, rounder*=0.1){}
for(i=n=0; k!=0 && (ch=escarg[i])!=0; i++, k--){
for (workp2 = workp + coll_symbol_length ; workp < workp2 ;)
for (i = 0, j = 0; i < len0 && ! ISALPHA ((unsigned char)mangled[i]);
i += 1, j += 1)
for (acount = 0;; acount++)
for (result = &node->value.answers; *result; result = &(*result)->next)
for (; ; i--, mask >>= 1)
for (; !fake ;)
for (p = &pfile->free_buffs;; p = &(*p)->next)
for (map = &set->maps[set->used - 1]; ! MAIN_FILE_P (map);
map = INCLUDED_FROM (set, map))
It isn't, and IMHO it shouldn't be, up to the standard to restrict
what kinds of expressions can appear in a for loop header. It's up
to each programmer.

The vast majority of C for loops I've seen are reasonably
straightforward.

I challenge you to come up with a consistent and reasonable
definition for the for loop that's more restrictive than the
current one. I predict that the resulting wording would be far
more complicated than what's currently in the standard, and that
it would be difficult to understand.

And any such restrictions would not make it the least bit more
difficult to write ugly and convoluted C code. So don't do that.
--
Keith Thompson (The_Other_Keith) kst-***@mib.org <http://www.ghoti.net/~kst>
Working, but not speaking, for JetHead Development, Inc.
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"
bartc
2017-04-10 17:28:43 UTC
Permalink
Raw Message
Post by Keith Thompson
Post by bartc
for (x0 = 8; x0; --x0) {
for (i = 0, c = nj.comp; i < nj.ncomp; ++i, ++c) {
for (mbx = mby = 0;;) {
for (;*zTok;zTok++){
for(n=1; z[n] && z[n]!=':' && !sqlite3Isspace(z[n]); n++){}
for(i=0, n=1; zFmt[i]; i++, n++){
for(i=j=0; zFmt[i]; i++){
for(i=*pRoot; i>0; i=iNext){
for(toFree=nBlock*16; toFree<(mem3.nPool*16); toFree *= 2){
for(iFullSz=mem5.szAtom, iLogsize=0; iFullSz<nByte; iFullSz *= 2,
iLogsize++){}
for(n=0, j=mem5.aiFreelist[i]; j>=0; j = MEM5LINK(j)->next, n++){}
for(; (x=(*pre))!=0; pre++) *(--bufpt) = x;
for(idx=precision&0xfff, rounder=0.5; idx>0; idx--, rounder*=0.1){}
for(i=n=0; k!=0 && (ch=escarg[i])!=0; i++, k--){
for (workp2 = workp + coll_symbol_length ; workp < workp2 ;)
for (i = 0, j = 0; i < len0 && ! ISALPHA ((unsigned char)mangled[i]);
i += 1, j += 1)
for (acount = 0;; acount++)
for (result = &node->value.answers; *result; result = &(*result)->next)
for (; ; i--, mask >>= 1)
for (; !fake ;)
for (p = &pfile->free_buffs;; p = &(*p)->next)
for (map = &set->maps[set->used - 1]; ! MAIN_FILE_P (map);
map = INCLUDED_FROM (set, map))
It isn't, and IMHO it shouldn't be, up to the standard to restrict
what kinds of expressions can appear in a for loop header. It's up
to each programmer.
The vast majority of C for loops I've seen are reasonably
straightforward.
I took a large file of C code at random. I went to line 123,000 and
searched for the next for-loop which was:

for(i = 0; handler_info[i].name != NULL; i++)

Explain to why that can't be written more clearly as a while-loop,
because it certainly isn't the iterative loop that 'for' (not 'forall')
is associated with in other languages:

i = 0;
while (handler_info[i].name) ++i;

In fact, explain to me what the purpose of 'while' is as hardly anyone
seems to use it! Since any while-loop:

while (cond) body

can be written as:

for (; cond ;) body

Hence my remark that you have to analyse every 'for' to identify which
category it belongs to (endless loop, repeat-n-times, loop from 0 to
N-1, loop from N-1 to 0, loop from A to B, simple while, and 'weird').
Post by Keith Thompson
I challenge you to come up with a consistent and reasonable
definition for the for loop that's more restrictive than the
current one. I predict that the resulting wording would be far
more complicated than what's currently in the standard, and that
it would be difficult to understand.
This is the for-loop from Algol-60 (iirc):

for i:=expr until expr [by expr] do body

That's more restrictive that C's, but is is that hard to understand?
Post by Keith Thompson
And any such restrictions would not make it the least bit more
difficult to write ugly and convoluted C code. So don't do that.
Most of my examples above would be difficult to write using such a
restricted for-statement. You'd have to use 'while'. Which would be a
big improvement as now you /know/ any for-statement is a simple
iterative loop, while a while-statement encourages you to set up the
various parts - initialise, condition, increment - vertically rather
than lumped together on one line.

Win-win.
--
bartc
Scott Lurndal
2017-04-10 17:49:17 UTC
Permalink
Raw Message
Post by bartc
I took a large file of C code at random. I went to line 123,000 and
for(i = 0; handler_info[i].name != NULL; i++)
Explain to why that can't be written more clearly as a while-loop,
Clarity is in the eye of the beholder. The for loop is perfectly
clear, particularly with the C90 grammar.
Keith Thompson
2017-04-10 18:50:58 UTC
Permalink
Raw Message
[snip examples of ugly for loops]
Post by bartc
Post by Keith Thompson
It isn't, and IMHO it shouldn't be, up to the standard to restrict
what kinds of expressions can appear in a for loop header. It's up
to each programmer.
The vast majority of C for loops I've seen are reasonably
straightforward.
I took a large file of C code at random. I went to line 123,000 and
for(i = 0; handler_info[i].name != NULL; i++)
Explain to why that can't be written more clearly as a while-loop,
because it certainly isn't the iterative loop that 'for' (not 'forall')
i = 0;
while (handler_info[i].name) ++i;
I find the for loop at least as clear as the while loop. Of the three
clauses, the first initializes the loop, the second is the condition
under which the loop will continue, and the third steps to the next
iteration.

If you'd rather write it as a while loop, you are of course free to do
so. I note that your while loop is equivalent to the for loop only if
the for loop has an empty body. If it doesn't, the "++i;" will be part
of the body of the while loop, and not clearly distinguished from the
rest of the body.

I understand that you find the while loop clearer. I find the for loop
clearer. I don't expect either of us to change our minds.
Post by bartc
In fact, explain to me what the purpose of 'while' is as hardly anyone
while (cond) body
for (; cond ;) body
C *could* have omitted the while loop, or the for loop. It could have
omitted all control structures other than conditional gotos. C's for
loop encapsulates three aspects of loop control that I personally find
useful and clear.

I generally wouldn't use a for loop when the first and third clauses are
omitted; I'd use a while loop. If the first *or* third clause is
omitted, I'd have to consider it on a case-by-case basis.

Now if you assume that a loop with the name "for" has to correspond to
the kind of for loop you'll find in, say, Pascal or Algol, then C's for
loop is going to be confusing. Perhaps you'd find it clearer if it had
a different name?
Post by bartc
Hence my remark that you have to analyse every 'for' to identify which
category it belongs to (endless loop, repeat-n-times, loop from 0 to
N-1, loop from N-1 to 0, loop from A to B, simple while, and 'weird').
And that analysis shouldn't be difficult -- *if* the code is written
clearly. If it's not written clearly, then it doesn't matter what
language construct it uses.
Post by bartc
Post by Keith Thompson
I challenge you to come up with a consistent and reasonable
definition for the for loop that's more restrictive than the
current one. I predict that the resulting wording would be far
more complicated than what's currently in the standard, and that
it would be difficult to understand.
for i:=expr until expr [by expr] do body
That's more restrictive that C's, but is is that hard to understand?
No, it's easy to understand -- and it's far more restrictive than
C's for loop. If you want to restrict C's for loop that severely,
disallowing anything other than stepping through a uniform sequence
of integer values, that's a valid opinion. I disagree, and your
proposal will break existing code. What you propose is not what
C's for loop means.
Post by bartc
Post by Keith Thompson
And any such restrictions would not make it the least bit more
difficult to write ugly and convoluted C code. So don't do that.
Most of my examples above would be difficult to write using such a
restricted for-statement. You'd have to use 'while'. Which would be a
big improvement as now you /know/ any for-statement is a simple
iterative loop, while a while-statement encourages you to set up the
various parts - initialise, condition, increment - vertically rather
than lumped together on one line.
Win-win.
It would break existing code. No such change will ever happen in a
language called "C". Lose-lose.

Again, your opinion that C's for loop is too complicated is perfectly
valid, even though I don't share it. You're free to restrict your own
use as you like, and/or to implement your own preferred ideas in your
own language.

I seriously doubt that there's anything meaningful left to be said.
--
Keith Thompson (The_Other_Keith) kst-***@mib.org <http://www.ghoti.net/~kst>
Working, but not speaking, for JetHead Development, Inc.
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"
bartc
2017-04-10 19:33:27 UTC
Permalink
Raw Message
Post by Keith Thompson
Post by Joe Pfeiffer
i = 0;
while (handler_info[i].name) ++i;
I find the for loop at least as clear as the while loop. Of the three
clauses, the first initializes the loop, the second is the condition
under which the loop will continue, and the third steps to the next
iteration.
But you wouldn't put three, especially disjoint, statements on the same
line; they'd be arranged vertically. (Apart from the slightly liberty I
took above. But there, the ")" is a strong separator; the ";" is a weak
separator especially if the things on each side are not executed
sequentially.)
Post by Keith Thompson
If you'd rather write it as a while loop, you are of course free to do
so. I note that your while loop is equivalent to the for loop only if
the for loop has an empty body.
The original had an empty body; I forgot to show the ";" which was on
the next line.
Post by Keith Thompson
C *could* have omitted the while loop, or the for loop.
It could have omitted the while loop as 'for' can do everything while
can. Especially using:

#define while(x) for (;(x);)

Leaving out 'for' wouldn't have been a great loss, as it is hardly a
proper 'for' statement with the special language support that normally
entails. But it would be inconvenient when you /do/ want a simple
iteration. And for those who do show some restraint and use whichever of
'for' and 'while' is most appropriate.
Post by Keith Thompson
It could have
omitted all control structures other than conditional gotos.
No, there is no good reason for that. Syntax of this kind is the
simplest possible thing to add to a language.

(In my C compiler, support for 'while' adds 30 lines of code to the
program, out of about 18,000. A C99 'for' needed over 100 because it's
fiddly.)
Post by Keith Thompson
C's for
loop encapsulates three aspects of loop control that I personally find
useful and clear.
For an iterative loop, these are aspects you shouldn't need to worry
about. A 'for' /implies/ iteration; you shouldn't have to write it
explicitly!
Post by Keith Thompson
Perhaps you'd find it clearer if it had
a different name?
'for' is misleading, that's for sure.
Post by Keith Thompson
And that analysis shouldn't be difficult -- *if* the code is written
clearly. If it's not written clearly, then it doesn't matter what
language construct it uses.
No, the language can force the issue by not allowing you to write
obscure code, not in loops anyway. If absolutely anything can go inside
a for-loop, then obviously people will take advantage:

for(i=rand(), j=rand(), printf("%d\n",(i+j)/2);0;);

(A weak attempt as I don't have the imagination to do this stuff properly.)
--
bartc
Keith Thompson
2017-04-10 20:06:11 UTC
Permalink
Raw Message
[...]
Post by bartc
Post by Keith Thompson
C *could* have omitted the while loop, or the for loop.
It could have omitted the while loop as 'for' can do everything while
#define while(x) for (;(x);)
Leaving out 'for' wouldn't have been a great loss, as it is hardly a
proper 'for' statement with the special language support that normally
entails.
I think that's the root of your objection. You insist on a "for" loop
being similar to the "for" loop that's seen in Algol and Pascal. It
isn't. It could have been called, say, "iterate" with exactly the same
meaning.

I suggest that your use of the word "proper" has no significance.

The extra flexibility of C's for loop relative to Pascal's is
entirely deliberate. The fact that you don't like it is, yet again,
perfectly valid, but not particularly relevant to anthing other
than your own personal preferences.
Post by bartc
Post by Keith Thompson
It could have
omitted all control structures other than conditional gotos.
No, there is no good reason for that. Syntax of this kind is the
simplest possible thing to add to a language.
I didn't say there would be a good reason. I merely meant that omitting
all control structures other than conditional gotos would in principal
leave us with a language that could express everything C can express.
(The resulting language would not be one that I would care to use.)

[...]
Post by bartc
Post by Keith Thompson
Perhaps you'd find it clearer if it had
a different name?
'for' is misleading, that's for sure.
It misleads you. It doesn't mislead most of the rest of us.

There is no solvable problem here.

[...]
--
Keith Thompson (The_Other_Keith) kst-***@mib.org <http://www.ghoti.net/~kst>
Working, but not speaking, for JetHead Development, Inc.
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"
Gareth Owen
2017-04-10 20:48:53 UTC
Permalink
Raw Message
Post by Keith Thompson
Post by bartc
'for' is misleading, that's for sure.
It misleads you. It doesn't mislead most of the rest of us.
That's because he's an idiot.
Post by Keith Thompson
There is no solvable problem here.
You could stop responding to his idiocy.
bartc
2017-04-10 21:15:33 UTC
Permalink
Raw Message
Post by Keith Thompson
I think that's the root of your objection. You insist on a "for" loop
being similar to the "for" loop that's seen in Algol and Pascal. It
isn't. It could have been called, say, "iterate" with exactly the same
meaning.
I suggest that your use of the word "proper" has no significance.
Have a look at this simple looping task here:

http://rosettacode.org/wiki/Loops/For

Out of 170 languages, just over 30 have C-style for-loop. Nearly 80 have
something that looks like an Algol-style loop. (The other 60 did their
own thing or I couldn't categorise them at a glance.)

The C-style loops were easy to spot; without exception:

* The 'i' outer loop control had to be specified three times

* The increment op had to be specified explicitly

* The loop-terminating condition had to be specified explicitly.

More of a DIY for-loop if you ask me; the language hasn't left much to
do! (This is what a compiler is for; why not use it?)

The looping task here is so common that one would expect a language to
provide a dedicated feature for that. Most of these do, but
unfortunately the more popular ones seem to have gone the C route.

(It doesn't seem to have occurred to anyone (except a few of these
languages) that you can have both a dedicated for-loop /and/ a flexible
'loop' like C's.)
--
bartc
Michael Barry
2017-04-11 01:46:06 UTC
Permalink
Raw Message
Post by bartc
Post by Keith Thompson
I think that's the root of your objection. You insist on a "for" loop
being similar to the "for" loop that's seen in Algol and Pascal. It
isn't. It could have been called, say, "iterate" with exactly the same
meaning.
I suggest that your use of the word "proper" has no significance.
http://rosettacode.org/wiki/Loops/For
Out of 170 languages, just over 30 have C-style for-loop. Nearly 80 have
something that looks like an Algol-style loop. (The other 60 did their
own thing or I couldn't categorise them at a glance.)
* The 'i' outer loop control had to be specified three times
* The increment op had to be specified explicitly
* The loop-terminating condition had to be specified explicitly.
More of a DIY for-loop if you ask me; the language hasn't left much to
do! (This is what a compiler is for; why not use it?)
The looping task here is so common that one would expect a language to
provide a dedicated feature for that. Most of these do, but
unfortunately the more popular ones seem to have gone the C route.
(It doesn't seem to have occurred to anyone (except a few of these
languages) that you can have both a dedicated for-loop /and/ a flexible
'loop' like C's.)
--
bartc
http://rosettacode.org/wiki/99_Bottles_of_Beer#Bottled_Version_2

Mike B. :-)
Scott Lurndal
2017-04-10 21:46:59 UTC
Permalink
Raw Message
Post by Keith Thompson
Post by bartc
Leaving out 'for' wouldn't have been a great loss, as it is hardly a
proper 'for' statement with the special language support that normally
entails.
I think that's the root of your objection. You insist on a "for" loop
being similar to the "for" loop that's seen in Algol and Pascal. It
isn't. It could have been called, say, "iterate" with exactly the same
meaning.
Actually, I consider the C 'for' construct to be a natural
extension of the ALGOL and Pascal FOR constructs. They all
provide an initial condition, a terminal condition and an
optional step condition. Pascal, e.g., limits the
initial condition to be a numeric (or enumeration) which
limits the usefuless of the construct.
bartc
2017-04-10 22:09:00 UTC
Permalink
Raw Message
Post by Scott Lurndal
Post by Keith Thompson
Post by bartc
Leaving out 'for' wouldn't have been a great loss, as it is hardly a
proper 'for' statement with the special language support that normally
entails.
I think that's the root of your objection. You insist on a "for" loop
being similar to the "for" loop that's seen in Algol and Pascal. It
isn't. It could have been called, say, "iterate" with exactly the same
meaning.
Actually, I consider the C 'for' construct to be a natural
extension of the ALGOL and Pascal FOR constructs. They all
provide an initial condition, a terminal condition and an
optional step condition.
I can't see any connection (apart from the use of the "for" keyword). C
provides a general purpose, lower level construct that can emulate a For
statement from those other languages. But it is more effort, is more
error prone, and has to be done manually.

A extension of those other For statements might be more the sorts of
things that Python allows with For: general purpose iteration over the
values in a range or a list. Much more disciplined than the C
counterpart which allows literally anything:

for (i=0,j=1; rand()!=12345; x[++k]='A'){}

What are the start and end values of the loop index? You can't answer
because there is /no/ loop index. And you can't tell how many iterations
this will do.
--
BARTC
Scott Lurndal
2017-04-11 12:40:43 UTC
Permalink
Raw Message
Post by bartc
Post by Scott Lurndal
Actually, I consider the C 'for' construct to be a natural
extension of the ALGOL and Pascal FOR constructs. They all
provide an initial condition, a terminal condition and an
optional step condition.
for (i=0,j=1; rand()!=12345; x[++k]='A'){}
Initial condition: i=0, j=1;
Terminal condition: rand() != 12345
Step condition: x[++k]='A'

It's pretty damn clear.
Post by bartc
What are the start and end values of the loop index? You can't answer
because there is /no/ loop index. And you can't tell how many iterations
this will do.
Nor can you tell, a priori, with "do until" or "while" constructs. So what?
bartc
2017-04-11 13:15:25 UTC
Permalink
Raw Message
Post by Scott Lurndal
Post by bartc
Post by Scott Lurndal
Actually, I consider the C 'for' construct to be a natural
extension of the ALGOL and Pascal FOR constructs. They all
provide an initial condition, a terminal condition and an
optional step condition.
for (i=0,j=1; rand()!=12345; x[++k]='A'){}
Initial condition: i=0, j=1;
Terminal condition: rand() != 12345
Step condition: x[++k]='A'
It's pretty damn clear.
Initial condition: Any gobbledygook
Terminal condition: More gobbleydook
Step condition: Yet more random, unrelated nonsense

Sure, it's clear if you don't care whether those conditions mean
anything or not.
Post by Scott Lurndal
Post by bartc
What are the start and end values of the loop index? You can't answer
because there is /no/ loop index. And you can't tell how many iterations
this will do.
Nor can you tell, a priori, with "do until" or "while" constructs. So what?
Do you agree that C provides only a low level, general purpose version
of those dedicated for-constructs provided in other languages?

A loop with a control variable, a start and end value, needs at least
those three bits of information, plus some denotation that this is a
loop, so four. A typical syntax is:

for i=1,5

Which is six syntactic elements in total.

A C version would be:

for (i=1; i<=5; ++i)

containing 13 elements.But it has the advantage that the language lets
you make errors like this:

for (i=1; i<5; ++j)

Or lets you have fun like rotating the elements around:

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

It's just that some people see this kind of thing as a disadvantage, in
not being able to detect as many errors.
--
bartc
Tim Rentsch
2017-04-26 17:13:09 UTC
Permalink
Raw Message
Post by bartc
Post by Scott Lurndal
Post by Keith Thompson
Post by bartc
Leaving out 'for' wouldn't have been a great loss, as it is
hardly a proper 'for' statement with the special language
support that normally entails.
I think that's the root of your objection. You insist on a "for"
loop being similar to the "for" loop that's seen in Algol and
Pascal. It isn't. It could have been called, say, "iterate" with
exactly the same meaning.
Actually, I consider the C 'for' construct to be a natural
extension of the ALGOL and Pascal FOR constructs. They all
provide an initial condition, a terminal condition and an
optional step condition.
I can't see any connection (apart from the use of the "for"
keyword). C provides a general purpose, lower level construct
that can emulate a For statement from those other languages.
[...]
I think some historical perspective might be in order here. In
"high-level languages", the original iteration construct is DO
loops in FORTRAN. A DO loop steps an iteration control variable
through an arithmetic progression. The original FORTRAN did not
have other looping constructs IIANM - any other kind of loop
needs to be fabricated using IF and GOTO statements.

A few years after FORTRAN came Algol-60. Algol-60 also has just
one kind of looping statement in the language (ie, not counting
the if/goto kind), named 'for' rather than 'DO'. The Algol-60
'for' statement has a controlled variable, like the FORTRAN DO,
but is much richer in terms of loop control: multiple "elements"
are allowed, where each "element" may be a single value, a range
ala FORTRAN DO, or a pair of "recurring expression and 'while'
test", similar to the last two elements of a for() statement in C
(except in Algol the recurring expression is evaluated at the
start of each iteration rather than at the end).

Basic came along about two years after Algol-60, with a 'for'
statement essentially the same as DO in FORTRAN (and no other
looping constructs). It was important that 'for' be simple, both
because Basic itself was designed around being simple, and
because it ran in pretty limited hardware environments. (Later
versions of Basic added other more elaborate kinds of statements,
but they weren't there in the original Basic.)

Two or three years after Basic we see a language at the other end
of the size/complexity spectrum, PL/I. PL/I also has just one
looping construct, which like FORTRAN is named 'DO', but 'DO' in
PL/I is richer (in some ways, not all) than 'for' in Algol.
Notably, the PL/I 'DO' allows combining "while" tests with a
regular arithmetic progression, but also allows "while" tests all
by themselves, with no controlled variable at all. Shortly after
PL/I was introduced (which was 1965?), its 'DO' statement had
still more options, including an Algol-like "recurring
expression" and an 'UNTIL' form that is similar to "while" (with
the test inverted) but with the test at the end of the loop
rather than the beginning - ie, like a do...while() in C.

Several years after PL/I came Pascal, which went back to the
FORTRAN/Basic style of iteration statement, which it also calls
'for'. Pascal uses a separate 'WHILE' statement for loops with
only a test and no controlled variable, and a 'REPEAT' statement
for at-least-once style loops. Needless to say, Pascal chose
simple versions of control constructs in part because it was
intended from the outset as a teaching language.

Disclaimer: all the above from memory and/or checked against
reference material found on the net, but I have not gone back
and checked against the original references in all cases.

I expect that what one thinks of as a "traditional for loop"
depends a lot one's background. My first language was FORTRAN,
followed soon thereafter by PL/I. Somewhere in there I picked up
a little Basic but I never took Basic seriously. By the time
Pascal became the rage I was well along the path of working in
numerous languages, so Pascal wasn't ever anything special for
me. Conversely, those whose first language was Basic or Pascal
probably got used to those simpler versions of 'for' loops
(especially coupled with the 'while' in Pascal) as being the
"traditional" form of iteration construct. But the actual
history is more complicated than that. For me the limited form
of 'for' in Pascal was a special case, because I was well-versed
in PL/I by the time I first saw Pascal. I'm sure other people
have very much the opposite reaction, especially since Pascal
was much more widely learned than PL/I was. Still, before
either of those was Algol-60, whose 'for' looping construct is
decidely more elaborate than the Basic/Pascal-style 'for' loop.
s***@casperkitty.com
2017-04-26 17:38:28 UTC
Permalink
Raw Message
Post by Tim Rentsch
I expect that what one thinks of as a "traditional for loop"
depends a lot one's background. My first language was FORTRAN,
followed soon thereafter by PL/I. Somewhere in there I picked up
a little Basic but I never took Basic seriously. By the time
Pascal became the rage I was well along the path of working in
numerous languages, so Pascal wasn't ever anything special for
me. Conversely, those whose first language was Basic or Pascal
probably got used to those simpler versions of 'for' loops
(especially coupled with the 'while' in Pascal) as being the
"traditional" form of iteration construct. But the actual
history is more complicated than that. For me the limited form
of 'for' in Pascal was a special case, because I was well-versed
in PL/I by the time I first saw Pascal. I'm sure other people
have very much the opposite reaction, especially since Pascal
was much more widely learned than PL/I was. Still, before
either of those was Algol-60, whose 'for' looping construct is
decidely more elaborate than the Basic/Pascal-style 'for' loop.
From what I understand, although FORTRAN allowed loops to be written as
either

TOTAL = 0
I=1
1 TOTAL = TOTAL + ARR(I)
I=I+1
IF I .LE. 100 THEN 1

or as

TOTAL = 0
DO 1 I=1,100
TOTAL = TOTAL + ARR(I)
1 CONTINUE

compilers would not be expected to generate the same code for both. A good
compiler would be expected to perform strength reduction on the evaluation
of ARR(I) on any platform where it would be advantageous to do so, but such
optimizations would not be expected given the former construct.

Although PL/I added a lot of functionality to its FOR loops, I think it
maintained a requirement that code not alter the control variable within
the loop. A multi-pass compiler could use one pass to determine which
control variables are definitely not modified within a loop and apply
optimizations based upon that, but languages which forbid changes to
control variables within a loop wouldn't need to scan code for such
changes before applying optimizations.

Is my understanding correct?
s***@casperkitty.com
2017-04-10 22:23:44 UTC
Permalink
Raw Message
Post by Scott Lurndal
Actually, I consider the C 'for' construct to be a natural
extension of the ALGOL and Pascal FOR constructs. They all
provide an initial condition, a terminal condition and an
optional step condition. Pascal, e.g., limits the
initial condition to be a numeric (or enumeration) which
limits the usefuless of the construct.
I'd consider the PL/I form as more of a natural extension; it allows loops
to include multiple ranges, processed in sequence, with a compiler figuring
out how best to handle them.

Otherwise, the style of loop used in Pascal or FORTRAN allows for strength
reductions to be performed in even a single-pass-plus-backpatching compiler
even before it has analyzed the entire content of a loop. If code branches
out of the middle of a loop on the first iteration such strength reduction
might be counter-productive, but a compiler wouldn't have to worry about
whether a loop's control variable might get changed mid-loop in ways that
would cause already-generated code to execute incorrectly on later passes
of the loop.
Richard Bos
2017-04-14 11:51:18 UTC
Permalink
Raw Message
Post by Keith Thompson
Post by bartc
Leaving out 'for' wouldn't have been a great loss, as it is hardly a
proper 'for' statement with the special language support that normally
entails.
I think that's the root of your objection. You insist on a "for" loop
being similar to the "for" loop that's seen in Algol and Pascal.
BASIC. You're trying to argue with someone who pretends to understand
only BASIC.
Post by Keith Thompson
Post by bartc
'for' is misleading, that's for sure.
It misleads you.
Not even that.
Post by Keith Thompson
There is no solvable problem here.
There is: you're being trolled, and the solution is for you not to let
yourself be trolled.

Richard
bartc
2017-04-14 12:14:28 UTC
Permalink
Raw Message
Post by Richard Bos
Post by Keith Thompson
Post by bartc
Leaving out 'for' wouldn't have been a great loss, as it is hardly a
proper 'for' statement with the special language support that normally
entails.
I think that's the root of your objection. You insist on a "for" loop
being similar to the "for" loop that's seen in Algol and Pascal.
BASIC. You're trying to argue with someone who pretends to understand
only BASIC.
Post by Keith Thompson
Post by bartc
'for' is misleading, that's for sure.
It misleads you.
Not even that.
Post by Keith Thompson
There is no solvable problem here.
There is: you're being trolled, and the solution is for you not to let
yourself be trolled.
And people here can continue to delude themselves that C's 'for' is
superior in all ways to those of any other language.

But you can apply quantitative measures that are independent of anyone's
subjective opinions, or whether you think that pointing out perceived
deficiencies (to people who seem to have fingers in their ears), is
'trolling'.

For one, just count the number of tokens that are needed to express a
simple loop, and the number of undetectable ways it can go wrong. Then
do the same with any Basic, Algol, Pascal, Ada or Fortran equivalent.

Sorry, but these facts would be obvious to a child.
--
bartc
s***@casperkitty.com
2017-04-14 17:42:39 UTC
Permalink
Raw Message
Post by bartc
For one, just count the number of tokens that are needed to express a
simple loop, and the number of undetectable ways it can go wrong. Then
do the same with any Basic, Algol, Pascal, Ada or Fortran equivalent.
C's for loop does have one good and useful feature I've not seen in any
other language: an easy choice of whether the end value should be included
or excluded. For the common scenario of a loop which needs to stop one
short of an object's length, there is some benefit to:

for (int i=0; i<length; i++)

versus

For i As Integer = 0 To length - 1

The C-style version needs slightly more tokens because VB.NET defaults to
a step size of 1, and C regards the opening parenthesis as a separate token
from "for", even though it conveys no useful information and is included for
visual balance with the closing parenthesis that separates the last clause
from the body of the loop.

That having been said, such a feature could be provided in other styles of
loop e.g. by using a syntax like:

For i As Integer = 0 Before length

though I've not seen other languages do that.
bartc
2017-04-14 18:04:35 UTC
Permalink
Raw Message
Post by s***@casperkitty.com
Post by bartc
For one, just count the number of tokens that are needed to express a
simple loop, and the number of undetectable ways it can go wrong. Then
do the same with any Basic, Algol, Pascal, Ada or Fortran equivalent.
C's for loop does have one good and useful feature I've not seen in any
other language: an easy choice of whether the end value should be included
or excluded. For the common scenario of a loop which needs to stop one
for (int i=0; i<length; i++)
versus
For i As Integer = 0 To length - 1
Yes, that point is rarely brought up. Most of those other languages are
1-based or any-based, not purely 0-based.

That makes the 'for i=a to b' form awkward as it iterates over an
inclusive range.
Post by s***@casperkitty.com
The C-style version needs slightly more tokens because VB.NET defaults to
a step size of 1, and C regards the opening parenthesis as a separate token
from "for", even though it conveys no useful information and is included for
visual balance with the closing parenthesis that separates the last clause
from the body of the loop.
If you exclude parentheses, there are still more tokens, because 'i' is
specified three times; the '<' is needed, and so is '++'.
Post by s***@casperkitty.com
That having been said, such a feature could be provided in other styles of
For i As Integer = 0 Before length
though I've not seen other languages do that.
I've also thought of using a different keyword ('upto' for example), but
the need isn't as great, for example I can say (in one language):

for i in A ...

and it will pick up the bounds of A, which might be anything including
0..N-1. While Python allows:

for i in range(N) # 0 .. N-1
for i in range(A,B) # A .. B-1

Or sometimes you just say: forall x in A; the index doesn't figure at all.

So there are several possibilities that are a little higher level than
the basic 'for' iterating over A-to-B. C's is lower level so there is
less language help if you get it wrong:

for (i=0; i<=sizeof(A)/sizeof(B[0]); ++j) ...
--
bartc
Ben Bacarisse
2017-04-14 20:43:21 UTC
Permalink
Raw Message
***@casperkitty.com writes:
<snip>
Post by s***@casperkitty.com
That having been said, such a feature could be provided in other styles of
For i As Integer = 0 Before length
though I've not seen other languages do that.
(loop for i from 1 to 10 sum i)
55
Post by s***@casperkitty.com
(loop for i from 1 below 10 sum i)
45
--
Ben.
Stefan Ram
2017-04-14 22:09:43 UTC
Permalink
Raw Message
Newsgroups: comp.lang.c,comp.lang.c++
Post by s***@casperkitty.com
That having been said, such a feature could be provided in other styles of
For i As Integer = 0 Before length
though I've not seen other languages do that.
(loop for i from 1 to 10 sum i)
55
Post by s***@casperkitty.com
(loop for i from 1 below 10 sum i)
45
C++ (after appropriate definitions):

int main()
{
auto sum { 0 };

for( auto const i : from{ 1, below( 3 )} )sum += i;
::std::cout << sum << '\n'; }

. And, BTW, the variable declaration and the whole
loop are being compiled here into just

movl $3, %edx

, that is, all the looping is done at compile time!

However, my current, simplistic, definitions are not
prepared for other increments than »+1«. (See full
C++ code at the end of this post.)

JavaScript is closer to Lisp, so you can get the value
of the sum /as the value of the loop/ in JavaScript,
just as in Common Lisp.

function * from_below( from, top )
{ let i = from; while ( i < top )yield i++; }

console.log
( eval( "sum = 0; for( let i of from_below( 1, 3 ))sum += i;" ));

(prints »3«).

Full C++ source code:

#include <initializer_list>
#include <iostream>
#include <ostream>

struct intref
{ int i = 0;
constexpr explicit intref( int const i ): i{ i } {}
constexpr int operator * () const { return i; }
constexpr intref & operator ++ () { ++i; return *this; }
constexpr bool operator != ( intref const other ) const
{ return this->i != other.i; }};

struct from
{ intref const first;
intref const top;
constexpr from( int const first, int const top ):
first{ first }, top{ top } {}
constexpr intref const begin() const { return first; }
constexpr intref const end() const { return top; }};

constexpr int below( int const i )
{ return i; }

constexpr int including( int const i )
{ return i + 1; }

int main()
{ auto sum { 0 };
for( auto const i : from{ 1, below( 3 )} )sum += i;
::std::cout << sum << '\n'; }

. I am not an experienced writer of C++ classes, so
I appreciate all comments on my C++ source code with a
Followup-To header for the newsgroup comp.lang.c++.

My most frequent error when summing up, is forgetting to
initialize the sum variable. Using »auto« above means that
I can't forget this!

Of course, one could define the abstractions so as to
force the user to use one of »below« or »including«.

Newsgroups: comp.lang.c,comp.lang.c++
Tim Rentsch
2017-04-26 18:02:52 UTC
Permalink
Raw Message
[...] people here can continue to delude themselves that C's 'for' is
superior in all ways to those of any other language.
No one here is saying that, nor do they think it. What is
the point of misprepresenting that?
Gareth Owen
2017-04-26 18:05:57 UTC
Permalink
Raw Message
Post by Tim Rentsch
[...] people here can continue to delude themselves that C's 'for' is
superior in all ways to those of any other language.
No one here is saying that, nor do they think it. What is
the point of misprepresenting that?
Trolls gotta troll
Keith Thompson
2017-04-26 19:02:58 UTC
Permalink
Raw Message
Post by Gareth Owen
Post by Tim Rentsch
[...] people here can continue to delude themselves that C's 'for' is
superior in all ways to those of any other language.
No one here is saying that, nor do they think it. What is
the point of misprepresenting that?
Trolls gotta troll
You're not helping.
--
Keith Thompson (The_Other_Keith) kst-***@mib.org <http://www.ghoti.net/~kst>
Working, but not speaking, for JetHead Development, Inc.
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"
Gareth Owen
2017-04-26 20:55:20 UTC
Permalink
Raw Message
Post by Keith Thompson
Post by Gareth Owen
Post by Tim Rentsch
[...] people here can continue to delude themselves that C's 'for' is
superior in all ways to those of any other language.
No one here is saying that, nor do they think it. What is
the point of misprepresenting that?
Trolls gotta troll
You're not helping.
Perhaps not, but do you believe attempting to reason with him is? Have
you seen any improvement in his behaviour, or his ability to comprehend
that his is not the only valid opinion. Do you think he posts in this
group to engage in rational discourse, or to provoke people like you?

Answer making reference to i) his claim above and ii) his claim that
failure to support $ in a variable name meant C was "crippled" .

You are free to ignore the myriad of stupid things he's said, but please
don't deny they exist.

At least my response has the benefit of brevity.
bartc
2017-04-26 23:15:24 UTC
Permalink
Raw Message
Post by Gareth Owen
Do you think he posts in this
group to engage in rational discourse
You certainly don't. Unless making jibes, insulting posters and bullying
counts as rational discourse.
Tim Rentsch
2017-04-27 20:23:17 UTC
Permalink
Raw Message
Post by Gareth Owen
Post by Keith Thompson
Post by Gareth Owen
Post by Tim Rentsch
[...] people here can continue to delude themselves that C's 'for' is
superior in all ways to those of any other language.
No one here is saying that, nor do they think it. What is
the point of misprepresenting that?
Trolls gotta troll
You're not helping.
Perhaps not, but do you believe attempting to reason with him is?
I have found that it does, sometimes.
Post by Gareth Owen
Have
you seen any improvement in his behaviour, or his ability to comprehend
that his is not the only valid opinion.
Generally in responding to his posts I think it helps to stay well
away from opinion and as much as possible limit my comments to
facts. In cases where I do have a non-fact to offer, I try to
phrase it as a possible point of view, and not try to convince
him of anything.
Post by Gareth Owen
Do you think he posts in this
group to engage in rational discourse, or to provoke people like you?
Oh, probably not either one, at least not primarily. He posts to
blow off steam, because something is frustrating him. Taking
this viewpoint has let me deal with his remarks more calmly.
Post by Gareth Owen
Answer making reference to i) his claim above and ii) his claim that
failure to support $ in a variable name meant C was "crippled" .
You are free to ignore the myriad of stupid things he's said, but please
don't deny they exist.
His statements often do take a brisk run into hyperbole,
I'll grant you that.
Post by Gareth Owen
At least my response has the benefit of brevity.
I think I understand your reaction, and for a while I had the
same reaction myself. Not sure what happened to change that,
but I think the change has been one for the better, both for
me and for the group at large (including Bart).
Gareth Owen
2017-04-14 17:12:20 UTC
Permalink
Raw Message
Post by Richard Bos
Post by Keith Thompson
There is no solvable problem here.
There is: you're being trolled, and the solution is for you not to let
yourself be trolled.
Worth repeating.
bartc
2017-04-14 17:37:16 UTC
Permalink
Raw Message
Post by Gareth Owen
Post by Richard Bos
Post by Keith Thompson
There is no solvable problem here.
There is: you're being trolled, and the solution is for you not to let
yourself be trolled.
Worth repeating.
FWIW my own opinion is that you more of a troll than anyone else at the
minute (that is, of those who are not obviously nutters, or bots).

Let's see, you last post was:

"Malcolm is incapable of distinguishing between his preferences and
Platonic ideals. Its kind of his thing."

And before:

"That's because he's an idiot."

And:

"will not work. A (IMHO truly horrible but mostly forgiveable)
historical anomaly of the language design."

Gasp! An actual technical comment about C. And not only a comment, but a
criticism.

And, apparently back on form:

"and honestly I have no idea why so many non-idiots
are still arguing with him. He's 'fir' with better grammar."

"Yes, but they're not morons."

"Don't forget the reverse vampires"

"The working of his mind is not something that mortals should ponder."

Thank you for your valuable contributions.
GOTHIER Nathan
2017-04-10 22:03:03 UTC
Permalink
Raw Message
On Mon, 10 Apr 2017 20:33:27 +0100
Post by bartc
No, there is no good reason for that. Syntax of this kind is the
simplest possible thing to add to a language.
I disagree. The basic syntax for loops is the combination of label and goto.

Actually C is no more than a macro assembler.
Malcolm McLean
2017-04-10 21:10:31 UTC
Permalink
Raw Message
Post by Keith Thompson
Again, your opinion that C's for loop is too complicated is perfectly
valid, even though I don't share it. You're free to restrict your own
use as you like, and/or to implement your own preferred ideas in your
own language.
Not too complicated. Too flexible. Part of the reason is that putting
restrictions in what can be allowed in the different places actually
puts more burden on the compiler.

But code like this

for(i = 0, j = init_value();; k ? ++i : j = step_value(j,k))

is hard to understand. There's some tricky logic going on with the
i's and j's, and a for loop just isn't the place to document that.

If C's for had the form

for(counter = init_value to end_value, step increment)

like Basic then you would always have a concept of "the loop's
counting variable" which is the main purpose of a for loop.
m***@gmail.com
2017-04-11 15:41:30 UTC
Permalink
Raw Message
Post by Malcolm McLean
If C's for had the form
for(counter = init_value to end_value, step increment)
like Basic then you would always have a concept of "the loop's
counting variable" which is the main purpose of a for loop.
So you'd rather it wasn't able to be used to (for example) traverse
a linked list - chacun a son gout, I suppose.
s***@casperkitty.com
2017-04-11 15:58:10 UTC
Permalink
Raw Message
Post by m***@gmail.com
So you'd rather it wasn't able to be used to (for example) traverse
a linked list - chacun a son gout, I suppose.
Many languages have a form of iteration loop which is expressly restricted
to code where the control variable will iterate through a pre-determined
sequence of values. In C, the code:

for (int i=0; i<20; i++)

can either mark the start of a loop in which "i" will iterate sequentially
through the values 0..19, or it might mark the start of a looping construct
where "i" ends up getting changed to an arbitrary sequence of values. Having
a construct which would tell someone reading the code "This variable will
proceed through these values without deviation" without them having to search
for anything that might modify the variable would be helpful. Perhaps C
could add a special rule which would say that if a variable is declared as
"const" within the first clause of a "for" header, that qualifier would
become effective only once the loop body had begun, so that

for (const int i=0; i<20; i++) {...}

would say that within the first pass of the loop "i" would be treated as a
const int equal to 0, within the second pass, it would be treated as a const
int equal to 1, etc. and a compiler would be free to perform strength
reduction involving "i" even if e.g. a program did something like:

writeData(myStream, &i, sizeof i);

which would otherwise compel a compiler to assume that "i" might have been
modified by that or any subsequent outside function calls.
Malcolm McLean
2017-04-11 16:06:30 UTC
Permalink
Raw Message
Post by m***@gmail.com
Post by Malcolm McLean
If C's for had the form
for(counter = init_value to end_value, step increment)
like Basic then you would always have a concept of "the loop's
counting variable" which is the main purpose of a for loop.
So you'd rather it wasn't able to be used to (for example) traverse
a linked list - chacun a son gout, I suppose.
Ideally you'd have a rule that a for loop must be of the form

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

(with only i, ii, iii, iv allowed as counting variables)

except in the case of iterating over a linked list


for(ptr = head; ptr != NULL; ptr = ptr->next)

but no compiler can enforce that. However we know that the Basic form
form

for var = 1 to N step 2

works reasonably well. And it forces you to have a loop counter.
Scott Lurndal
2017-04-11 16:46:08 UTC
Permalink
Raw Message
Post by Malcolm McLean
Post by m***@gmail.com
Post by Malcolm McLean
If C's for had the form
for(counter = init_value to end_value, step increment)
like Basic then you would always have a concept of "the loop's
counting variable" which is the main purpose of a for loop.
So you'd rather it wasn't able to be used to (for example) traverse
a linked list - chacun a son gout, I suppose.
Ideally you'd have a rule that a for loop must be of the form
Ideally? As per whose ideals?
Post by Malcolm McLean
for(i=0;i<N;i++)
Gareth Owen
2017-04-11 18:02:21 UTC
Permalink
Raw Message
Post by Scott Lurndal
Post by Malcolm McLean
Ideally you'd have a rule that a for loop must be of the form
Ideally? As per whose ideals?
Malcolm is incapable of distinguishing between his preferences and
Platonic ideals. Its kind of his thing.
Richard Bos
2017-04-14 11:59:41 UTC
Permalink
Raw Message
Post by m***@gmail.com
Post by Malcolm McLean
If C's for had the form
for(counter = init_value to end_value, step increment)
like Basic then you would always have a concept of "the loop's
counting variable" which is the main purpose of a for loop.
So you'd rather it wasn't able to be used to (for example) traverse
a linked list - chacun a son gout, I suppose.
Of course not! No, we'd have a special FORLIST statement that allowed
you to traverse linked lists. And a FORFILE to allow us to easily and
quickly run through the characters in a file. And a FORTREE to run
through a tree - there would be special syntax, of course, to allow
pre-, post- and in-order traversal, of course, _and_ a special keyword
to specify the kind of tree. And a FOREACH. And a FOR2D and a FOR3D.

It would all, of course, be much less complicated than C. And you'd
still be f*@#&d if you wanted to loop through the data you get from a
database connection.

Richard
Tim Rentsch
2017-04-26 17:59:59 UTC
Permalink
Raw Message
Post by Keith Thompson
[examples]
It isn't, and IMHO it shouldn't be, up to the standard to restrict
what kinds of expressions can appear in a for loop header. It's up
to each programmer.
The vast majority of C for loops I've seen are reasonably
straightforward.
I took a large file of C code at random. I went to line 123,000 and
for(i = 0; handler_info[i].name != NULL; i++)
Explain to why that can't be written more clearly as a while-loop,
[...]
Most loops follow the same general pattern:

there is a simple initialization, to establish the loop
invariant for the base case;

there is a simple test to be performed at the start of each
iteration, to see if all cases have been covered;

there is general code in the loop body that "enlarges" the
loop invariant from the already covered cases to include an
additional case; and

there is a fairly simple update to advance the program state
that shows which cases have been covered.

A for() loop in C recognizes this general pattern, providing
slots for the three simple items, leaving the one larger case for
the body of the loop. One advantage to writing the loop shown
above as a for() loop is to establish that it is following the
common general pattern, and to make it easy to pick those out.
Using while() doesn't do that. Of course that isn't the only
consideration, and other factors (including personal preference)
may tip the decision one way or the other. The point is the
two choices here (ie, between for() and while()) each have their
own plusses and minuses - it isn't all one or all the other.
In fact, explain to me what the purpose of 'while' is as hardly
anyone seems to use it!
That's silly. I think most code uses for() loops more often than
while() loops, but certainly while() is used extensively (I
measured while() as roughly 1/3 as often as for() on the average,
over several millions lines of various open-source C projects).

Most loops are easily written as for() loops precisely because
the for() statement was chosen to accommodate the general pattern
that most loops fall into. The reason for having while() is to
deal with loops that do /not/ fall into that pattern. But there
aren't as many of those, so we expect to see it less often.
bartc
2017-04-27 20:40:43 UTC
Permalink
Raw Message
Post by Tim Rentsch
Post by bartc
In fact, explain to me what the purpose of 'while' is as hardly
anyone seems to use it!
That's silly. I think most code uses for() loops more often than
while() loops, but certainly while() is used extensively (I
measured while() as roughly 1/3 as often as for() on the average,
over several millions lines of various open-source C projects).
On my current project, the C source has 60 'for' statements and 150
'while' statements. But this is a program that only ever uses 'for' to
iterate over A to B.

The advantage (for me when I look at my own code), is I know instantly
that a for is a[n iterative] for, and not a while masquerading as a for,
or some other kind of beast entirely.
Post by Tim Rentsch
Most loops are easily written as for() loops
Including all while loops:

while (cond) {}

is equivalent to:

for (;cond;) {}

Both use exactly the same number of characters. Hence my remark that
while isn't really needed, especially considering my observation that
what ought to be while loops are often written as for-loops anyway.

precisely because
Post by Tim Rentsch
the for() statement was chosen to accommodate the general pattern
that most loops fall into. The reason for having while() is to
deal with loops that do /not/ fall into that pattern.
No, for the reason above. The reason /ought/ to be so that obvious
while-loops are written as whiles, and it is then clear at a glance what
we're dealing with. But that very often doesn't happen.
Post by Tim Rentsch
Post by bartc
[...] people here can continue to delude themselves that C's 'for' is
superior in all ways to those of any other language.
No one here is saying that, nor do they think it. What is
the point of misrepresenting that?
Post by bartc
The C for loop is too flexible. [...]
What Malcolm means is that the C for loop is too flexible for
someone who is as brilliant as he is. For those of us who aren't
in his league, the flexibility of for() in C is seen as being
more an advantage than it is a disadvantage.
Plus other comments (from others) along the lines of, Those who
criticise C's 'for' or find elaborate uses of it hard to understand,
ought to stick to Basic.
--
bartc
Tim Rentsch
2017-05-02 12:17:05 UTC
Permalink
Raw Message
Post by bartc
Post by Tim Rentsch
Post by bartc
In fact, explain to me what the purpose of 'while' is as hardly
anyone seems to use it!
That's silly. I think most code uses for() loops more often than
while() loops, but certainly while() is used extensively (I
measured while() as roughly 1/3 as often as for() on the average,
over several millions lines of various open-source C projects).
On my current project, the C source has 60 'for' statements and 150
while' statements. But this is a program that only ever uses 'for' to
iterate over A to B.
The advantage (for me when I look at my own code), is I know instantly
that a for is a[n iterative] for, and not a while masquerading as a
for, or some other kind of beast entirely.
Post by Tim Rentsch
Most loops are easily written as for() loops
while (cond) {}
for (;cond;) {}
Both use exactly the same number of characters. Hence my remark that
while isn't really needed, especially considering my observation that
what ought to be while loops are often written as for-loops anyway.
precisely because
Post by Tim Rentsch
the for() statement was chosen to accommodate the general pattern
that most loops fall into. The reason for having while() is to
deal with loops that do /not/ fall into that pattern.
No, for the reason above. The reason /ought/ to be so that obvious
while-loops are written as whiles, and it is then clear at a glance
what we're dealing with. But that very often doesn't happen.
We are talking about different things here. What I am talking
about is some C language constructs (in particular for(), and
also while() as most C programmers see them. If you want to see
these constructs differently that's up to you, but it isn't what
I was talking about.
Post by bartc
Post by Tim Rentsch
Post by bartc
[...] people here can continue to delude themselves that C's 'for' is
superior in all ways to those of any other language.
No one here is saying that, nor do they think it. What is
the point of misrepresenting that?
Post by bartc
The C for loop is too flexible. [...]
What Malcolm means is that the C for loop is too flexible for
someone who is as brilliant as he is. For those of us who aren't
in his league, the flexibility of for() in C is seen as being
more an advantage than it is a disadvantage.
What I did say is that the flexibility of for() in C is seen [ie,
by myself, and many other C programmers] as being more an
advantage than it is a disadvantage. What I did /not/ say that C's
'for' is superior in all ways to those of any other language. I
hope you understand that those two statements are quite different.
David Kleinecke
2017-05-03 19:50:44 UTC
Permalink
Raw Message
Post by Tim Rentsch
Post by bartc
Post by Tim Rentsch
Post by bartc
In fact, explain to me what the purpose of 'while' is as hardly
anyone seems to use it!
That's silly. I think most code uses for() loops more often than
while() loops, but certainly while() is used extensively (I
measured while() as roughly 1/3 as often as for() on the average,
over several millions lines of various open-source C projects).
On my current project, the C source has 60 'for' statements and 150
while' statements. But this is a program that only ever uses 'for' to
iterate over A to B.
The advantage (for me when I look at my own code), is I know instantly
that a for is a[n iterative] for, and not a while masquerading as a
for, or some other kind of beast entirely.
Post by Tim Rentsch
Most loops are easily written as for() loops
while (cond) {}
for (;cond;) {}
Both use exactly the same number of characters. Hence my remark that
while isn't really needed, especially considering my observation that
what ought to be while loops are often written as for-loops anyway.
precisely because
Post by Tim Rentsch
the for() statement was chosen to accommodate the general pattern
that most loops fall into. The reason for having while() is to
deal with loops that do /not/ fall into that pattern.
No, for the reason above. The reason /ought/ to be so that obvious
while-loops are written as whiles, and it is then clear at a glance
what we're dealing with. But that very often doesn't happen.
We are talking about different things here. What I am talking
about is some C language constructs (in particular for(), and
also while() as most C programmers see them. If you want to see
these constructs differently that's up to you, but it isn't what
I was talking about.
Post by bartc
Post by Tim Rentsch
Post by bartc
[...] people here can continue to delude themselves that C's 'for' is
superior in all ways to those of any other language.
No one here is saying that, nor do they think it. What is
the point of misrepresenting that?
Post by bartc
The C for loop is too flexible. [...]
What Malcolm means is that the C for loop is too flexible for
someone who is as brilliant as he is. For those of us who aren't
in his league, the flexibility of for() in C is seen as being
more an advantage than it is a disadvantage.
What I did say is that the flexibility of for() in C is seen [ie,
by myself, and many other C programmers] as being more an
advantage than it is a disadvantage. What I did /not/ say that C's
'for' is superior in all ways to those of any other language. I
hope you understand that those two statements are quite different.
For years know I have been editing all the "for" out of the
source code I am editing. I have yet to see an example where
changing all the "for" to "while" makes anything more obscure.

My objection to "for" is esthetic. The business with two semi-
colons seems to me too non-C-like to tolerate.
Tim Rentsch
2017-05-05 08:20:48 UTC
Permalink
Raw Message
Post by David Kleinecke
[...contrasting uses of for() and while()...]
For years know I have been editing all the "for" out of the
source code I am editing. I have yet to see an example where
changing all the "for" to "while" makes anything more obscure.
Interesting perception, but not one that is shared by the
vast majority of C developers.
David Kleinecke
2017-05-05 19:37:54 UTC
Permalink
Raw Message
Post by Tim Rentsch
Post by David Kleinecke
[...contrasting uses of for() and while()...]
For years know I have been editing all the "for" out of the
source code I am editing. I have yet to see an example where
changing all the "for" to "while" makes anything more obscure.
Interesting perception, but not one that is shared by the
vast majority of C developers.
De gustibus.
Tim Rentsch
2017-05-06 07:16:24 UTC
Permalink
Raw Message
Post by David Kleinecke
Post by Tim Rentsch
Post by David Kleinecke
[...contrasting uses of for() and while()...]
For years know I have been editing all the "for" out of the
source code I am editing. I have yet to see an example where
changing all the "for" to "while" makes anything more obscure.
Interesting perception, but not one that is shared by the
vast majority of C developers.
De gustibus.
Yes, I expect they would say much the same about you.

There are at the very least tens of thousands of C developers who
see for() as providing advantages over while() in some contexts.
Not all of those people are stupid.
David Kleinecke
2017-05-06 18:49:13 UTC
Permalink
Raw Message
Post by Tim Rentsch
Post by David Kleinecke
Post by Tim Rentsch
Post by David Kleinecke
[...contrasting uses of for() and while()...]
For years know I have been editing all the "for" out of the
source code I am editing. I have yet to see an example where
changing all the "for" to "while" makes anything more obscure.
Interesting perception, but not one that is shared by the
vast majority of C developers.
De gustibus.
Yes, I expect they would say much the same about you.
There are at the very least tens of thousands of C developers who
see for() as providing advantages over while() in some contexts.
Not all of those people are stupid.
De gustibus once again. The gist of "de gustibus" is
that neither side (or none of the sides) is wrong, stupid
or misguided.
Malcolm McLean
2017-05-06 20:16:16 UTC
Permalink
Raw Message
Post by David Kleinecke
De gustibus once again. The gist of "de gustibus" is
that neither side (or none of the sides) is wrong, stupid
or misguided.
My sister is a philosopher. She says of Scotch whisky "why value smoothness,
why not value fire?" I can't quite get together a response to that, but
I'm not convinced.
David Kleinecke
2017-05-06 21:10:00 UTC
Permalink
Raw Message
Post by Malcolm McLean
Post by David Kleinecke
De gustibus once again. The gist of "de gustibus" is
that neither side (or none of the sides) is wrong, stupid
or misguided.
My sister is a philosopher. She says of Scotch whisky "why value smoothness,
why not value fire?" I can't quite get together a response to that, but
I'm not convinced.
The trick is to agree to disagree without in any way down-
valorizing the other guy's opinions. For example, I read your
"but I'm not convinced." as containing a nuance that you agreeing
would make your sister's opinion somehow more "true" than it was
before you agreed.
Joe Pfeiffer
2017-05-07 02:23:46 UTC
Permalink
Raw Message
Post by David Kleinecke
Post by Tim Rentsch
Post by David Kleinecke
Post by Tim Rentsch
Post by David Kleinecke
[...contrasting uses of for() and while()...]
For years know I have been editing all the "for" out of the
source code I am editing. I have yet to see an example where
changing all the "for" to "while" makes anything more obscure.
Interesting perception, but not one that is shared by the
vast majority of C developers.
De gustibus.
Yes, I expect they would say much the same about you.
There are at the very least tens of thousands of C developers who
see for() as providing advantages over while() in some contexts.
Not all of those people are stupid.
De gustibus once again. The gist of "de gustibus" is
that neither side (or none of the sides) is wrong, stupid
or misguided.
Yes, but there are many, many C programmers including me who regard
your side of the debate as being, indeed, wrong and misguided (you are
clearly not stupid).
David Kleinecke
2017-05-07 04:51:56 UTC
Permalink
Raw Message
Post by Joe Pfeiffer
Post by David Kleinecke
Post by Tim Rentsch
Post by David Kleinecke
Post by Tim Rentsch
Post by David Kleinecke
[...contrasting uses of for() and while()...]
For years know I have been editing all the "for" out of the
source code I am editing. I have yet to see an example where
changing all the "for" to "while" makes anything more obscure.
Interesting perception, but not one that is shared by the
vast majority of C developers.
De gustibus.
Yes, I expect they would say much the same about you.
There are at the very least tens of thousands of C developers who
see for() as providing advantages over while() in some contexts.
Not all of those people are stupid.
De gustibus once again. The gist of "de gustibus" is
that neither side (or none of the sides) is wrong, stupid
or misguided.
Yes, but there are many, many C programmers including me who regard
your side of the debate as being, indeed, wrong and misguided (you are
clearly not stupid).
QED
fir
2017-05-07 12:04:38 UTC
Permalink
Raw Message
Post by Joe Pfeiffer
Post by David Kleinecke
Post by Tim Rentsch
Post by David Kleinecke
Post by Tim Rentsch
Post by David Kleinecke
[...contrasting uses of for() and while()...]
For years know I have been editing all the "for" out of the
source code I am editing. I have yet to see an example where
changing all the "for" to "while" makes anything more obscure.
Interesting perception, but not one that is shared by the
vast majority of C developers.
De gustibus.
Yes, I expect they would say much the same about you.
There are at the very least tens of thousands of C developers who
see for() as providing advantages over while() in some contexts.
Not all of those people are stupid.
De gustibus once again. The gist of "de gustibus" is
that neither side (or none of the sides) is wrong, stupid
or misguided.
Yes, but there are many, many C programmers including me who regard
your side of the debate as being, indeed, wrong and misguided (you are
clearly not stupid).
QED
c has praiseworthy attitude to make c codes as short as it could (though i think many holes in this attitude do appear, some intentional some maybe not intentional - it would be good to rethink that and enumerate them but it is a pice of work.. )

if so the reasonable/compromisable step would be imo to furn

for(int i=0; i<222; i++)
into

for(222) //with default i, (j,k if nested)

(as an additional form not repalcement maybe)

its shorter it also os some kind of
abstraction (its easier to think on fors in such form, abstract from machinery for
example thinking how to implement

int a = 100;
for(a) a += rand()%20;

one also can think on such extended
fors:

for(1,2,3,5,7,11,13, 200..300, 299..-200)

where i will be 1 then 2 then .. then 200 then 201.. then 202 etc

also could go in whole pack of abstract fors

non_sequential_for(100) {} //the expresion my be called non sequential order for given i's - but say cannot be called in paralel

sequential_for(100) {} //must be sequential

paralel_for()//may be parralel

and possibly more
(i was writing already on that though
maybe now i see a bit more clear that pack of such built in fors could be good idea)
dont remember the details now
fir
2017-05-07 12:09:36 UTC
Permalink
Raw Message
Post by fir
Post by Joe Pfeiffer
Post by David Kleinecke
Post by Tim Rentsch
Post by David Kleinecke
Post by Tim Rentsch
Post by David Kleinecke
[...contrasting uses of for() and while()...]
For years know I have been editing all the "for" out of the
source code I am editing. I have yet to see an example where
changing all the "for" to "while" makes anything more obscure.
Interesting perception, but not one that is shared by the
vast majority of C developers.
De gustibus.
Yes, I expect they would say much the same about you.
There are at the very least tens of thousands of C developers who
see for() as providing advantages over while() in some contexts.
Not all of those people are stupid.
De gustibus once again. The gist of "de gustibus" is
that neither side (or none of the sides) is wrong, stupid
or misguided.
Yes, but there are many, many C programmers including me who regard
your side of the debate as being, indeed, wrong and misguided (you are
clearly not stupid).
QED
c has praiseworthy attitude to make c codes as short as it could (though i think many holes in this attitude do appear, some intentional some maybe not intentional - it would be good to rethink that and enumerate them but it is a pice of work.. )
if so the reasonable/compromisable step would be imo to furn
for(int i=0; i<222; i++)
into
for(222) //with default i, (j,k if nested)
(as an additional form not repalcement maybe)
its shorter it also os some kind of
abstraction (its easier to think on fors in such form, abstract from machinery for
example thinking how to implement
int a = 100;
for(a) a += rand()%20;
one also can think on such extended
for(1,2,3,5,7,11,13, 200..300, 299..-200)
where i will be 1 then 2 then .. then 200 then 201.. then 202 etc
also could go in whole pack of abstract fors
non_sequential_for(100) {} //the expresion my be called non sequential order for given i's - but say cannot be called in paralel
sequential_for(100) {} //must be sequential
paralel_for()//may be parralel
and possibly more
(i was writing already on that though
maybe now i see a bit more clear that pack of such built in fors could be good idea)
dont remember the details now
as to whiles one could said that if for
take numbers of repeats while could take
conditions

for(100)

while(a<100)

which make spearate constructs.. though one could try to blend it into one, though separation also could be good idea
fir
2017-05-07 12:18:21 UTC
Permalink
Raw Message
Post by fir
Post by fir
Post by Joe Pfeiffer
Post by David Kleinecke
Post by Tim Rentsch
Post by David Kleinecke
Post by Tim Rentsch
Post by David Kleinecke
[...contrasting uses of for() and while()...]
For years know I have been editing all the "for" out of the
source code I am editing. I have yet to see an example where
changing all the "for" to "while" makes anything more obscure.
Interesting perception, but not one that is shared by the
vast majority of C developers.
De gustibus.
Yes, I expect they would say much the same about you.
There are at the very least tens of thousands of C developers who
see for() as providing advantages over while() in some contexts.
Not all of those people are stupid.
De gustibus once again. The gist of "de gustibus" is
that neither side (or none of the sides) is wrong, stupid
or misguided.
Yes, but there are many, many C programmers including me who regard
your side of the debate as being, indeed, wrong and misguided (you are
clearly not stupid).
QED
c has praiseworthy attitude to make c codes as short as it could (though i think many holes in this attitude do appear, some intentional some maybe not intentional - it would be good to rethink that and enumerate them but it is a pice of work.. )
if so the reasonable/compromisable step would be imo to furn
for(int i=0; i<222; i++)
into
for(222) //with default i, (j,k if nested)
(as an additional form not repalcement maybe)
its shorter it also os some kind of
abstraction (its easier to think on fors in such form, abstract from machinery for
example thinking how to implement
int a = 100;
for(a) a += rand()%20;
one also can think on such extended
for(1,2,3,5,7,11,13, 200..300, 299..-200)
where i will be 1 then 2 then .. then 200 then 201.. then 202 etc
also could go in whole pack of abstract fors
non_sequential_for(100) {} //the expresion my be called non sequential order for given i's - but say cannot be called in paralel
sequential_for(100) {} //must be sequential
paralel_for()//may be parralel
and possibly more
(i was writing already on that though
maybe now i see a bit more clear that pack of such built in fors could be good idea)
dont remember the details now
as to whiles one could said that if for
take numbers of repeats while could take
conditions
for(100)
while(a<100)
which make spearate constructs.. though one could try to blend it into one, though separation also could be good idea
one could also try to distinguish (say but some speparate names) while() that
checks the condition on every 'turn' against the one that checks it only on entry once, but hard to say if that would be usable or not really
fir
2017-05-07 12:54:24 UTC
Permalink
Raw Message
Post by fir
Post by fir
Post by fir
Post by Joe Pfeiffer
Post by David Kleinecke
Post by Tim Rentsch
Post by David Kleinecke
Post by Tim Rentsch
Post by David Kleinecke
[...contrasting uses of for() and while()...]
For years know I have been editing all the "for" out of the
source code I am editing. I have yet to see an example where
changing all the "for" to "while" makes anything more obscure.
Interesting perception, but not one that is shared by the
vast majority of C developers.
De gustibus.
Yes, I expect they would say much the same about you.
There are at the very least tens of thousands of C developers who
see for() as providing advantages over while() in some contexts.
Not all of those people are stupid.
De gustibus once again. The gist of "de gustibus" is
that neither side (or none of the sides) is wrong, stupid
or misguided.
Yes, but there are many, many C programmers including me who regard
your side of the debate as being, indeed, wrong and misguided (you are
clearly not stupid).
QED
c has praiseworthy attitude to make c codes as short as it could (though i think many holes in this attitude do appear, some intentional some maybe not intentional - it would be good to rethink that and enumerate them but it is a pice of work.. )
if so the reasonable/compromisable step would be imo to furn
for(int i=0; i<222; i++)
into
for(222) //with default i, (j,k if nested)
(as an additional form not repalcement maybe)
its shorter it also os some kind of
abstraction (its easier to think on fors in such form, abstract from machinery for
example thinking how to implement
int a = 100;
for(a) a += rand()%20;
one also can think on such extended
for(1,2,3,5,7,11,13, 200..300, 299..-200)
where i will be 1 then 2 then .. then 200 then 201.. then 202 etc
also could go in whole pack of abstract fors
non_sequential_for(100) {} //the expresion my be called non sequential order for given i's - but say cannot be called in paralel
sequential_for(100) {} //must be sequential
paralel_for()//may be parralel
and possibly more
(i was writing already on that though
maybe now i see a bit more clear that pack of such built in fors could be good idea)
dont remember the details now
as to whiles one could said that if for
take numbers of repeats while could take
conditions
for(100)
while(a<100)
which make spearate constructs.. though one could try to blend it into one, though separation also could be good idea
one could also try to distinguish (say but some speparate names) while() that
checks the condition on every 'turn' against the one that checks it only on entry once, but hard to say if that would be usable or not really
yet maybe some fragment of some idea how to shorten coded
getting resizable full arrays are done (as it was explained) one coud add syntax for "add + resize"

something like

int outcome[];

for(int i=0; i<10; i++)
outcome[] += i;

where in older prospect it would need more like

int outcome_size = 0;
int outcome[outcome_size];

for(int i=0; i<10; i++)
{
outcome_size++;
resize outcome[outcome_size];

outcome[outcome_size-1] = i;
}
bartc
2017-05-07 12:48:46 UTC
Permalink
Raw Message
Post by fir
c has praiseworthy attitude to make c codes as short as it could (though i think many holes in this attitude do appear, some intentional some maybe not intentional - it would be good to rethink that and enumerate them but it is a pice of work.. )
if so the reasonable/compromisable step would be imo to furn
for(int i=0; i<222; i++)
into
for(222) //with default i, (j,k if nested)
(as an additional form not repalcement maybe)
This can be done as a macro:

#define FOR(n) for(int i=0; i<(n); ++i)

Nested FOR would be OK (each i is in a different scope), provided you
don't need access to the loop index. Ie. just a repeat-N-times loop.
Post by fir
its shorter it also os some kind of
abstraction (its easier to think on fors in such form, abstract from machinery for
example thinking how to implement
int a = 100;
for(a) a += rand()%20;
You've lost me here; what does this mean? (That's not a good sign for a
new language proposal!)
--
bartc
fir
2017-05-07 13:13:41 UTC
Permalink
Raw Message
Post by bartc
Post by fir
c has praiseworthy attitude to make c codes as short as it could (though i think many holes in this attitude do appear, some intentional some maybe not intentional - it would be good to rethink that and enumerate them but it is a pice of work.. )
if so the reasonable/compromisable step would be imo to furn
for(int i=0; i<222; i++)
into
for(222) //with default i, (j,k if nested)
(as an additional form not repalcement maybe)
#define FOR(n) for(int i=0; i<(n); ++i)
Nested FOR would be OK (each i is in a different scope), provided you
don't need access to the loop index. Ie. just a repeat-N-times loop.
Post by fir
its shorter it also os some kind of
abstraction (its easier to think on fors in such form, abstract from machinery for
example thinking how to implement
int a = 100;
for(a) a += rand()%20;
You've lost me here; what does this mean? (That's not a good sign for a
new language proposal!)
i dont know, this is open question ;c

(not meaning that answer to this is interesting, right now i dont see much usability that can be puttet here but
i not 'investigated' it and i dont know)

this is sorta touchinga problem like

for(int i=0; i<strlen(s); i++)

which i usually forgetting how it works (afair it calls strlen every turn which in this case is bad)
David Brown
2017-05-07 13:10:14 UTC
Permalink
Raw Message
Post by Joe Pfeiffer
Post by David Kleinecke
Post by Tim Rentsch
Post by David Kleinecke
Post by Tim Rentsch
Post by David Kleinecke
[...contrasting uses of for() and while()...]
For years know I have been editing all the "for" out of the
source code I am editing. I have yet to see an example where
changing all the "for" to "while" makes anything more obscure.
Interesting perception, but not one that is shared by the
vast majority of C developers.
De gustibus.
Yes, I expect they would say much the same about you.
There are at the very least tens of thousands of C developers who
see for() as providing advantages over while() in some contexts.
Not all of those people are stupid.
De gustibus once again. The gist of "de gustibus" is
that neither side (or none of the sides) is wrong, stupid
or misguided.
Yes, but there are many, many C programmers including me who regard
your side of the debate as being, indeed, wrong and misguided (you are
clearly not stupid).
QED
No, I believe you have (again) missed the point. The idea of "de
gustibus" is a balance - "In matters of taste, there can be no
disputes". It applies to arguments like emacs vs. vim, or which brace
style is "best" in C, or if you should use underscores or camelCaps in
identifiers.

But in this case, there is one person (you) who has rather weird ideas
about how to write and re-write C code - and everyone else who has
expressed an opinion here, along with all the authors of C code easily
available for examination, have a completely different opinion.
Further, several people have given good reasons for using standard C
formulations and types (the main point being that they are /standard/)
and asked you for justification for your opinion - with no answer.

This is not "de gustibus" - it's like a crackpot who claims people never
actually went to the moon, and that his opinion that the moon is made of
cheese is equally valid to anyone else's opinion.

You are, of course, free to write C code however you want to - at least,
when it is just for your own entertainment and hobby interest. But
don't expect anyone else to see it as anything other than wrong and
misguided - unless you can provide solid justification for /why/ you
think your ideas lead to clearer or better code, or that it is an method
that other people support.
Manfred
2017-05-07 14:47:15 UTC
Permalink
Raw Message
Post by David Brown
QED
No, I believe you have (again) missed the point. The idea of "de
gustibus" is a balance - "In matters of taste, there can be no
disputes".
<snip>
Post by David Brown
This is not "de gustibus" - it's like a crackpot who claims people never
actually went to the moon, and that his opinion that the moon is made of
cheese is equally valid to anyone else's opinion.
Excellent point on the real meaning of "de gustibus non disputandum est"
- knowledge of Latin being way too much underestimated and misused nowadays.
Post by David Brown
You are, of course, free to write C code however you want to - at least,
when it is just for your own entertainment and hobby interest.
I would stress the point as /if/ "it is just for your own entertainment"
Serious code, that is meant to run in some real life environment, should
be just good.

But
Post by David Brown
don't expect anyone else to see it as anything other than wrong and
misguided - unless you can provide solid justification for /why/ you
think your ideas lead to clearer or better code, or that it is an method
that other people support.
I would replace the /or/ into /and/ "that it is a method that other
people support"
Some practice is not to be considered good just because it may be
commonly used by someone else, think e.g. of blind copy-paste from
unverified sources on the net.
David Brown
2017-05-07 19:08:37 UTC
Permalink
Raw Message
Post by Manfred
Post by David Brown
QED
No, I believe you have (again) missed the point. The idea of "de
gustibus" is a balance - "In matters of taste, there can be no
disputes".
<snip>
Post by David Brown
This is not "de gustibus" - it's like a crackpot who claims people never
actually went to the moon, and that his opinion that the moon is made of
cheese is equally valid to anyone else's opinion.
Excellent point on the real meaning of "de gustibus non disputandum est"
- knowledge of Latin being way too much underestimated and misused nowadays.
My knowledge of Latin is poor, but my google-foo is top class :-)
Post by Manfred
Post by David Brown
You are, of course, free to write C code however you want to - at least,
when it is just for your own entertainment and hobby interest.
I would stress the point as /if/ "it is just for your own entertainment"
Serious code, that is meant to run in some real life environment, should
be just good.
Most professional programmers who have been in the job for a while have
had to deal with code written by some muppet that things their own
personal style of C is best. You know, code that begins with "#define
begin {", or "#define FOR(n) for(int i=0; i<(n); ++i)".
Post by Manfred
But
Post by David Brown
don't expect anyone else to see it as anything other than wrong and
misguided - unless you can provide solid justification for /why/ you
think your ideas lead to clearer or better code, or that it is an method
that other people support.
I would replace the /or/ into /and/ "that it is a method that other
people support"
Some practice is not to be considered good just because it may be
commonly used by someone else, think e.g. of blind copy-paste from
unverified sources on the net.
I guess so. It turns out that millions of people /can/ be wrong :-)

But if significant numbers of people follow a particular style in C,
then you can at least argue popularity and familiarity as a benefit for it.
bartc
2017-05-07 20:54:05 UTC
Permalink
Raw Message
Post by David Brown
Most professional programmers who have been in the job for a while have
had to deal with code written by some muppet that things their own
personal style of C is best. You know, code that begins with "#define
begin {", or "#define FOR(n) for(int i=0; i<(n); ++i)".
That last example looks suspiciously like the example macro I posted
earlier today (in response to a suggested N-times loop, as I assumed it
was).

I would no longer use such macros (I don't think language deficiencies
should be fixed with the CPP; it's not powerful enough anyway).

But examples such as those are fairly innocuous, so it's bit rich
looking down your nose at them. Not when you look at a lot of open
source code and it's so plastered with macros that you can't make head
or tail of it.

Here's a macro call in gcc.c I noticed:

PATFETCH(c);

What's PATFETCH? It's one of these:

# ifndef PATFETCH
# ifdef WCHAR
# define PATFETCH(c) \
do {if (p == pend) return REG_EEND; \
c = (UCHAR_T) *p++; \
if (translate && (c <= 0xff)) c = (UCHAR_T) translate[c]; \
} while (0)
# else /* BYTE */
# define PATFETCH(c) \
do {if (p == pend) return REG_EEND; \
c = (unsigned char) *p++; \
if (translate) c = (unsigned char) translate[c]; \
} while (0)
# endif /* WCHAR */
# endif

Any the wiser? Probably not!

There are any number examples of macro used to impose a style on code
which also serves to make it incomprehensible to everyone else. Is that
macro call defined as a function, variable, expression, another macro,
an attribute, a type, or just defined as nothing at all? You have to to
research every single one to get a picture of what a bit of code is
actually doing.

Please just give me the luxury of dealing only with a handful of macros
such as FOR!
--
bartc
David Brown
2017-05-07 22:59:26 UTC
Permalink
Raw Message
Post by bartc
Post by David Brown
Most professional programmers who have been in the job for a while have
had to deal with code written by some muppet that things their own
personal style of C is best. You know, code that begins with "#define
begin {", or "#define FOR(n) for(int i=0; i<(n); ++i)".
That last example looks suspiciously like the example macro I posted
earlier today (in response to a suggested N-times loop, as I assumed it
was).
Yes indeed. I don't think you were advocating its use - merely telling
the other poster that it was possible (which is fair enough).
Post by bartc
I would no longer use such macros (I don't think language deficiencies
should be fixed with the CPP; it's not powerful enough anyway).
I don't think language "deficiencies" should be "fixed" except by
changes to the language, /modest/ implementation extensions, or simply
using a different language. If you want to use C, use C. If you want
to use something else, use that. There are enough programming languages
around to choose from if C does not suit your taste or your needs.

For example, if you don't like C's "for" loops, C++ allows alternatives
like "for (auto i : {1, 2, 3, 4, 5})". Or you can just pick a
completely different language.
Post by bartc
But examples such as those are fairly innocuous, so it's bit rich
looking down your nose at them.
No, it is not "a bit rich". Just because there are worse misuses of the
pre-processor, does not mean that those two examples are bad!
Post by bartc
Not when you look at a lot of open
source code and it's so plastered with macros that you can't make head
or tail of it.
Lots of people write crap code. When it is published as open source,
everyone can see the crap code - rather than having it hidden away.
Nothing about being open source implies quality or lack of quality, or
good style or bad style. Without looking in detail, of course, it is
hard to guess if a macro is a good use of the preprocessor, or a bad misuse.
Post by bartc
PATFETCH(c);
# ifndef PATFETCH
# ifdef WCHAR
# define PATFETCH(c) \
do {if (p == pend) return REG_EEND; \
c = (UCHAR_T) *p++; \
if (translate && (c <= 0xff)) c = (UCHAR_T) translate[c]; \
} while (0)
# else /* BYTE */
# define PATFETCH(c) \
do {if (p == pend) return REG_EEND; \
c = (unsigned char) *p++; \
if (translate) c = (unsigned char) translate[c]; \
} while (0)
# endif /* WCHAR */
# endif
Any the wiser? Probably not!
/I/ am none the wiser from that. But presumably someone has good reason
for the macro - or at least, /had/ a good reason when it was written.
These days, a functional macro like that would be best written as an
inline function - but that was not a possibility in gcc's early days
(and anyway, a C compiler usually has to be written in slightly old
language, to avoid chicken-and-egg issues).
Post by bartc
There are any number examples of macro used to impose a style on code
which also serves to make it incomprehensible to everyone else. Is that
macro call defined as a function, variable, expression, another macro,
an attribute, a type, or just defined as nothing at all? You have to to
research every single one to get a picture of what a bit of code is
actually doing.
There is a /huge/ different between a macro that is doing something
/new/, and one that is giving a new name to standard features, or simply
hiding normal C code.
Post by bartc
Please just give me the luxury of dealing only with a handful of macros
such as FOR!
Well, of course /you/ can use it. But I can tell you I'd hate to have
to see it in real code, and I'd consider it a mark of someone who does
not understand C.
David Kleinecke
2017-05-07 23:59:11 UTC
Permalink
Raw Message
Post by David Brown
Post by bartc
Post by David Brown
Most professional programmers who have been in the job for a while have
had to deal with code written by some muppet that things their own
personal style of C is best. You know, code that begins with "#define
begin {", or "#define FOR(n) for(int i=0; i<(n); ++i)".
That last example looks suspiciously like the example macro I posted
earlier today (in response to a suggested N-times loop, as I assumed it
was).
Yes indeed. I don't think you were advocating its use - merely telling
the other poster that it was possible (which is fair enough).
Post by bartc
I would no longer use such macros (I don't think language deficiencies
should be fixed with the CPP; it's not powerful enough anyway).
I don't think language "deficiencies" should be "fixed" except by
changes to the language, /modest/ implementation extensions, or simply
using a different language. If you want to use C, use C. If you want
to use something else, use that. There are enough programming languages
around to choose from if C does not suit your taste or your needs.
For example, if you don't like C's "for" loops, C++ allows alternatives
like "for (auto i : {1, 2, 3, 4, 5})". Or you can just pick a
completely different language.
Post by bartc
But examples such as those are fairly innocuous, so it's bit rich
looking down your nose at them.
No, it is not "a bit rich". Just because there are worse misuses of the
pre-processor, does not mean that those two examples are bad!
Post by bartc
Not when you look at a lot of open
source code and it's so plastered with macros that you can't make head
or tail of it.
Lots of people write crap code. When it is published as open source,
everyone can see the crap code - rather than having it hidden away.
Nothing about being open source implies quality or lack of quality, or
good style or bad style. Without looking in detail, of course, it is
hard to guess if a macro is a good use of the preprocessor, or a bad misuse.
Post by bartc
PATFETCH(c);
# ifndef PATFETCH
# ifdef WCHAR
# define PATFETCH(c) \
do {if (p == pend) return REG_EEND; \
c = (UCHAR_T) *p++; \
if (translate && (c <= 0xff)) c = (UCHAR_T) translate[c]; \
} while (0)
# else /* BYTE */
# define PATFETCH(c) \
do {if (p == pend) return REG_EEND; \
c = (unsigned char) *p++; \
if (translate) c = (unsigned char) translate[c]; \
} while (0)
# endif /* WCHAR */
# endif
Any the wiser? Probably not!
/I/ am none the wiser from that. But presumably someone has good reason
for the macro - or at least, /had/ a good reason when it was written.
These days, a functional macro like that would be best written as an
inline function - but that was not a possibility in gcc's early days
(and anyway, a C compiler usually has to be written in slightly old
language, to avoid chicken-and-egg issues).
Post by bartc
There are any number examples of macro used to impose a style on code
which also serves to make it incomprehensible to everyone else. Is that
macro call defined as a function, variable, expression, another macro,
an attribute, a type, or just defined as nothing at all? You have to to
research every single one to get a picture of what a bit of code is
actually doing.
There is a /huge/ different between a macro that is doing something
/new/, and one that is giving a new name to standard features, or simply
hiding normal C code.
Post by bartc
Please just give me the luxury of dealing only with a handful of macros
such as FOR!
Well, of course /you/ can use it. But I can tell you I'd hate to have
to see it in real code, and I'd consider it a mark of someone who does
not understand C.
I think your point about inline functions deserves to
be underlined. It is (obviously?) the way to go.

I think even the C89 standard would allow a compiler that
inlined all the static subroutines in a unit. These days of
lots of memory makes that quite feasible. Note that that way
there is no need for an "inline" keyword. Has anybody done
that?
Robert Wessel
2017-05-08 03:28:51 UTC
Permalink
Raw Message
On Sun, 7 May 2017 16:59:11 -0700 (PDT), David Kleinecke
Post by David Kleinecke
Post by David Brown
Post by bartc
Post by David Brown
Most professional programmers who have been in the job for a while have
had to deal with code written by some muppet that things their own
personal style of C is best. You know, code that begins with "#define
begin {", or "#define FOR(n) for(int i=0; i<(n); ++i)".
That last example looks suspiciously like the example macro I posted
earlier today (in response to a suggested N-times loop, as I assumed it
was).
Yes indeed. I don't think you were advocating its use - merely telling
the other poster that it was possible (which is fair enough).
Post by bartc
I would no longer use such macros (I don't think language deficiencies
should be fixed with the CPP; it's not powerful enough anyway).
I don't think language "deficiencies" should be "fixed" except by
changes to the language, /modest/ implementation extensions, or simply
using a different language. If you want to use C, use C. If you want
to use something else, use that. There are enough programming languages
around to choose from if C does not suit your taste or your needs.
For example, if you don't like C's "for" loops, C++ allows alternatives
like "for (auto i : {1, 2, 3, 4, 5})". Or you can just pick a
completely different language.
Post by bartc
But examples such as those are fairly innocuous, so it's bit rich
looking down your nose at them.
No, it is not "a bit rich". Just because there are worse misuses of the
pre-processor, does not mean that those two examples are bad!
Post by bartc
Not when you look at a lot of open
source code and it's so plastered with macros that you can't make head
or tail of it.
Lots of people write crap code. When it is published as open source,
everyone can see the crap code - rather than having it hidden away.
Nothing about being open source implies quality or lack of quality, or
good style or bad style. Without looking in detail, of course, it is
hard to guess if a macro is a good use of the preprocessor, or a bad misuse.
Post by bartc
PATFETCH(c);
# ifndef PATFETCH
# ifdef WCHAR
# define PATFETCH(c) \
do {if (p == pend) return REG_EEND; \
c = (UCHAR_T) *p++; \
if (translate && (c <= 0xff)) c = (UCHAR_T) translate[c]; \
} while (0)
# else /* BYTE */
# define PATFETCH(c) \
do {if (p == pend) return REG_EEND; \
c = (unsigned char) *p++; \
if (translate) c = (unsigned char) translate[c]; \
} while (0)
# endif /* WCHAR */
# endif
Any the wiser? Probably not!
/I/ am none the wiser from that. But presumably someone has good reason
for the macro - or at least, /had/ a good reason when it was written.
These days, a functional macro like that would be best written as an
inline function - but that was not a possibility in gcc's early days
(and anyway, a C compiler usually has to be written in slightly old
language, to avoid chicken-and-egg issues).
Post by bartc
There are any number examples of macro used to impose a style on code
which also serves to make it incomprehensible to everyone else. Is that
macro call defined as a function, variable, expression, another macro,
an attribute, a type, or just defined as nothing at all? You have to to
research every single one to get a picture of what a bit of code is
actually doing.
There is a /huge/ different between a macro that is doing something
/new/, and one that is giving a new name to standard features, or simply
hiding normal C code.
Post by bartc
Please just give me the luxury of dealing only with a handful of macros
such as FOR!
Well, of course /you/ can use it. But I can tell you I'd hate to have
to see it in real code, and I'd consider it a mark of someone who does
not understand C.
I think your point about inline functions deserves to
be underlined. It is (obviously?) the way to go.
I think even the C89 standard would allow a compiler that
inlined all the static subroutines in a unit. These days of
lots of memory makes that quite feasible. Note that that way
there is no need for an "inline" keyword. Has anybody done
that?
All static functions? No, that would probably be silly. But many
compilers will inline functions based on various heuristics, whether
or not they're declared as static or inline. If it's not static the
compiler will likely have to generate an out-of-line version as well
(in case someone calls it), and inline really just gets treated as a
hint (not unlike "register", although in many implementations register
has no effect other than preventing you from taking the address of the
object). LTCG makes that work even better, as things can be inlined
across translation units. FWIW, compilers can't inline all functions
marked "inline" either - for example, they cannot do so for in general
for recursive functions.

Malcolm McLean
2017-05-07 15:56:45 UTC
Permalink
Raw Message
Post by David Brown
No, I believe you have (again) missed the point. The idea of "de
gustibus" is a balance - "In matters of taste, there can be no
disputes". It applies to arguments like emacs vs. vim, or which brace
style is "best" in C, or if you should use underscores or camelCaps in
identifiers.
Many things can be objectively tested, but you need a university
psychology department to do it. They'd probably actually quite
appreciate the task for little undergraduate projects.
under_scores versus camelCaps is a case in point, programmers will
likely perform better on some tasks than others dependent on the
choice of identifier style.
Post by David Brown
This is not "de gustibus" - it's like a crackpot who claims people never
actually went to the moon, and that his opinion that the moon is made of
cheese is equally valid to anyone else's opinion.
The claim is that replacing for loops with while loops leads to code
which is easier to read and more maintainable. Unlike the claim that
the moon is made of cheese, that's not obviously and objectively
falsifiable, though I would assume it is incorrect in the absence of
information to the contrary.
John Bode
2017-04-11 16:15:26 UTC
Permalink
Raw Message
Post by bartc
Post by Keith Thompson
[...]
Post by Malcolm McLean
The C for loop is too flexible.
I believe that's a minority opinion.
A minority of at least two then.
Post by Keith Thompson
The flexibility means, for example, that you can use the same construct
for (node *ptr = head; node != NULL; node = node->next)
that you'd use to iterate over an array.
That's the trouble: it can be practically anything. If trying to
understand code (or transcribe into a generic algorithm or whatever) you
have to stop and analyse a for-statement. The header tends to be written
on one line so you also have to scan it looking for commas and
semicolons to properly identify the different parts.
Welcome to programming in C.

C for loops *are* far more generalized than in languages like Fortran,
where loops are limited to iterating over a non-modifiable scalar with an
optional stride. C basically blurred the distinction between for and
while loops, which on balance made it more useful. Iterating over a list
such as the example above is a natural extension of for loop semantics.

Do people abuse the construct? Yes, continually. That doesn't make it
a bad thing in and of itself.
s***@casperkitty.com
2017-04-11 16:29:45 UTC
Permalink
Raw Message
Post by John Bode
C for loops *are* far more generalized than in languages like Fortran,
where loops are limited to iterating over a non-modifiable scalar with an
optional stride. C basically blurred the distinction between for and
while loops, which on balance made it more useful. Iterating over a list
such as the example above is a natural extension of for loop semantics.
Blurring distinctions isn't a good thing when the distinctions serve a useful
purpose. The ability to use constructs like *ptr++ to avoid the need to
compute subscript addresses within a loop reduced the need for the kinds of
optimizations compilers of the day could apply only to restricted iteration
loops, and thus reduced the need to distinguish those loops from other forms.
Such distinctions are still useful, however, in languages that make them.
Manfred
2017-04-13 14:00:14 UTC
Permalink
Raw Message
Post by Malcolm McLean
Post by Peabody
for(linepos= 0;
linepos < linelen-3; linepos+= 3, dataframelen++)
<snip>
Post by Malcolm McLean
The C for loop is too flexible.
I, FWIW, find the C for loop pretty well designed.
Although it can be abused, I think the OP example is not such a case: in
fact it keeps two indexes linepos and dataframelen, which apparently
need to be kept in sync with each other, incremented in the very same
statement, which looks good to me.
Tim Rentsch
2017-04-17 02:45:27 UTC
Permalink
Raw Message
Post by Manfred
Post by Malcolm McLean
Post by Peabody
for(linepos= 0;
linepos < linelen-3; linepos+= 3, dataframelen++)
<snip>
Post by Malcolm McLean
The C for loop is too flexible.
I, FWIW, find the C for loop pretty well designed.
in fact it keeps two indexes linepos and dataframelen, which
apparently need to be kept in sync with each other, incremented in the
very same statement, which looks good to me.
Wholeheartedly agree.
Tim Rentsch
2017-04-26 18:09:41 UTC
Permalink
Raw Message
The C for loop is too flexible. [...]
What Malcolm means is that the C for loop is too flexible for
someone who is as brilliant as he is. For those of us who aren't
in his league, the flexibility of for() in C is seen as being
more an advantage than it is a disadvantage.
Loading...