Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]
Groups > comp.lang.c > #90116 > unrolled thread
| Started by | Real Troll <real.troll@trolls.com> |
|---|---|
| First post | 2016-07-08 00:00 -0300 |
| Last post | 2016-08-01 10:09 -0400 |
| Articles | 20 on this page of 74 — 29 participants |
Back to article view | Back to comp.lang.c
EXIT_SUCCESS Real Troll <real.troll@trolls.com> - 2016-07-08 00:00 -0300
Re: EXIT_SUCCESS luser droog <luser.droog@gmail.com> - 2016-07-07 19:54 -0700
Re: EXIT_SUCCESS Ian Collins <ian-news@hotmail.com> - 2016-07-08 15:03 +1200
Re: EXIT_SUCCESS James Kuyper <jameskuyper@verizon.net> - 2016-07-07 23:20 -0400
Re: EXIT_SUCCESS Richard Heathfield <rjh@cpax.org.uk> - 2016-07-08 10:19 +0100
Re: EXIT_SUCCESS Malcolm McLean <malcolm.mclean5@btinternet.com> - 2016-07-08 03:25 -0700
Re: EXIT_SUCCESS Richard Heathfield <rjh@cpax.org.uk> - 2016-07-08 13:49 +0100
Re: EXIT_SUCCESS Keith Thompson <kst-u@mib.org> - 2016-07-08 08:33 -0700
Re: EXIT_SUCCESS Gareth Owen <gwowen@gmail.com> - 2016-07-08 18:03 +0100
Re: EXIT_SUCCESS Ben Bacarisse <ben.usenet@bsb.me.uk> - 2016-07-08 19:11 +0100
Re: EXIT_SUCCESS "Osmium" <r124c4u102@comcast.net> - 2016-07-08 14:25 -0500
Re: EXIT_SUCCESS Ben Bacarisse <ben.usenet@bsb.me.uk> - 2016-07-08 20:34 +0100
Re: EXIT_SUCCESS Ken Brody <kenbrody@spamcop.net> - 2016-07-11 19:10 -0400
Re: EXIT_SUCCESS Robert Wessel <robertwessel2@yahoo.com> - 2016-07-10 01:21 -0500
Re: EXIT_SUCCESS Joe Pfeiffer <pfeiffer@cs.nmsu.edu> - 2016-07-10 16:09 -0600
Re: EXIT_SUCCESS Keith Thompson <kst-u@mib.org> - 2016-07-10 16:01 -0700
Re: EXIT_SUCCESS "Osmium" <r124c4u102@comcast.net> - 2016-07-10 18:30 -0500
Re: EXIT_SUCCESS Keith Thompson <kst-u@mib.org> - 2016-07-10 17:00 -0700
Re: EXIT_SUCCESS James Kuyper <jameskuyper@verizon.net> - 2016-07-10 22:43 -0400
Re: EXIT_SUCCESS Siri Cruise <chine.bleu@yahoo.com> - 2016-07-10 22:31 -0700
Re: EXIT_SUCCESS raltbos@xs4all.nl (Richard Bos) - 2016-07-11 08:24 +0000
Re: EXIT_SUCCESS Ken Brody <kenbrody@spamcop.net> - 2016-07-11 19:18 -0400
Re: EXIT_SUCCESS gazelle@shell.xmission.com (Kenny McCormack) - 2016-07-11 00:47 +0000
Re: EXIT_SUCCESS gordonb.0aikd@burditt.org (Gordon Burditt) - 2016-07-12 18:52 -0500
Re: EXIT_SUCCESS "James R. Kuyper" <jameskuyper@verizon.net> - 2016-07-12 20:32 -0400
Re: EXIT_SUCCESS Joe Pfeiffer <pfeiffer@cs.nmsu.edu> - 2016-07-12 20:59 -0600
Re: EXIT_SUCCESS gordonb.a2m2l@burditt.org (Gordon Burditt) - 2016-07-13 02:11 -0500
Re: EXIT_SUCCESS James Kuyper <jameskuyper@verizon.net> - 2016-07-13 11:26 -0400
Re: EXIT_SUCCESS Keith Thompson <kst-u@mib.org> - 2016-07-13 08:48 -0700
Re: EXIT_SUCCESS Tim Rentsch <txr@alumni.caltech.edu> - 2016-07-18 09:54 -0700
Re: EXIT_SUCCESS James Kuyper <jameskuyper@verizon.net> - 2016-07-08 17:46 -0400
Re: EXIT_SUCCESS Keith Thompson <kst-u@mib.org> - 2016-07-09 13:13 -0700
Re: EXIT_SUCCESS jgh@mdfs.net - 2016-07-25 04:42 -0700
Re: EXIT_SUCCESS Richard Heathfield <rjh@cpax.org.uk> - 2016-07-25 13:07 +0100
Re: EXIT_SUCCESS Udyant Wig <udyant.wig@gmail.com> - 2016-07-25 20:05 +0530
Re: EXIT_SUCCESS raltbos@xs4all.nl (Richard Bos) - 2016-07-25 16:06 +0000
Re: EXIT_SUCCESS Richard Heathfield <rjh@cpax.org.uk> - 2016-07-25 17:41 +0100
Re: EXIT_SUCCESS Keith Thompson <kst-u@mib.org> - 2016-07-25 11:04 -0700
Re: EXIT_SUCCESS Richard Heathfield <rjh@cpax.org.uk> - 2016-07-25 19:14 +0100
Re: EXIT_SUCCESS BartC <bc@freeuk.com> - 2016-07-25 22:00 +0100
Re: EXIT_SUCCESS Richard Heathfield <rjh@cpax.org.uk> - 2016-07-25 22:03 +0100
Re: EXIT_SUCCESS BartC <bc@freeuk.com> - 2016-07-25 22:41 +0100
Re: EXIT_SUCCESS jadill33@gmail.com - 2016-07-25 14:50 -0700
Re: EXIT_SUCCESS Keith Thompson <kst-u@mib.org> - 2016-07-25 15:04 -0700
Re: EXIT_SUCCESS David Brown <david.brown@hesbynett.no> - 2016-07-26 10:43 +0200
Re: EXIT_SUCCESS jadill33@gmail.com - 2016-07-25 14:41 -0700
Re: EXIT_SUCCESS David Brown <david.brown@hesbynett.no> - 2016-07-26 10:59 +0200
Re: EXIT_SUCCESS jadill33@gmail.com - 2016-07-27 06:20 -0700
Re: EXIT_SUCCESS Ben Bacarisse <ben.usenet@bsb.me.uk> - 2016-07-27 15:44 +0100
Re: EXIT_SUCCESS Ben Bacarisse <ben.usenet@bsb.me.uk> - 2016-07-27 16:22 +0100
Re: EXIT_SUCCESS Joe Pfeiffer <pfeiffer@cs.nmsu.edu> - 2016-07-27 11:20 -0600
Re: EXIT_SUCCESS luser droog <luser.droog@gmail.com> - 2016-07-27 15:32 -0700
Re: EXIT_SUCCESS Ben Bacarisse <ben.usenet@bsb.me.uk> - 2016-07-28 14:47 +0100
Re: EXIT_SUCCESS Keith Thompson <kst-u@mib.org> - 2016-07-25 08:46 -0700
Re: EXIT_SUCCESS David Brown <david.brown@hesbynett.no> - 2016-07-26 12:44 +0200
Re: EXIT_SUCCESS Keith Thompson <kst-u@mib.org> - 2016-07-26 08:24 -0700
Re: EXIT_SUCCESS David Brown <david.brown@hesbynett.no> - 2016-07-26 19:26 +0200
Re: EXIT_SUCCESS BartC <bc@freeuk.com> - 2016-07-26 18:03 +0100
Re: EXIT_SUCCESS Ken Brody <kenbrody@spamcop.net> - 2016-07-11 19:15 -0400
Re: EXIT_SUCCESS supercat@casperkitty.com - 2016-07-11 16:46 -0700
Re: EXIT_SUCCESS raltbos@xs4all.nl (Richard Bos) - 2016-07-15 13:51 +0000
Re: EXIT_SUCCESS supercat@casperkitty.com - 2016-07-15 08:07 -0700
Re: EXIT_SUCCESS Ken Brody <kenbrody@spamcop.net> - 2016-07-15 14:33 -0400
Re: EXIT_SUCCESS raltbos@xs4all.nl (Richard Bos) - 2016-07-23 09:07 +0000
Re: EXIT_SUCCESS Randy Howard <rhoward.mx@EverybodyUsesIt.com> - 2016-07-23 16:44 -0500
Re: EXIT_SUCCESS Ken Brody <kenbrody@spamcop.net> - 2016-07-25 10:36 -0400
Re: EXIT_SUCCESS Randy Howard <rhoward.mx@EverybodyUsesIt.com> - 2016-07-25 15:28 -0500
Re: EXIT_SUCCESS Rosario19 <Ros@invalid.invalid> - 2016-07-18 09:45 +0200
Re: EXIT_SUCCESS gordonb.bitq1@burditt.org (Gordon Burditt) - 2016-07-08 17:56 -0500
Re: EXIT_SUCCESS Keith Thompson <kst-u@mib.org> - 2016-07-08 08:35 -0700
Re: EXIT_SUCCESS luser droog <luser.droog@gmail.com> - 2016-07-31 15:03 -0700
Re: EXIT_SUCCESS Real Troll <real.troll@trolls.com> - 2016-07-31 18:09 -0400
Re: EXIT_SUCCESS luser droog <luser.droog@gmail.com> - 2016-07-31 15:36 -0700
Re: EXIT_SUCCESS James Kuyper <jameskuyper@verizon.net> - 2016-08-01 10:09 -0400
Page 3 of 4 — ← Prev page 1 2 [3] 4 Next page →
| From | Richard Heathfield <rjh@cpax.org.uk> |
|---|---|
| Date | 2016-07-25 22:03 +0100 |
| Message-ID | <nn5ur2$vdd$1@dont-email.me> |
| In reply to | #91059 |
On 25/07/16 22:00, BartC wrote: > On 25/07/2016 19:14, Richard Heathfield wrote: >> On 25/07/16 19:04, Keith Thompson wrote: >>> Richard Heathfield <rjh@cpax.org.uk> writes: > >>>>>> size_t maxval = sizeof numbers / sizeof numbers[0] - 1; >>>>>> return numbers[a <= maxval ? a : maxval]; > >>>> A slightly better solution (which, of course, I thought of /after/ >>>> posting) would have been to make maxval static. >>> >>> And const? >> >> Yep. I thought of that one after posting the one I thought of after >> posting the first one. Shades of IEFBR14. > > So: > > static const size_t maxval = ... > > before you've even started expressing the size of the array? Give it a rest, BartC. > I might go with: > > #define LEN(a) (sizeof (a)/sizeof ((a)[0])) > #define UPB(a) (LEN(a)-1) And that makes things /simpler/? Furrfu! -- Richard Heathfield Email: rjh at cpax dot org dot uk "Usenet is a strange place" - dmr 29 July 1999 Sig line 4 vacant - apply within
[toc] | [prev] | [next] | [standalone]
| From | BartC <bc@freeuk.com> |
|---|---|
| Date | 2016-07-25 22:41 +0100 |
| Message-ID | <nn611p$8av$1@dont-email.me> |
| In reply to | #91060 |
On 25/07/2016 22:03, Richard Heathfield wrote: > On 25/07/16 22:00, BartC wrote: >> >> So: >> >> static const size_t maxval = ... >> >> before you've even started expressing the size of the array? > > Give it a rest, BartC. People have different opinions on how to write code. And they're entitled to express their opinions here. I think your example is heavy-handed for what is supposed to be a compile-time constant. >> I might go with: >> >> #define LEN(a) (sizeof (a)/sizeof ((a)[0])) >> #define UPB(a) (LEN(a)-1) > > And that makes things /simpler/? Furrfu! You write those macros once. You use them everywhere. Or you could choose to write 'sizeof(A)/sizeof(A[0])' over and over again. -- Bartc
[toc] | [prev] | [next] | [standalone]
| From | jadill33@gmail.com |
|---|---|
| Date | 2016-07-25 14:50 -0700 |
| Message-ID | <b75fc3d1-6bc7-414c-9e32-0ae27b646378@googlegroups.com> |
| In reply to | #91062 |
On Monday, July 25, 2016 at 5:41:19 PM UTC-4, Bart wrote: > On 25/07/2016 22:03, Richard Heathfield wrote: > > On 25/07/16 22:00, BartC wrote: > > >> > >> So: > >> > >> static const size_t maxval = ... > >> > >> before you've even started expressing the size of the array? > > > > Give it a rest, BartC. > > People have different opinions on how to write code. > > And they're entitled to express their opinions here. > > I think your example is heavy-handed for what is supposed to be a > compile-time constant. > > >> I might go with: > >> > >> #define LEN(a) (sizeof (a)/sizeof ((a)[0])) > >> #define UPB(a) (LEN(a)-1) > > > > And that makes things /simpler/? Furrfu! > > You write those macros once. > > You use them everywhere. > > Or you could choose to write 'sizeof(A)/sizeof(A[0])' over and over again. I've always liked 'sizeof_array' as the name I use for this macro. LEN is too generic for my tastes. And yes, it's worth using a macro if you have to do it more than once. I can't imagine wanting to maintaining dozens of different instances of this construct scattered throughout a codebase. My test code is made up of statically defined arrays of stuff, so I see it plenty enough. Best regards, John D.
[toc] | [prev] | [next] | [standalone]
| From | Keith Thompson <kst-u@mib.org> |
|---|---|
| Date | 2016-07-25 15:04 -0700 |
| Message-ID | <ln7fc9cr2b.fsf@kst-u.example.com> |
| In reply to | #91059 |
BartC <bc@freeuk.com> writes:
> On 25/07/2016 19:14, Richard Heathfield wrote:
>> On 25/07/16 19:04, Keith Thompson wrote:
>>> Richard Heathfield <rjh@cpax.org.uk> writes:
>
>>>>>> size_t maxval = sizeof numbers / sizeof numbers[0] - 1;
>>>>>> return numbers[a <= maxval ? a : maxval];
>
>>>> A slightly better solution (which, of course, I thought of /after/
>>>> posting) would have been to make maxval static.
>>>
>>> And const?
>>
>> Yep. I thought of that one after posting the one I thought of after
>> posting the first one. Shades of IEFBR14.
>
> So:
>
> static const size_t maxval = ...
>
> before you've even started expressing the size of the array?
What?
The size of the array is determined by the initializer.
We were merely talking about adding "const" and "static" to the existing
declaration of "maxval", like this:
static const char *get_foo(size_t a)
{
static const char *numbers[] =
{
"zero",
"one",
"two",
"three",
"four"
};
static const size_t maxval = sizeof numbers / sizeof numbers[0] - 1;
return numbers[a <= maxval ? a : maxval];
}
[...]
--
Keith Thompson (The_Other_Keith) kst-u@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"
[toc] | [prev] | [next] | [standalone]
| From | David Brown <david.brown@hesbynett.no> |
|---|---|
| Date | 2016-07-26 10:43 +0200 |
| Message-ID | <nn77rf$e7s$1@dont-email.me> |
| In reply to | #91041 |
On 25/07/16 20:04, Keith Thompson wrote:
> Richard Heathfield <rjh@cpax.org.uk> writes:
>> On 25/07/16 17:06, Richard Bos wrote:
>>> Richard Heathfield <rjh@cpax.org.uk> wrote:
>>>
>>>> On 25/07/16 12:42, jgh@mdfs.net wrote:
>>>
>>>> static const char *get_foo(size_t a)
>>>> {
>>>> static const char *numbers[] =
>>>> {
>>>> "zero",
>>>> "one",
>>>> "two",
>>>> "three",
>>>> "four"
>>>> };
>>>> size_t maxval = sizeof numbers / sizeof numbers[0] - 1;
>>>>
>>>> return numbers[a <= maxval ? a : maxval];
>>>> }
>>>
>>> A good solution,
>>
>> A slightly better solution (which, of course, I thought of /after/
>> posting) would have been to make maxval static.
>
> And const?
>
That would seem natural.
Neither "static" nor "const" will change the efficiency of the generated
code (assuming basic optimisations), since the compiler can see that
maxval never changes and cannot be accessed outside the function. My
normal practice here would be to make maxval const, but not static -
since it is obvious that the value is a compile-time constant, there is
no need to ask the compiler explicitly to preserve it across function
calls by adding "static". But it is not something I would be
particularly concerned about.
[toc] | [prev] | [next] | [standalone]
| From | jadill33@gmail.com |
|---|---|
| Date | 2016-07-25 14:41 -0700 |
| Message-ID | <9c263285-548c-4f42-8d54-94ba1c3628ab@googlegroups.com> |
| In reply to | #91032 |
On Monday, July 25, 2016 at 12:42:00 PM UTC-4, Richard Heathfield wrote:
> On 25/07/16 17:06, Richard Bos wrote:
> > Richard Heathfield <r...@...uk> wrote:
> >
> >> On 25/07/16 12:42, j...@...net wrote:
> >
> >> static const char *get_foo(size_t a)
> >> {
> >> static const char *numbers[] =
> >> {
> >> "zero",
> >> "one",
> >> "two",
> >> "three",
> >> "four"
> >> };
> >> size_t maxval = sizeof numbers / sizeof numbers[0] - 1;
> >>
> >> return numbers[a <= maxval ? a : maxval];
> >> }
> >
> > A good solution,
>
> A slightly better solution (which, of course, I thought of /after/
> posting) would have been to make maxval static.
>
> > but it only works well if the accepted values of a are
> > contiguous (or nearly so, with at most a handful of ugly extra defaults
> > scattered through the array).
>
> That's right. I fitted the solution to the problem. If the problem
> changes, sometimes the solution changes too (for example, to a perfect
> hash or even some kind of dictionary).
I think I have you covered here.
\code
#include <stdio.h>
#include <assert.h>
typedef struct value_string
{
unsigned int value;
const char* strptr;
} value_string;
const char*
val_to_str( const unsigned int val, const value_string* vs, const char* unknown_str );
const char*
try_val_to_str( const unsigned int val, const value_string *vs );
const char*
try_val_to_str_idx( const unsigned int val, const value_string *vs, int *idx );
/* Tries to match 'val' against each element in the value_string array 'vs'.
Returns the associated string ptr on a match, 'unknown_str' on failure. */
const char*
val_to_str( const unsigned int val, const value_string* vs, const char* unknown_str )
{
const char* str;
str = try_val_to_str( val, vs );
return str != NULL ? str : unknown_str;
}
/*
* Tries to match 'val' against each element in the value_string array 'vs'.
* On a match, returns the associated string ptr, and sets "*idx" to the
* index in that table. On failure, returns NULL, and sets "*idx" to -1.
*/
const char*
try_val_to_str_idx( const unsigned int val, const value_string* vs, int* idx )
{
int i = 0;
assert( idx != NULL );
if ( vs )
{
while ( vs[i].strptr )
{
if ( vs[i].value == val )
{
*idx = i;
return vs[i].strptr;
}
++i;
}
}
*idx = -1;
return NULL;
}
/* Like try_val_to_str_idx(), but doesn't return the index. */
const char*
try_val_to_str( const unsigned int val, const value_string* vs )
{
int ignore_me;
return try_val_to_str_idx( val, vs, &ignore_me );
}
static const value_string numbers_vals[] =
{
{ 0, "zero" },
{ 1, "one" },
{ 2, "two" },
{ 3, "three" },
{ 4, "four" },
{ 7, "seven" },
{ 8, "eight" },
{ 9, "nine" },
{ 0, NULL }
};
int main( void )
{
int i;
for ( i = 0; i < 10; ++i ) {
printf( "%s\n", val_to_str( i, numbers_vals, "?" ) );
}
return 0;
}
\endcode
Refactoring it to mimic your example is left as an exercise for the
reader.
Best regards,
John D.
[toc] | [prev] | [next] | [standalone]
| From | David Brown <david.brown@hesbynett.no> |
|---|---|
| Date | 2016-07-26 10:59 +0200 |
| Message-ID | <nn78qd$h3u$1@dont-email.me> |
| In reply to | #91063 |
On 25/07/16 23:41, jadill33@gmail.com wrote:
> On Monday, July 25, 2016 at 12:42:00 PM UTC-4, Richard Heathfield wrote:
>> On 25/07/16 17:06, Richard Bos wrote:
>>> Richard Heathfield <r...@...uk> wrote:
>>>
<snip>
>>
>>> but it only works well if the accepted values of a are
>>> contiguous (or nearly so, with at most a handful of ugly extra defaults
>>> scattered through the array).
>>
>> That's right. I fitted the solution to the problem. If the problem
>> changes, sometimes the solution changes too (for example, to a perfect
>> hash or even some kind of dictionary).
>
> I think I have you covered here.
>
> \code
<snip linear search>
> \endcode
>
> Refactoring it to mimic your example is left as an exercise for the
> reader.
>
If the accepted values don't fit a nice pattern to allow a simple
solution such as Richard's, why not just use a switch?
static const char *get_foo(size_t a) {
switch (a) {
case 0 : return "zero";
case 1 : return "one";
case 2 : return "two";
case 3 : return "three";
default : return "four";
}
}
Then the compiler can sort out the best arrangement of tables,
calculations, comparisons, etc. If your set of values and strings is
big enough to warrant something smarter than such a switch, then it is
probably big enough to warrant something smarter than a linear search.
You would at least want a binary search, if not a hash of some sort (as
suggested by Richard).
[toc] | [prev] | [next] | [standalone]
| From | jadill33@gmail.com |
|---|---|
| Date | 2016-07-27 06:20 -0700 |
| Message-ID | <db999c15-dd8b-4dbe-9f55-936d56ca32c9@googlegroups.com> |
| In reply to | #91082 |
On Tuesday, July 26, 2016 at 5:00:08 AM UTC-4, David Brown wrote:
> On 25/07/16 23:41, j...@...com wrote:
> > On Monday, July 25, 2016 at 12:42:00 PM UTC-4, Richard Heathfield wrote:
> >> On 25/07/16 17:06, Richard Bos wrote:
> >>> Richard Heathfield <r...@...uk> wrote:
> >>>
> <snip>
> >>
> >>> but it only works well if the accepted values of a are
> >>> contiguous (or nearly so, with at most a handful of ugly extra defaults
> >>> scattered through the array).
> >>
> >> That's right. I fitted the solution to the problem. If the problem
> >> changes, sometimes the solution changes too (for example, to a perfect
> >> hash or even some kind of dictionary).
> >
> > I think I have you covered here.
> >
> > \code
> <snip linear search>
> > \endcode
> >
> > Refactoring it to mimic your example is left as an exercise for the
> > reader.
> >
>
> If the accepted values don't fit a nice pattern to allow a simple
> solution such as Richard's, why not just use a switch?
Depends on the scope of the problem. If it's a one time translation in a
small embedded system, then a single switch is fine. If you have to
translate lots of enumerated values to strings for human readability, as
you might find in a packet analyzer or a MIL-1553 traffic bus monitor,
then raw coding hundreds of these switch statements is not ideal.
> static const char *get_foo(size_t a) {
> switch (a) {
> case 0 : return "zero";
> case 1 : return "one";
> case 2 : return "two";
> case 3 : return "three";
> default : return "four";
> }
> }
>
> Then the compiler can sort out the best arrangement of tables,
> calculations, comparisons, etc. If your set of values and strings is
> big enough to warrant something smarter than such a switch, then it is
> probably big enough to warrant something smarter than a linear search.
> You would at least want a binary search, if not a hash of some sort (as
> suggested by Richard).
Most of the enumerated value to string tranlations that I have are small.
I just have a lot of them. If I had a lot of large tables, then yes I
would consider making them more complex. In my translations, the majority
of translations are simple binary conditions like "on/off", "true/false",
though there are some tables with a few dozen elements. For those, I guess
I consider the increase in code complexity to not be worth the (potentially
imperceptible) decrease in efficiency.
Best regards,
John D.
[toc] | [prev] | [next] | [standalone]
| From | Ben Bacarisse <ben.usenet@bsb.me.uk> |
|---|---|
| Date | 2016-07-27 15:44 +0100 |
| Message-ID | <87h9bbf8d7.fsf@bsb.me.uk> |
| In reply to | #91132 |
jadill33@gmail.com writes:
> On Tuesday, July 26, 2016 at 5:00:08 AM UTC-4, David Brown wrote:
>> On 25/07/16 23:41, j...@...com wrote:
>> > On Monday, July 25, 2016 at 12:42:00 PM UTC-4, Richard Heathfield wrote:
>> >> On 25/07/16 17:06, Richard Bos wrote:
>> >>> Richard Heathfield <r...@...uk> wrote:
>> >>>
>> <snip>
>> >>
>> >>> but it only works well if the accepted values of a are
>> >>> contiguous (or nearly so, with at most a handful of ugly extra defaults
>> >>> scattered through the array).
>> >>
>> >> That's right. I fitted the solution to the problem. If the problem
>> >> changes, sometimes the solution changes too (for example, to a perfect
>> >> hash or even some kind of dictionary).
>> >
>> > I think I have you covered here.
>> >
>> > \code
>> <snip linear search>
>> > \endcode
>> >
>> > Refactoring it to mimic your example is left as an exercise for the
>> > reader.
>> >
>>
>> If the accepted values don't fit a nice pattern to allow a simple
>> solution such as Richard's, why not just use a switch?
>
> Depends on the scope of the problem. If it's a one time translation in a
> small embedded system, then a single switch is fine. If you have to
> translate lots of enumerated values to strings for human readability, as
> you might find in a packet analyzer or a MIL-1553 traffic bus monitor,
> then raw coding hundreds of these switch statements is not ideal.
<snip>
> Most of the enumerated value to string tranlations that I have are small.
> I just have a lot of them.
Do you know about the X macro trick (it may have a proper name, but
that's what I call it)? You can use it generate code for arbitrary
lists like this. First, you put you enum into a file (list.h in this
case):
X(red, 42)
X(green, 34)
X(blue, 12)
Here, I've allowed for the full generality with arbitrary numbers. Now
you can define the enum like this:
#define X(name, num) name = num,
enum List {
#include "list.h"
};
and, elsewhere, you can generate the function to map values to strings
like this:
const char *enum_to_str(unsigned int e)
{
switch (e) {
#define X(name, num) case name: return #name;
#include "list.h"
}
return "default";
}
Of course, with consecutive values, you can use similar code to make a
table rather than a switch and the X macro list would just need the name
rather than a name and a value.
<snip>
--
Ben.
[toc] | [prev] | [next] | [standalone]
| From | Ben Bacarisse <ben.usenet@bsb.me.uk> |
|---|---|
| Date | 2016-07-27 16:22 +0100 |
| Message-ID | <87zip3ds1d.fsf@bsb.me.uk> |
| In reply to | #91134 |
ram@zedat.fu-berlin.de (Stefan Ram) writes: > Ben Bacarisse <ben.usenet@bsb.me.uk> writes: >>Do you know about the X macro trick (it may have a proper name, but > > Know? I /invented/ it! <snip code> > Ok, I found this out by myself, but probably I am neither > the only nor the first one, who came up with this idea. Yes, I think it's been invented dozens of times. <snip> -- Ben.
[toc] | [prev] | [next] | [standalone]
| From | Joe Pfeiffer <pfeiffer@cs.nmsu.edu> |
|---|---|
| Date | 2016-07-27 11:20 -0600 |
| Message-ID | <1binvrf16l.fsf@pfeifferfamily.net> |
| In reply to | #91134 |
ram@zedat.fu-berlin.de (Stefan Ram) writes:
> Ben Bacarisse <ben.usenet@bsb.me.uk> writes:
>>Do you know about the X macro trick (it may have a proper name, but
>
> Know? I /invented/ it!
>
> /*
> < filename = [stringcall.c]
> encoding = [ANSI_X3.4-1968]
> notation = [ISO/IEC 9899:1999 (E)]
> author = [Stefan Ram] > */
> #include <stdio.h> /* puts */
> #include <string.h> /* strcmp */
> #define F(r,n,b) r n b
> #define FUNCTIONS \
> F( void, iota, (){ puts( "Lima" ); } )\
> F( void, zeta, (){ puts( "Zulu" ); } )\
> /**/
> FUNCTIONS
> #undef F
> #define F(r,n,b) n,
> void( * const function[] )() ={ FUNCTIONS };
> #undef F
> #define F(r,n,b) #n,
> char const * const name[] ={ FUNCTIONS };
> #undef F
> int const top = sizeof name / sizeof 0[ name ];
> void call( char const * const n )
> { for( int i = 0; i < top; ++i )
> if( !strcmp( n, i[ name ]))i[ function ](); }
> int main( void ){ call( "iota" ); call( "zeta" ); }
>
> Ok, I found this out by myself, but probably I am neither
> the only nor the first one, who came up with this idea.
>
> Maybe one can do this with functions too?
>
> #include <stdio.h>
>
> void( *f )( char const *, int n );
>
> void g()
> { f( "alpha", 2 );
> f( "beta", 4 ); }
>
> void putstring( char const * const text, int const n )
> { puts( text ); }
>
> void putnumber( char const * const text, int const n )
> { printf( "%d\n", n ); }
>
> int main( void )
> { f = putstring; g();
> f = putnumber; g(); }
>
> alpha
> beta
> 2
> 4
>
> See? Yet another invention of mine!
>
> (I do not remember having seen this trick with functions
> before, but probably ...)
I did pretty much the same thing for a program's configuration files
once. I used a macro I called "process" that took information about a
data structure as its arguments. One source file #defined process as
read_field, another as write_field. Now my .h file could just "process"
all the fields in order, so any changes I made in the configuration file
format were automatically tracked both reading and writing it.
[toc] | [prev] | [next] | [standalone]
| From | luser droog <luser.droog@gmail.com> |
|---|---|
| Date | 2016-07-27 15:32 -0700 |
| Message-ID | <ed2cc33d-fe6d-4b69-92ac-41f542e06bb5@googlegroups.com> |
| In reply to | #91134 |
On Wednesday, July 27, 2016 at 9:45:01 AM UTC-5, Ben Bacarisse wrote:
> jadill33@gmail.com writes:
>
> > On Tuesday, July 26, 2016 at 5:00:08 AM UTC-4, David Brown wrote:
> >> On 25/07/16 23:41, j...@...com wrote:
> >> > On Monday, July 25, 2016 at 12:42:00 PM UTC-4, Richard Heathfield wrote:
> >> >> On 25/07/16 17:06, Richard Bos wrote:
> >> >>> Richard Heathfield <r...@...uk> wrote:
> >> >>>
> >> <snip>
> >> >>
> >> >>> but it only works well if the accepted values of a are
> >> >>> contiguous (or nearly so, with at most a handful of ugly extra defaults
> >> >>> scattered through the array).
> >> >>
> >> >> That's right. I fitted the solution to the problem. If the problem
> >> >> changes, sometimes the solution changes too (for example, to a perfect
> >> >> hash or even some kind of dictionary).
> >> >
> >> > I think I have you covered here.
> >> >
> >> > \code
> >> <snip linear search>
> >> > \endcode
> >> >
> >> > Refactoring it to mimic your example is left as an exercise for the
> >> > reader.
> >> >
> >>
> >> If the accepted values don't fit a nice pattern to allow a simple
> >> solution such as Richard's, why not just use a switch?
> >
> > Depends on the scope of the problem. If it's a one time translation in a
> > small embedded system, then a single switch is fine. If you have to
> > translate lots of enumerated values to strings for human readability, as
> > you might find in a packet analyzer or a MIL-1553 traffic bus monitor,
> > then raw coding hundreds of these switch statements is not ideal.
> <snip>
> > Most of the enumerated value to string tranlations that I have are small.
> > I just have a lot of them.
>
> Do you know about the X macro trick (it may have a proper name, but
> that's what I call it)? You can use it generate code for arbitrary
> lists like this.
I love X Macros! But let me show an alternate form that I think is nicer.
>First, you put you enum into a file (list.h in this
> case):
>
> X(red, 42)
> X(green, 34)
> X(blue, 12)
>
The alternative is to put the list into a macro. For reasons to be
elaborated later, the macro to call on each value `X` it itself
passed-in to this macro.
#define MY_LIST(X) \
X(red, 42) \
X(green, 34) \
X(blue, 12) \
/**/
> Here, I've allowed for the full generality with arbitrary numbers. Now
> you can define the enum like this:
>
> #define X(name, num) name = num,
> enum List {
> #include "list.h"
> };
>
For the alternative, rather than calling it `X` here, give it a meaningful
name.
#define DEFINE_ENUM_VALUES(name, num) name = num,
enum List {
MY_LIST(DEFINE_ENUM_VALUES)
};
> and, elsewhere, you can generate the function to map values to strings
> like this:
>
> const char *enum_to_str(unsigned int e)
> {
> switch (e) {
> #define X(name, num) case name: return #name;
> #include "list.h"
> }
> return "default";
> }
Same here. `X` can be a more meaningful name.
const char *enum_to_str(unsigned int e)
{
switch (e) {
#define YIELD_STRING(name, num) case name: return #name;
MY_LIST(YIELD_STRING)
}
return "default";
}
> Of course, with consecutive values, you can use similar code to make a
> table rather than a switch and the X macro list would just need the name
> rather than a name and a value.
>
Ditto. Thanks for bringing this up!
[toc] | [prev] | [next] | [standalone]
| From | Ben Bacarisse <ben.usenet@bsb.me.uk> |
|---|---|
| Date | 2016-07-28 14:47 +0100 |
| Message-ID | <8760rpzxgj.fsf@bsb.me.uk> |
| In reply to | #91180 |
luser droog <luser.droog@gmail.com> writes: > On Wednesday, July 27, 2016 at 9:45:01 AM UTC-5, Ben Bacarisse wrote: >> jadill33@gmail.com writes: <snip> >> > Depends on the scope of the problem. If it's a one time translation in a >> > small embedded system, then a single switch is fine. If you have to >> > translate lots of enumerated values to strings for human readability, as >> > you might find in a packet analyzer or a MIL-1553 traffic bus monitor, >> > then raw coding hundreds of these switch statements is not ideal. >> <snip> >> > Most of the enumerated value to string tranlations that I have are small. >> > I just have a lot of them. >> >> Do you know about the X macro trick (it may have a proper name, but >> that's what I call it)? You can use it generate code for arbitrary >> lists like this. > > I love X Macros! But let me show an alternate form that I think is nicer. > >>First, you put you enum into a file (list.h in this >> case): >> >> X(red, 42) >> X(green, 34) >> X(blue, 12) >> > > The alternative is to put the list into a macro. For reasons to be > elaborated later, the macro to call on each value `X` it itself > passed-in to this macro. > > #define MY_LIST(X) \ > X(red, 42) \ > X(green, 34) \ > X(blue, 12) \ > /**/ Yes, there's a lot to be said for doing it that way round (passing in a macro name at expansion time), but when the lists are being automatically generated it can be handy just to have them in a file to #include. Mind you, the extra line and trailing \s are not much bother (provided you can generate a suitable name) so this way would work in that situation too. <snip> > Ditto. Thanks for bringing this up! You're welcome. Thanks for expanding on it. It's method worth knowing. -- Ben.
[toc] | [prev] | [next] | [standalone]
| From | Keith Thompson <kst-u@mib.org> |
|---|---|
| Date | 2016-07-25 08:46 -0700 |
| Message-ID | <lnk2g9d8jy.fsf@kst-u.example.com> |
| In reply to | #90965 |
jgh@mdfs.net writes:
> Keith Thompson wrote:
>> A better solution is:
>> if (a == 0) result = "zero";
>> else if (a == 1) result = "one";
>> else if (a == 2) result = "two";
>> else if (a == 3) result = "three";
>> else result = "four";
>> return result;
>
> If you want to do multiple ifs like that, I prefer to do:
> result = "four"; // default
> if (a == 0) result = "zero";
> if (a == 1) result = "one";
> if (a == 2) result = "two";
> if (a == 3) result = "three";
> return result;
>
> jgh
Why do you omit the "else"s?
Of course in this specific case a switch statement would be clearer
(and, less importantly, faster), but I presume the example is meant
as a more general illustration, covering cases where "switch" would
not work.
--
Keith Thompson (The_Other_Keith) kst-u@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"
[toc] | [prev] | [next] | [standalone]
| From | David Brown <david.brown@hesbynett.no> |
|---|---|
| Date | 2016-07-26 12:44 +0200 |
| Message-ID | <nn7ets$4t6$1@dont-email.me> |
| In reply to | #91010 |
On 25/07/16 17:46, Keith Thompson wrote: > jgh@mdfs.net writes: >> Keith Thompson wrote: >>> A better solution is: >>> if (a == 0) result = "zero"; >>> else if (a == 1) result = "one"; >>> else if (a == 2) result = "two"; >>> else if (a == 3) result = "three"; >>> else result = "four"; >>> return result; >> >> If you want to do multiple ifs like that, I prefer to do: >> result = "four"; // default >> if (a == 0) result = "zero"; >> if (a == 1) result = "one"; >> if (a == 2) result = "two"; >> if (a == 3) result = "three"; >> return result; >> >> jgh > > Why do you omit the "else"s? Presumably the else's were omitted because they are not necessary, and perhaps also because in many coding standards they would require brackets to added. The else's don't make the code any clearer to the reader, and are unlikely to make any difference to a compiler's code generation (assuming at least basic optimisation). > > Of course in this specific case a switch statement would be clearer > (and, less importantly, faster), but I presume the example is meant > as a more general illustration, covering cases where "switch" would > not work. >
[toc] | [prev] | [next] | [standalone]
| From | Keith Thompson <kst-u@mib.org> |
|---|---|
| Date | 2016-07-26 08:24 -0700 |
| Message-ID | <lnh9bcbexi.fsf@kst-u.example.com> |
| In reply to | #91085 |
David Brown <david.brown@hesbynett.no> writes:
> On 25/07/16 17:46, Keith Thompson wrote:
>> jgh@mdfs.net writes:
>>> Keith Thompson wrote:
>>>> A better solution is:
>>>> if (a == 0) result = "zero";
>>>> else if (a == 1) result = "one";
>>>> else if (a == 2) result = "two";
>>>> else if (a == 3) result = "three";
>>>> else result = "four";
>>>> return result;
>>>
>>> If you want to do multiple ifs like that, I prefer to do:
>>> result = "four"; // default
>>> if (a == 0) result = "zero";
>>> if (a == 1) result = "one";
>>> if (a == 2) result = "two";
>>> if (a == 3) result = "three";
>>> return result;
>>>
>>> jgh
>>
>> Why do you omit the "else"s?
>
> Presumably the else's were omitted because they are not necessary, and
> perhaps also because in many coding standards they would require
> brackets to added. The else's don't make the code any clearer to the
> reader, and are unlikely to make any difference to a compiler's code
> generation (assuming at least basic optimisation).
They might not be necessary in this particular case, but when I read the
code I have to verify that no more than one of the conditions can be
true. In a more complicated example, that could be difficult.
I doubt that a coding standard would require curly braces with "else"
but not require them without it. And if it did, the answer would be to
add the braces.
(In any case, thanks for your response, but I asked why jgh ommitted the
"else"s.)
>> Of course in this specific case a switch statement would be clearer
>> (and, less importantly, faster), but I presume the example is meant
>> as a more general illustration, covering cases where "switch" would
>> not work.
--
Keith Thompson (The_Other_Keith) kst-u@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"
[toc] | [prev] | [next] | [standalone]
| From | David Brown <david.brown@hesbynett.no> |
|---|---|
| Date | 2016-07-26 19:26 +0200 |
| Message-ID | <nn86fj$sip$1@dont-email.me> |
| In reply to | #91089 |
On 26/07/16 17:24, Keith Thompson wrote: > David Brown <david.brown@hesbynett.no> writes: >> On 25/07/16 17:46, Keith Thompson wrote: >>> jgh@mdfs.net writes: >>>> Keith Thompson wrote: >>>>> A better solution is: >>>>> if (a == 0) result = "zero"; >>>>> else if (a == 1) result = "one"; >>>>> else if (a == 2) result = "two"; >>>>> else if (a == 3) result = "three"; >>>>> else result = "four"; >>>>> return result; >>>> >>>> If you want to do multiple ifs like that, I prefer to do: >>>> result = "four"; // default >>>> if (a == 0) result = "zero"; >>>> if (a == 1) result = "one"; >>>> if (a == 2) result = "two"; >>>> if (a == 3) result = "three"; >>>> return result; >>>> >>>> jgh >>> >>> Why do you omit the "else"s? >> >> Presumably the else's were omitted because they are not necessary, and >> perhaps also because in many coding standards they would require >> brackets to added. The else's don't make the code any clearer to the >> reader, and are unlikely to make any difference to a compiler's code >> generation (assuming at least basic optimisation). > > They might not be necessary in this particular case, but when I read the > code I have to verify that no more than one of the conditions can be > true. In a more complicated example, that could be difficult. It all depends on the style of code you are used to. But you are certainly right that in a more complicated example, you would probably want to structure the code a little differently. > > I doubt that a coding standard would require curly braces with "else" > but not require them without it. And if it did, the answer would be to > add the braces. It is not unreasonable. A coding standard could allow unbracketed single-line if statements with a simple "then" clause (such as "if (a == 0) result = "zero";) while insisting on brackets for multi-line statements, complex statements, or else clauses. > > (In any case, thanks for your response, but I asked why jgh ommitted the > "else"s.) Yes, of course - that will be up to him to respond. I can only tell you why /I/ might well omit the else's in such a code snippet. > >>> Of course in this specific case a switch statement would be clearer >>> (and, less importantly, faster), but I presume the example is meant >>> as a more general illustration, covering cases where "switch" would >>> not work. >
[toc] | [prev] | [next] | [standalone]
| From | BartC <bc@freeuk.com> |
|---|---|
| Date | 2016-07-26 18:03 +0100 |
| Message-ID | <nn855l$nn4$1@dont-email.me> |
| In reply to | #91085 |
On 26/07/2016 11:44, David Brown wrote: > On 25/07/16 17:46, Keith Thompson wrote: >> jgh@mdfs.net writes: >>> Keith Thompson wrote: >>>> A better solution is: >>>> if (a == 0) result = "zero"; >>>> else if (a == 1) result = "one"; >>>> else if (a == 2) result = "two"; >>>> else if (a == 3) result = "three"; >>>> else result = "four"; >>>> return result; >>> >>> If you want to do multiple ifs like that, I prefer to do: >>> result = "four"; // default >>> if (a == 0) result = "zero"; >>> if (a == 1) result = "one"; >>> if (a == 2) result = "two"; >>> if (a == 3) result = "three"; >>> return result; >>> >>> jgh >> >> Why do you omit the "else"s? > > Presumably the else's were omitted because they are not necessary, and > perhaps also because in many coding standards they would require > brackets to added. The else's don't make the code any clearer to the > reader, and are unlikely to make any difference to a compiler's code > generation (assuming at least basic optimisation). It looks wrong. The options are exclusive so they should be expressed that way, by using an if-else chain perhaps. Otherwise the human reader needs to double-check that at most one option is executed, and so does the compiler. (You shouldn't really rely on a compiler either to do the job of tidying up poor code like this. The clear intent of this code, as written, is to always evaluate four if-statements. I believe in a compiler doing what the programmer intended.) This code might even lead to people posting on here as to why the expected else clauses are omitted! -- Bartc
[toc] | [prev] | [next] | [standalone]
| From | Ken Brody <kenbrody@spamcop.net> |
|---|---|
| Date | 2016-07-11 19:15 -0400 |
| Message-ID | <nm19be$q6v$1@dont-email.me> |
| In reply to | #90136 |
On 7/8/2016 5:46 PM, James Kuyper wrote: > On 07/08/2016 01:03 PM, Gareth Owen wrote: >> Keith Thompson <kst-u@mib.org> writes: >> >>> I would look forward to your explanation of how that makes any sense >>> at all (preferably, as Richard suggests, in a different thread) >>> if I thought there was a reasonable chance of that happening. >> >> Well if thought "structured" meant "SESE in all circumstances", and your >> program had at least one failure mode and one success mode you'd store >> your return value in a variable and return it in the sole return-statement. > > One of my first significant programming projects involved trying to make > a minor change to a text-based computer game written in spaghetti Basic, > that was deliberately padded to come out to exactly 1000 lines of code. > My first paid programming job involved unraveling a big ball of > spaghetti Fortran code. [...] Speaking of BASIC and FORTRAN... One of my first significant programming projects was to rewrite a rather hefty Star Trek program written in FORTRAN into a rather wimpy version of BASIC. (Why? Because that's the only language that my high school had available "way back when".) -- Kenneth Brody
[toc] | [prev] | [next] | [standalone]
| From | supercat@casperkitty.com |
|---|---|
| Date | 2016-07-11 16:46 -0700 |
| Message-ID | <76a61972-7163-4711-a325-000287eeeb21@googlegroups.com> |
| In reply to | #90243 |
On Monday, July 11, 2016 at 6:16:06 PM UTC-5, Ken Brody wrote: > One of my first significant programming projects was to rewrite a rather > hefty Star Trek program written in FORTRAN into a rather wimpy version of > BASIC. (Why? Because that's the only language that my high school had > available "way back when".) Did you know that the game was ported to the Atari 2600 Video Computer System in 1980? The lack of floating-point support meant one could only move or fire in eight directions, and the ratings at the end failed to consider initial mission parameters so eking out a victory when given a huge number of enemies and minimal resources would be rewarded with a poor rating, while coasting through on an easy mission with more generous resources would yield a better one. Aside from those details, though, the game is pretty much there.
[toc] | [prev] | [next] | [standalone]
Page 3 of 4 — ← Prev page 1 2 [3] 4 Next page →
Back to top | Article view | comp.lang.c
csiph-web