acceptable use of goto?

M

Morris Dovey

Richard said:
You didn't save anything with this approach - you only left the
possibility for a caller to crash the system by calling it with a zero
option.

Hmm - my earlier comment stands. I might take a different view if
this were a widely-used library function likely to be used
blindly by coders who needed to be protected from themselves.
Even if you had done an explicit zero check (or needed to) then the
overhead was nothing compared to the display loop.

A set of test compiles and assembly assemblies showed that in my
environment with gnu toolchain provided some interesting results.
I've copied the assembly listings into the matching C files and
put 3 test cases at:

http://www.iedu.com/c/ta1.c (Ben's)
http://www.iedu.com/c/ta2.c (Mine)
http://www.iedu.com/c/ta3.c (Mine, with a zero check)

The file Ben posted and the file I posted assemble to the same
length (87 bytes). The file I posted above with a check for
(arraylen > 0) was only 73 bytes and actually produced less
entry/exit code.

There is an execution-time cost in calling this function to
determine whether it should be run or not. If your programming
environment is such that built-in protection from failure to do
necessary checks can be a problem, then I'm inclined to agree
that the cost is justified. In other environments where that's
not a problem (but where performance /is/) then I'm inclined to
minimize overhead processing by avoiding even the small amount of
overhead inherent in the call by moving the test outside the
function.

I won't claim that either approach is _always_ right, but thought
you might find it interesting that my version got shorter when
code to perform the test was added.
 
R

Richard

Morris Dovey said:
Hmm - my earlier comment stands. I might take a different view if
this were a widely-used library function likely to be used
blindly by coders who needed to be protected from themselves.


A set of test compiles and assembly assemblies showed that in my
environment with gnu toolchain provided some interesting results.
I've copied the assembly listings into the matching C files and
put 3 test cases at:

Asm is totally platform specific and Off Topic.
http://www.iedu.com/c/ta1.c (Ben's)
http://www.iedu.com/c/ta2.c (Mine)
http://www.iedu.com/c/ta3.c (Mine, with a zero check)

The file Ben posted and the file I posted assemble to the same
length (87 bytes). The file I posted above with a check for
(arraylen > 0) was only 73 bytes and actually produced less
entry/exit code.

It seems to be all theory and no practice.

Who cares? We are talking good design and run time safety. No one really
cares generally for a few bytes. In addition you are wrong about the
size in the real world. What about the repeated checks by code which
CALLS this function?

Sorry, but you fail the design admission test.

And please dont snip the code in question:

bens code: does not crash or exhibit UDB

,----
| void print_int_array(int *array, size_t arraylen)
| {
| putchar('(');
| for (size_t i = 0; i < arraylen; i++)
| printf("%s%d", (i ? ", " : ""), array);
| putchar(')');
| }
`----

your code which can:

,----
| void print_int_array(int *array, size_t arraylen)
| { putchar('(');
| do printf("%d%s",*array++,--arraylen?", ":")\n");
| while (arraylen);
| }
`----

To be honest I am surprised you are defending your code.
 
M

Morris Dovey

Richard said:
Asm is totally platform specific and Off Topic.

Of course it is - that's why it was made available elsewhere,
with only a link here.
Sorry, but you fail the design admission test.

Then it's a good thing I don't do that for a living. :)
And please dont snip the code in question:

bens code: does not crash or exhibit UDB

,----
| void print_int_array(int *array, size_t arraylen)
| {
| putchar('(');
| for (size_t i = 0; i < arraylen; i++)
| printf("%s%d", (i ? ", " : ""), array);
| putchar(')');
| }
`----

your code which can:

,----
| void print_int_array(int *array, size_t arraylen)
| { putchar('(');
| do printf("%d%s",*array++,--arraylen?", ":")\n");
| while (arraylen);
| }
`----


And the (smaller) case you chose ignore/not quote:

void print_int_array(int *array,size_t arraylen)
{ if (arraylen > 0)
{ putchar('(');
do printf("%d%s",*array++,--arraylen?", ":")\n");
while (arraylen);
}
}
To be honest I am surprised you are defending your code.

I wasn't, and have enough of it running around the world (and
above it) to not feel the need to defend it. Rather, the
intention was to share something I thought you might find
interesting. A silly error on my part.
 
R

Richard

Morris Dovey said:
Richard said:
Asm is totally platform specific and Off Topic.

Of course it is - that's why it was made available elsewhere,
with only a link here.
Sorry, but you fail the design admission test.

Then it's a good thing I don't do that for a living. :)
And please dont snip the code in question:

bens code: does not crash or exhibit UDB

,----
| void print_int_array(int *array, size_t arraylen)
| {
| putchar('(');
| for (size_t i = 0; i < arraylen; i++)
| printf("%s%d", (i ? ", " : ""), array);
| putchar(')');
| }
`----

your code which can:

,----
| void print_int_array(int *array, size_t arraylen)
| { putchar('(');
| do printf("%d%s",*array++,--arraylen?", ":")\n");
| while (arraylen);
| }
`----


And the (smaller) case you chose ignore/not quote:


I didnt see that. All my comments were based on your original submission
which you then defended by saying/insinuating you had the checks done
externally.
void print_int_array(int *array,size_t arraylen)
{ if (arraylen > 0)
{ putchar('(');
do printf("%d%s",*array++,--arraylen?", ":")\n");
while (arraylen);
}
}


I wasn't, and have enough of it running around the world (and
above it) to not feel the need to defend it. Rather, the
intention was to share something I thought you might find
interesting. A silly error on my part.

I am unsure as to which bit of your original code is interesting?
Seriously, I can see no reason for it and it would have failed any code
reviews that I have been part of in the past. I dont mean this to insult
you, but to point out that NOT doing the zero check was silly and did
pretty much nothing in terms of efficiency one way or another.

Think of it as debugging "visually" as you were so supportive of a few
days earlier :-;
 
M

Morris Dovey

Richard said:
Morris Dovey said:
Richard said:
Asm is totally platform specific and Off Topic.

Of course it is - that's why it was made available elsewhere,
with only a link here.
Sorry, but you fail the design admission test.

Then it's a good thing I don't do that for a living. :)
And please dont snip the code in question:

bens code: does not crash or exhibit UDB

,----
| void print_int_array(int *array, size_t arraylen)
| {
| putchar('(');
| for (size_t i = 0; i < arraylen; i++)
| printf("%s%d", (i ? ", " : ""), array);
| putchar(')');
| }
`----

your code which can:

,----
| void print_int_array(int *array, size_t arraylen)
| { putchar('(');
| do printf("%d%s",*array++,--arraylen?", ":")\n");
| while (arraylen);
| }
`----


And the (smaller) case you chose ignore/not quote:


I didnt see that. All my comments were based on your original submission
which you then defended by saying/insinuating you had the checks done
externally.


In nearly all of the work I did, removal of _all_ avoidable
overhead was crucial. I used printf() here because it seemed
counter-productive to use faster and smaller code to pump out an
integer value, but it's been a very long time since I've used it
in production code - eight years, to be exact, and that version
of printf() was stripped to just the subset of conversions used
in that project's code.

I don't have any difficulty visualizing scenarios where
performance might not be such an issue, nor where a couple of
extra bytes here and there isn't a problem. I offer for your
consideration that there is an entire spectrum of environments -
and that, at one end of the spectrum, making code idiot-proof
takes a back seat to making the code fit into available memory or
meet hardware timing requirements.
I am unsure as to which bit of your original code is interesting?
Seriously, I can see no reason for it and it would have failed any code
reviews that I have been part of in the past. I dont mean this to insult
you, but to point out that NOT doing the zero check was silly and did
pretty much nothing in terms of efficiency one way or another.

What I found interesting was that the code _with_ the if
statement compiled to fewer machine instructions than the code
_without_ the test (for my particular toolchain and for my
particular environment) which struck me as counter-intuitive. I
thought /you/ might find it interesting because it strengthened
/your/ case.
Think of it as debugging "visually" as you were so supportive of a few
days earlier :-;

My views on that aren't likely to change much - not because I
have anything against debuggers, but rather because they don't
usually fill my needs. When I last actually _needed_ a debugger,
I ran the code inside a room-sized ICE (with an absolutely
obscene price tag) and found a handful of circuit errors in the
SOC.
 
J

João Jerónimo

Ben said:
void print_int_array(int *array, size_t arraylen)
{
putchar('(');
for (size_t i = 0; i < arraylen; i++)
printf("%s%d", (i ? ", " : ""), array);
putchar(')');
}


Are you aware that you are comparing the i variable twice in each
iteration? I think my solution with break ends being much more readable
(and less overkill)...

JJ
 
J

João Jerónimo

Richard said:
You wouldn't. You especially would not want to print possibly thousands
of corrupt data elements as your code would. Always doe the zero check
in the called function. It should not be the job of the calling code
especially when there is zero overhead by doing it properly as in Ben's
example.

assert() was invented long ago...

However, I understand that in some conditions migth be helpfull to print
empty arrays. That's a special case, anyway...

JJ
 
R

Richard

João Jerónimo said:
assert() was invented long ago...

I have seen code with so many ASSERTs that you could hardly read it. And
asserts are not a replacement for good practice. This is a simple case of
competent and "for free" 0 boundary check or lazy "I know better"
implementation. I know which one passes the code review and which one
doesn't. Yes we all have a choice, but there are good ones, robust ones
and there are almost willfully different and not so robust ones.
 
J

João Jerónimo

Richard said:
I have seen code with so many ASSERTs that you could hardly read it. And
asserts are not a replacement for good practice. This is a simple case of
competent and "for free" 0 boundary check or lazy "I know better"
implementation. I know which one passes the code review and which one
doesn't. Yes we all have a choice, but there are good ones, robust ones
and there are almost willfully different and not so robust ones.

I think the rubustness of choices depend always on your needs. If you want
to print (actually showing something on the screen) empty arrays, then it'd
be rather stupid to write a routine that's not able to print those arrays.

If you don't want to print those arrays, then there's no special reason to
support printing empty arrays. However, if you are afraid that someone
actually feeds your function with an empty array, then add an assert.

And I think we should be moderated with assertions. As of now, I've only
found them useful at the start of functions to test functions preconditions
and nowhere else.

JJ
 
R

Richard

João Jerónimo said:
I think the rubustness of choices depend always on your needs. If you
want

Of course but in a case like this, it's a no brainer.
to print (actually showing something on the screen) empty arrays, then it'd
be rather stupid to write a routine that's not able to print those
arrays.

Is anyone saying anything different? It really is a simple thing - check
for 0 case if that 0 case will cause a crash or UDB as Morris's code
would have.
If you don't want to print those arrays, then there's no special reason to
support printing empty arrays. However, if you are afraid that someone
actually feeds your function with an empty array, then add an assert.

Insert? Or you just do nothing. You seem to miss the point of robust
checks. And in this case it can be for free.
 
B

Ben Bacarisse

João Jerónimo said:
Ben said:
void print_int_array(int *array, size_t arraylen)
{
putchar('(');
for (size_t i = 0; i < arraylen; i++)
printf("%s%d", (i ? ", " : ""), array);
putchar(')');
}


Are you aware that you are comparing the i variable twice in each
iteration?


Yes. Are you aware the loop calls printf? If we were comparing "bit
hacks" that might be a concern, but in an output function?
I think my solution with break ends being much more readable
(and less overkill)...

Each to their own, as I said before. We could go at it, debating the
merits of various styles and coding practices, but Usenet is not a
good place to persuade people, so I have largely given up trying.
After about three posts each, it becomes impossible for either party to
say "oh, yes, yours is much clearer" and it usually takes three posts
to explain what one likes about ones own way of doing things --
stalemate is inevitable.

I've picked up lots of tips reading Usenet, but I don't recall anyone
agreeing they have been persuaded by a 367-message thread. It is best
just to show one's code, comment on preferences and move on.
 
R

Richard Heathfield

Ben Bacarisse said:

Each to their own, as I said before. We could go at it, debating the
merits of various styles and coding practices, but Usenet is not a
good place to persuade people, so I have largely given up trying.
After about three posts each, it becomes impossible for either party to
say "oh, yes, yours is much clearer"

Not *quite* impossible. I once persuaded an entrenched
strncpy-is-safer-than-strcpy supporter to change his view, after a
protracted debate that was notable for its civility.

So - it's not impossible, because at least one counter-example exists. But
it's pretty rare, nonetheless.
 
N

Nick Keighley

[exiting mid loop]

If I declare an integer array with:
int myarray[] = {5, 6, 3, 4, 8, 7, 2, 3, 4, 5, 6, 0};
And want to write a routine to print it like this:
(5, 6, 3, 4, 8, 7, 2, 3, 4, 5, 6, 0)
, my best hint would be (untested):

--------------------------------------------------
void print_int_array( int *array, int arraylen )
{
   assert( arraylen >= 1 );

   int *arrayend = array+arraylen;

   printf("(");
   for(;;) {
      printf("%d", *array);
      array++;
      if ( array == arrayend )
         break;
      printf(", ");
   }
   printf(")");}

--------------------------------------------------

Now, please point me out a better solution.
(This is not strictly the case of a loop with multiple exits, but helps to
ilustrate the idea...)


void printlist (int *a, int n)
{
printf ("%d", *a);

if (--n > 0)
{
printf (", ");
printlist (a, n);
}
}

void print_int_array_1 (int *array, int arraylen)
{
printf ("(");
printlist (array, arraylen);
printf (")");
}
 
B

Bartc

Nick said:
[exiting mid loop]

If I declare an integer array with:
int myarray[] = {5, 6, 3, 4, 8, 7, 2, 3, 4, 5, 6, 0};
And want to write a routine to print it like this:
(5, 6, 3, 4, 8, 7, 2, 3, 4, 5, 6, 0)
, my best hint would be (untested):
....
Now, please point me out a better solution.
(This is not strictly the case of a loop with multiple exits, but
helps to ilustrate the idea...)


void printlist (int *a, int n)
{
printf ("%d", *a);

if (--n > 0)
{
printf (", ");
printlist (a, n);
}
}

void print_int_array_1 (int *array, int arraylen)
{
printf ("(");
printlist (array, arraylen);
printf (")");
}

I think you want ++a in that printlist somewhere.

Also arraylen or n=0 is not a possibility.
 
B

Bartc

João Jerónimo said:
assert() was invented long ago...

However, I understand that in some conditions migth be helpfull to
print empty arrays. That's a special case, anyway...

What's special about empty arrays?

In other, dynamic languages, arrays can have zero or more elements.

In C, possibly it's illegal to have a fixed array of 0 elements, but it's
certainly possibly to have a 100-element array of which the first N elements
have been filled, where N can be zero, and you may want to display those
active elements.

So an empty array with N=0, bracketed according to the example in this
thread, should be shown as ().

And with N=1 as (a)

And with N=2 as (a,b) and so on.
 

Ask a Question

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

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,755
Messages
2,569,536
Members
45,020
Latest member
GenesisGai

Latest Threads

Top