Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]


Groups > comp.arch.embedded > #24987 > unrolled thread

XC8 novice question

Started byrwood <rwoodl@nowhere.com>
First post2016-09-11 15:02 +0800
Last post2016-09-12 17:33 +0000
Articles 20 on this page of 53 — 12 participants

Back to article view | Back to comp.arch.embedded


Contents

  XC8 novice question rwood <rwoodl@nowhere.com> - 2016-09-11 15:02 +0800
    Re: XC8 novice question Don Y <blockedofcourse@foo.invalid> - 2016-09-11 02:55 -0700
      Re: XC8 novice question rwood <rwoodl@nowhere.com> - 2016-09-11 18:25 +0800
        Re: XC8 novice question David Brown <david.brown@hesbynett.no> - 2016-09-11 13:35 +0200
          Re: XC8 novice question Don Y <blockedofcourse@foo.invalid> - 2016-09-11 07:32 -0700
            Re: XC8 novice question David Brown <david.brown@hesbynett.no> - 2016-09-11 16:58 +0200
              Re: XC8 novice question Don Y <blockedofcourse@foo.invalid> - 2016-09-11 13:15 -0700
                Re: XC8 novice question David Brown <david.brown@hesbynett.no> - 2016-09-12 08:55 +0200
                  Re: XC8 novice question Don Y <blockedofcourse@foo.invalid> - 2016-09-12 02:41 -0700
                    Re: XC8 novice question Mike Perkins <spam@spam.com> - 2016-09-12 13:16 +0100
                      Re: XC8 novice question David Brown <david.brown@hesbynett.no> - 2016-09-12 14:56 +0200
                        Re: XC8 novice question Mike Perkins <spam@spam.com> - 2016-09-12 14:33 +0100
                          Re: XC8 novice question David Brown <david.brown@hesbynett.no> - 2016-09-12 16:11 +0200
                        Re: XC8 novice question Jack <jack4747@gmail.com> - 2016-09-12 07:50 -0700
                          Re: XC8 novice question David Brown <david.brown@hesbynett.no> - 2016-09-12 22:23 +0200
                        Re: XC8 novice question Les Cargill <lcargill99@comcast.com> - 2016-09-12 15:34 -0500
                      Re: XC8 novice question Don Y <blockedofcourse@foo.invalid> - 2016-09-12 08:44 -0700
                    Re: XC8 novice question David Brown <david.brown@hesbynett.no> - 2016-09-12 14:35 +0200
                      Re: XC8 novice question Don Y <blockedofcourse@foo.invalid> - 2016-09-12 08:19 -0700
                        Re: XC8 novice question David Brown <david.brown@hesbynett.no> - 2016-09-12 23:11 +0200
                          Re: XC8 novice question Dennis <dennis@none.none> - 2016-09-12 17:04 -0500
                            Re: XC8 novice question Don Y <blockedofcourse@foo.invalid> - 2016-09-12 22:49 -0700
                            Re: XC8 novice question David Brown <david.brown@hesbynett.no> - 2016-09-13 09:04 +0200
                          Re: XC8 novice question Hans-Bernhard Bröker <HBBroeker@t-online.de> - 2016-09-13 00:16 +0200
                          Re: XC8 novice question Don Y <blockedofcourse@foo.invalid> - 2016-09-12 21:22 -0700
                            Re: XC8 novice question David Brown <david.brown@hesbynett.no> - 2016-09-13 12:25 +0200
                              Re: XC8 novice question Dennis <dennis@none.none> - 2016-09-13 10:22 -0500
                                Re: XC8 novice question David Brown <david.brown@hesbynett.no> - 2016-09-13 20:08 +0200
              Re: XC8 novice question rwood <rwoodl@nowhere.com> - 2016-09-12 16:50 +0800
            Re: XC8 novice question Tom Gardner <spamjunk@blueyonder.co.uk> - 2016-09-11 17:13 +0100
              Re: XC8 novice question Tom Gardner <spamjunk@blueyonder.co.uk> - 2016-09-11 17:19 +0100
                Re: XC8 novice question David Brown <david.brown@hesbynett.no> - 2016-09-12 09:00 +0200
        Re: XC8 novice question Don Y <blockedofcourse@foo.invalid> - 2016-09-11 07:28 -0700
      Re: XC8 novice question upsidedown@downunder.com - 2016-09-11 13:56 +0300
        Re: XC8 novice question David Brown <david.brown@hesbynett.no> - 2016-09-11 13:28 +0200
        Re: XC8 novice question Hans-Bernhard Bröker <HBBroeker@t-online.de> - 2016-09-11 13:36 +0200
          Re: XC8 novice question upsidedown@downunder.com - 2016-09-11 16:14 +0300
            Re: XC8 novice question Don Y <blockedofcourse@foo.invalid> - 2016-09-11 07:57 -0700
            Re: XC8 novice question Hans-Bernhard Bröker <HBBroeker@t-online.de> - 2016-09-12 22:52 +0200
              Re: XC8 novice question upsidedown@downunder.com - 2016-09-13 10:11 +0300
                Re: XC8 novice question Don Y <blockedofcourse@foo.invalid> - 2016-09-13 01:11 -0700
                  Re: XC8 novice question upsidedown@downunder.com - 2016-09-13 13:24 +0300
                    Re: XC8 novice question David Brown <david.brown@hesbynett.no> - 2016-09-13 12:39 +0200
                    Re: XC8 novice question Don Y <blockedofcourse@foo.invalid> - 2016-09-13 15:41 -0700
                      Re: XC8 novice question upsidedown@downunder.com - 2016-09-14 09:07 +0300
                        Re: XC8 novice question Don Y <blockedofcourse@foo.invalid> - 2016-09-13 23:29 -0700
        Re: XC8 novice question Don Y <blockedofcourse@foo.invalid> - 2016-09-11 07:50 -0700
    Re: XC8 novice question Hans-Bernhard Bröker <HBBroeker@t-online.de> - 2016-09-11 13:42 +0200
    Re: XC8 novice question Tim Wescott <tim@seemywebsite.com> - 2016-09-11 20:14 -0500
    Re: XC8 novice question rwood <rwoodl@nowhere.com> - 2016-09-12 16:54 +0800
      Re: XC8 novice question David Brown <david.brown@hesbynett.no> - 2016-09-12 11:05 +0200
        Re: XC8 novice question rwood <rwoodl@nowhere.com> - 2016-09-12 18:48 +0800
    Re: XC8 novice question John Temples <usenet@xargs-spam.com> - 2016-09-12 17:33 +0000

Page 2 of 3 — ← Prev page 1 [2] 3  Next page →


#25027

FromDennis <dennis@none.none>
Date2016-09-12 17:04 -0500
Message-ID<nr78oe$29s$1@dont-email.me>
In reply to#25026
On 09/12/2016 04:11 PM, David Brown wrote:
> On 12/09/16 17:19, Don Y wrote:
>> On 9/12/2016 5:35 AM, David Brown wrote:
>>> On 12/09/16 11:41, Don Y wrote:
>>>> On 9/11/2016 11:55 PM, David Brown wrote:
>>>>> On 11/09/16 22:15, Don Y wrote:
>
> <snip for brevity>
>
>>
>>>> I would NOT, for example, write:
>>>>      x=-1;
>>>
>>> Neither would I - I would write "x = -1;".  But I believe I am missing
>>> your point with this example.
>>
>> My example would be parsed as:
>>     x =- 1 ;
>
> Parsed by who or what?  A compiler would parse it as "x = -1;".  I
> assume we are still talking about C (or C++) ?

What he is getting at is that in the original K&R C the compound 
assignment operator was of the form =op. It was later changed to the 
current op= because of the ambiguity he noted. See the K&R section of

https://en.wikipedia.org/wiki/K%26R_C

I remember having to change a bunch of code for the "new" compilers.

>
> When writing, I would include appropriate spaces so that it is easy to
> see what it means.
>
>> Nowadays, you would see this as:
>>     x -= 1 ;
>
> That is a completely different statement.
>
>
>> Would you have noticed that it was NOT assigning "-1" to x?
>> Would you have wasted that precious, limited timeslot that you
>> had access to "The Machine" chasing down a bug that you could have
>> avoided just by adopting a style that, instead, writes this as:
>>     x = -1;
>
> I am afraid I still don't get your point.  "x = -1;" is exactly how I
> would write it.  I believe spacing like that is good style, and helps
> make it clear to the reader and the writer how the statement is parsed.
>  And like in normal text, appropriate spacing makes things easier to read.
>

[toc] | [prev] | [next] | [standalone]


#25030

FromDon Y <blockedofcourse@foo.invalid>
Date2016-09-12 22:49 -0700
Message-ID<nr8418$nm1$1@dont-email.me>
In reply to#25027
On 9/12/2016 3:04 PM, Dennis wrote:
> On 09/12/2016 04:11 PM, David Brown wrote:
>> On 12/09/16 17:19, Don Y wrote:
>>> On 9/12/2016 5:35 AM, David Brown wrote:
>>>> On 12/09/16 11:41, Don Y wrote:
>>>>> On 9/11/2016 11:55 PM, David Brown wrote:
>>>>>> On 11/09/16 22:15, Don Y wrote:
>>
>> <snip for brevity>
>>
>>>
>>>>> I would NOT, for example, write:
>>>>>      x=-1;
>>>>
>>>> Neither would I - I would write "x = -1;".  But I believe I am missing
>>>> your point with this example.
>>>
>>> My example would be parsed as:
>>>     x =- 1 ;
>>
>> Parsed by who or what?  A compiler would parse it as "x = -1;".  I
>> assume we are still talking about C (or C++) ?
>
> What he is getting at is that in the original K&R C the compound assignment
> operator was of the form =op. It was later changed to the current op= because
> of the ambiguity he noted. See the K&R section of
>
> https://en.wikipedia.org/wiki/K%26R_C
>
> I remember having to change a bunch of code for the "new" compilers.

The issue is that the statement (as I wrote it) is "valid" C -- for BOTH
of those DIFFERENT compilers.  No errors encountering it on an early
compiler *or* a 21st century compiler.

Yet it has very different semantics!

A ~1985 compiler *might* warn you that "you MAY be expecting an OBSOLESCENT
behaviour".  it could flag it as an error (if it was a forward-leaning
implementation).  Or, if it is behind the times, might gladly accept the
legacy parse of this statement.

A 2015 compiler may have forgotten all about this alternative interpretation
and merrily generate code that is different from what was ORIGINALLY intended
without even thinking about alerting you to the historical issue (the compiler
doesn't know the code's ancestry!)

You, the developer/maintainer, have no way of knowing how those who preceded
you behaved -- their "styles" -- which is the only way to guesstimate
how the tools might NOW *mis*behave with their code!

[toc] | [prev] | [next] | [standalone]


#25031

FromDavid Brown <david.brown@hesbynett.no>
Date2016-09-13 09:04 +0200
Message-ID<nr88d0$2m7$1@dont-email.me>
In reply to#25027
On 13/09/16 00:04, Dennis wrote:
> On 09/12/2016 04:11 PM, David Brown wrote:
>> On 12/09/16 17:19, Don Y wrote:
>>> On 9/12/2016 5:35 AM, David Brown wrote:
>>>> On 12/09/16 11:41, Don Y wrote:
>>>>> On 9/11/2016 11:55 PM, David Brown wrote:
>>>>>> On 11/09/16 22:15, Don Y wrote:
>>
>> <snip for brevity>
>>
>>>
>>>>> I would NOT, for example, write:
>>>>>      x=-1;
>>>>
>>>> Neither would I - I would write "x = -1;".  But I believe I am missing
>>>> your point with this example.
>>>
>>> My example would be parsed as:
>>>     x =- 1 ;
>>
>> Parsed by who or what?  A compiler would parse it as "x = -1;".  I
>> assume we are still talking about C (or C++) ?
> 
> What he is getting at is that in the original K&R C the compound
> assignment operator was of the form =op. It was later changed to the
> current op= because of the ambiguity he noted. See the K&R section of
> 
> https://en.wikipedia.org/wiki/K%26R_C
> 
> I remember having to change a bunch of code for the "new" compilers.

OK, thanks.

I came across K&R briefly C at university, but ANSI C was already the
norm by the time I was actually doing anything with it.  And I have no
knowledge of C from before the first version of "The C Programming
Language", and have not seen the syntax "x =- 1;" before.

History like this is interesting, but irrelevant to the issue of how to
write code /today/.

[toc] | [prev] | [next] | [standalone]


#25028

FromHans-Bernhard Bröker <HBBroeker@t-online.de>
Date2016-09-13 00:16 +0200
Message-ID<e3onquFg1fU1@mid.dfncis.de>
In reply to#25026
Am 12.09.2016 um 23:11 schrieb David Brown:
> On 12/09/16 17:19, Don Y wrote:
>> On 9/12/2016 5:35 AM, David Brown wrote:

>> Nowadays, you would see this as:
>>     x -= 1 ;
>
> That is a completely different statement.

In Standard C it is.  _Very_ early in the development of the language 
the syntax had a loophole that caused some compilers to parse "x =- 1;" 
as if one had written "x -= 1;"

That's water 30+ years under the bridge, though.  Even Lint has given up 
warning about this particular idiom long ago.

[toc] | [prev] | [next] | [standalone]


#25029

FromDon Y <blockedofcourse@foo.invalid>
Date2016-09-12 21:22 -0700
Message-ID<nr7uue$cr9$1@dont-email.me>
In reply to#25026
On 9/12/2016 2:11 PM, David Brown wrote:

>>>> I would NOT, for example, write:
>>>>      x=-1;
>>>
>>> Neither would I - I would write "x = -1;".  But I believe I am missing
>>> your point with this example.
>>
>> My example would be parsed as:
>>     x =- 1 ;
>
> Parsed by who or what?  A compiler would parse it as "x = -1;".  I assume we
> are still talking about C (or C++) ?

No.  Dig out a copy of Whitesmith's or pcc.  What is NOW expressed as
"x -= 1" was originally expressed as "x =- 1".  Ditto for =+, =%, etc.
So, if you were a lazy typist and liked omitting whitespace by thinking it
redundant, you typed:
     x=-1;
and got:
     x=x-1;
instead of:
     x = (-1);

> When writing, I would include appropriate spaces so that it is easy to see what
> it means.

My point is that most folks would think x=-1 (or x=+2, etc.) bound the
sign to the value more tightly than to the assignment operator.

The same sort of reasoning applies to
    x=y/*p;
where the '*' ends up binding more tightly to the '/' to produce the
comment introducer, "/*".  Note that the problem persists in the
language's current form -- but compilers often warn about it
(e.g., detecting "nested" comments, etc.)

>> Nowadays, you would see this as:
>>     x -= 1 ;
>
> That is a completely different statement.

No.  It is what the statement above HAS BECOME!  (as the language evolved)

>> Would you have noticed that it was NOT assigning "-1" to x?
>> Would you have wasted that precious, limited timeslot that you
>> had access to "The Machine" chasing down a bug that you could have
>> avoided just by adopting a style that, instead, writes this as:
>>     x = -1;
>
> I am afraid I still don't get your point.  "x = -1;" is exactly how I would
> write it.  I believe spacing like that is good style, and helps make it clear
> to the reader and the writer how the statement is parsed.  And like in normal
> text, appropriate spacing makes things easier to read.

See above.

Or, better yet, google turns up:
 
<http://bitsavers.informatik.uni-stuttgart.de/pdf/chromatics/CGC_7900_C_Programmers_Manual_Mar82.pdf>

Perhaps an interesting read for folks didn't have to write code
"back then".

>>>> And, I *would* write:
>>>>      p = &buffer[0];
>>>
>>> So would I - because I think the code looks clearer.  When I want p to
>>> be a pointer to the first element of "buffer", that's what I write.
>>
>> You'll more frequently encounter:
>>       p = buffer;
>
> I know.  But I prefer "p = &buffer[0];", because I think it looks clearer and
> makes more sense.  To my reading, "buffer" is an array - it does not make sense
> to assign an array to a pointer-to-int.  (I'm guessing at types here, since
> they were never declared - adjust them if necessary if "buffer" was an array of
> char or something else.)

I prefer it because I am more hardware oriented.  I think of "objects"
(poor choice of words) residing AT memory addresses.  So, it is only
natural for me to think about "the address of the zeroth element of
the array".

> C converts arrays or array operations into pointers and pointer operations in
> certain circumstances.  I wish it did not - but I can't change the language.
> But just because the language allows you to write code in a particular way, and
> just because many people /do/ write code in a particular way, does not
> necessarily mean it is a good idea to do so.
>
>>> I'd use parens in places that you'd consider superfluous -- but that
>>>> made bindings very obvious (cuz the compiler would do what I *told* it
>>>> without suggesting that I might be doing something unintended):
>>>
>>> Me too.  But that's for clarity of code for both the reader and the
>>> writer - not because I worry that my tools don't follow the rules of C.
>>
>> The problem isn't that tools don't follow the rules.  The problem is that
>> a compiler can be conforming WITHOUT holding your hand and reminding you
>> that what you've typed *is* "valid C" -- just not likely the valid C
>> that you assumed!
>
> Again, I can only say - get a decent compiler, and learn how to use it
> properly.  If you cannot use good compiler (because no good compilers exist for
> your target, at least not in your budget), then use an additional static error
> checker.

For how many different processors have you coded?  I have compilers
for processors that never made it into "mass production".  And, for
processors that saw very limited/targeted support.  If I'm willing to FUND
the development of a compiler -- knowing that I may be the only
customer for that compiler -- then I can "buy" all sorts of capabilities
in that compiler!

OTOH, if I have to pass those costs along to a client, he may be far less
excited about how "good the tool is" and, instead, wonder why *I* can't
compensate for the tool's quality.

What were tools like 20 years ago?  Could you approach your client/employer
and make the case for investing in the development of a compiler with
2016 capabilities?  Running, *effectively*, on 1995 hardware and OS?
Or, would you, instead, argue that the project should be deferred until
the tools were more capable?

Or, would you develop work styles that allowed you to produce reliable
products with the tools at your disposal??

> To be used in a safe, reliable, maintainable, and understandable way, you need
> to limit the C features you use and the style you use.  (This applies to any
> programming language, but perhaps more to C than other languages.)  And you use
> whatever tools you can to help spot errors as early as possible.
>
>>>>      y = x / (*p);
>>>
>>> Me too.
>>
>> Because the compiler would gladly think "y=x/*p;" was THREE characters
>> before the start of a comment -- without telling you that it was
>> interpreting it as such.  Again, you turn the crank and then spend
>> precious time staring at your code, wondering why its throwing an error
>> when none should exist (in YOUR mind).  Or, worse, mangling input:
>>
>>          y=/*p      /* this is the intended comment */
>>            x=3;
>>
>
> Again, spaces are your friend.

Spaces (or parens) are a stylistic choice.  The language doesn't mandate
their use.  E.g., this is perfectly valid:
      y=/*I want to initialize two variables to the same value
          in a single stmt*/x=3;

It's a bad coding STYLE but nothing that the compiler SHOULD complain
about!

>> seen, instead, as (error-free!):
>>
>>          y=x=3;
>
> Again, that's why you have to limit the features of C that you use.  And get
> whatever help you can from your tools to spot the errors (even if they are
> technically valid C).
>
>>>> And, to catch (some) '=' instead of "==" errors, write tests as:
>>>>      if ( CONSTANT == expression ) ...
>>>
>>> No, I would /never/ write that.  I would write it in a way that makes
>>> logical sense when reading or writing.  You would say "if the number of
>>> apples is 3, the price is $1" - you would never say "if 3 is the number
>>> of the apples, $1 is the price".
>>
>> If the bag yields 3 apples...
>
> Bags don't "yield" apples.

Sure they do!  Do you think they HORDE apples?

>>> Thus I would always write:
>>>
>>>     if (expression == constant) { .... }
>>>
>>> (I'm not a fan of shouting either - I left all-caps behind with BASIC
>>> long ago.)
>>
>> I ALWAYS use caps for manifest constants.
>
> Many people do.  I don't.  I really do not think it helps in any way, and it
> gives unnecessary emphasis to a rather minor issue, detracting from the
> readability of the code.

Would you write:
const zero = 0;
const nine = 9;
     for (index = zero; index < nine; index++)...
Or:
const start = zero;
const end = nine;
     for (index = start; index < end; index++)...
Or:
     for (index = START; index < END; index++)...

The latter makes it abundantly clear to me (without having to chase down
the declaration/definition of "start", "end", "zero" or "nine".  (who
is to say whether "zero" actually maps to '0' vs. "273" -- 0 degrees K!)

> But I am aware that some people think it is a useful idiom - and that a good
> many people think it is just something you do, because lots of other people do
> it.  I'm assuming you are in the first category here, and could give good
> reasons why you like all caps here, but I don't think we need to introduce any
> more points of disagreement and discussion at the moment!
>
>>> What benefit do you think "if (CONSTANT == expression)" gives you?  Why
>>> is it useful to invert the logic and make code hard to read, just in
>>> case you make a mistake and write "if (expression = CONSTANT)"?  It is
>>> highly unlikely that you would make such a mistake, and even less likely
>>> that you would make it and not find it quickly - and you compiler (or
>>> linter) will spot it for you.
>>
>> Again, you're spoiled by adopting C when it was far more mature
>> and had more mature tools as well as accessibility.  Give yourself
>> an hour, today, to use your PC/computer.  See how much work you get
>> done (lets forget that your computer is 1000 times more capable).
>> But, don't fret; whatever you DON'T get done you can tackle
>> tomorrow -- in THAT 1 hour timeslot!
>
> And again, you are missing the point.  I am not writing code for a 40 year old
> compiler.  Nor is the OP.  For the most part, I don't need to write unpleasant
> code to deal with outdated tools.

No, YOU are missing the point!  I'm writing code with 40 years of
"respectible track record".  You're arguing that I should "fix"
something (i.e., my style preferences) that isn't broken.  Because
it differs from what your *20* year track record has found to be
acceptable.  Should we both wait and see what next year's
crop of developers comes up with?  Maybe Hungarian notation will be
supplanted by Vietnamese notation?  Or, we'll decide that using identifiers
expressed in Esperanto is far more universally readable?

> I have, in the past, used far more limited compilers.  I have worked with
> compilers that only supported C90/ANSI, meaning I can't mix declarations and
> statements.  I have worked with compilers that have such god-awful code
> generation that I had to think about every little statement, and limit the
> number of local variables I used.  Very occasionally, I have to work on old
> projects that were made using such tools - and I have to go back to the dark
> ages for a while.
>
> Perhaps, long ago when the tools I had were poor and the company I worked for
> did not have the budget for a linter, it might have made sense to write "if
> (CONSTANT == expression)".  But not now - and I don't think there will be many
> developers working today for which it would still make sense.

I can then argue that we shouldn't bother with such an archaic language,
at all!  Look at all the cruft it brings along with it!  Why not wait to
see what pops up tomorrow as the language (and development style) du jour?
Or, why risk being early adopters -- let's wait a few *weeks* before
adopting tomorrow's advances!

Programming is still an art, not a science.  You rely on techniques that
have given you success in the past.  When 25% of product returns are due
to "I couldn't figure out how to USE this PoS!", that suggests current
development styles are probably "lacking".
<https://books.google.com/books?id=pAsCYZCMvOAC&pg=PA130&lpg=PA130&dq=product+returns+confusion&source=bl&ots=P_v4nTI0m8&sig=XZ6VGEOtuyJOG7Kwkcd2SMV2_6w&hl=en&sa=X&ved=0ahUKEwiDwtDKt4vPAhVk0YMKHfO-C-AQ6AEINjAD>

>>>> [would you consider "if (foo==bar())" as preferred to "if
>>>> (bar()==foo)"?]
>>>
>>> I'd usually try to avoid a function call inside an expression inside a
>>> conditional, but if I did then the guiding principle is to make it clear
>>> to read and understand.
>>
>> Which do you claim is cleared?
>> Imagine foo is "errno".
>> After answering, rethink it knowing that errno is actually a function
>> invocation on this platform.
>
> Neither is clear enough.

So, what's your solution?

>>>> Much of this is a consequence of how I learned to "read" (subvocalize)
>>>> code to myself:
>>>>      x = y;
>>>> is "x gets the value of y", not "x equals y".  (how would you read x ::=
>>>> y ?)
>>>>      if ( CONSTANT == expression )
>>>> is "if expression yields CONSTANT".  Catching myself saying "if CONSTANT
>>>> gets
>>>> expression" -- or "if variable gets expression":
>>>>      if ( CONSTANT = expression )
>>>>      if ( variable = expression )
>>>> is a red flag that I'm PROBABLY not doing what I want to do.
>>>>
>>>> I'll wager that most folks read:
>>>>      x = y;
>>>> as:
>>>>      x equals y
>>>
>>> I can't say I vocalize code directly - how does one read things like
>>> brackets or operators like -> ?  But "x = y" means "set x equal to y".
>>
>> And, x ::= y effectively says the same -- do you pronounce the colons?
>> Instead, use a verb that indicates the action being performed:
>>       x gets y
>
> I don't pronounce colons.  I also don't use a programming language with a ::=
> operator.  But if I did want to pronounce it, then "x gets y" would be fine.

Then you come up with alternative ways of conveying the information
present in that symbology.

E.g., "::=" (used to initialize a variable) vs '=' (used to define
*constants*, but not variables, and test for value equality) vs ":=:"
(to test for address equality) vs ":=" (chained assignment) in Algol;
'=' vs "==" in C; ":=" vs. '=' and ':' and "==" in Limbo; etc.

When conversing with someone not fluent in a language, the actual
punctuation plays an important role.  Saying "x gets y" to someone
who isn't familiar with Algol's "::=" would PROBABLY find them
writing "x = y".  When "reading" Limbo code to someone, I resort
to "colon-equals", "equals" and "colon" so I'm sure they know
exactly what I'm saying (because the differences are consequential)

>> I learned to code with left-facing arrows instead of equal signs
>> to make the "assignment" more explicit.
>
> I think that <- or := is a better choice of symbol for assignment.  The
> designers of C made a poor choice with "=".
>
>>>> and subtly change their intent, but NOT their words, when encountering:
>>>>      if ( x == y )
>>>> as:
>>>>      if x equals y
>>>
>>> "if x equals y", or "if x is equal to y".
>>>
>>>> (how would they read "if ( x = y )"?)
>>>
>>> I read it as "warning: suggest parentheses around assignment used as
>>> truth value" :-)
>>
>> No, your *compiler* tells you that.  If you've NEVER glossed over
>> such an assignment in your code, you've ALWAYS had a compiler holding
>> your hand for you.  I'm glad I didn't have to wait 10 years for such
>> a luxury before *I* started using C.
>
> I have used warnings on such errors for as long as I have used compilers that
> conveniently warned about them.  But I can say it is very rare that a compiler
> /has/ warned about it - it is not a mistake I have made more than a couple of
> times.  Still, I want my tools to warn me if it were to happen.

I want my tools to warn me of everything that they are capable of detecting.
INCLUDING the tool that occupies my cranial cavity!

>> I'll frequently store pointers to functions where you might store
>> a variable that you conditionally examine (and then dispatch to
>> one of N places in your code).  In my case, I just invoke the
>> function THROUGH the pointer -- the tests were done when I *chose*
>> which pointer to stuff into that variable (why should I bother to
>> repeat them each time this code fragment is executed?)
>>
>> When you do code reviews, do you all sit around with laptops and
>> live code copies?  Or, do you pour over LISTINGS with red pens?
>> Do you expect people to just give the code a cursory once-over?
>> Or, do you expect them to *read* the code and act as "human
>> compilers/processors"?
>
> I expect code to be as simple to understand as possible, so that it takes as
> little time or effort as possible for other people to read. That way others can
> spend their effort on confirming that what the code does is the right thing,
> rather than on figuring out what the code does first.

What's simple to me might not be simple to you!  E.g., I naturally
think in terms of pointers.  Others prefer array indexes.  For me
to jump/call *through* a pointer is far more obvious than encoding some
meaning into a flag at some point in the program.  Then, decoding that
flag at another point and dispatching based on that decode!  The latter
requires keeping two pieces of code in sync (encode & decode).  The
former puts everything in one place (encoding).

Should I write code at a level that a newbie developer can understand?
Should I limit myself to how expressive and productive I can be out of fear
that someone might not be quick to grasp what I've written?

>> There is no such thing as a perfect style.  You adopt a style that
>> works for you and measure its success by how buggy the code is (or
>> is not) that you produce and the time that it takes you to produce it.
>
> Yes.
>
>>
>> I suspect if I sat you down with some of these early and one-of-a-kind
>> compilers, you'd spend a helluva lot more time chasing down bugs that
>> the compiler didn't hint at.  And, probably run the risk of some creeping
>> into your release (x=y=3) that you'd never caught.
>
> No.
>
> Static checking by the compiler is not a substitute for writing correct code.

Where am I writing "INcorrect code"?  It meets the specifications of the
language.  It compiles without errors or warnings.  It fulfills the goals
of the specification.

It's just that *you* don't like my style!  Is that what makes it "not correct"?
If I replaced the identifiers for manifest constants with lowercase symbols,
would that make it MORE correct?  Should I use camelcase identifiers?
Hungarian notation?  Embedded underscores?   How do any of these make the
code more or less "correct"?

> You make it sound like I program by throwing a bunch of random symbols at the
> compiler, then fixing each point it complains about.  The checking is automated
> confirmation that I am following the rules I use when coding, plus convenient
> checking of silly typos that anyone makes on occasion.
>
>> Instead of pushing an update to the customer over the internet, you'd
>> send someone out to their site to install a new set of EPROMs.  Or,
>> have them mail the product back to you as their replacement arrived
>> (via USPS).  Kind of annoying for the customer when he's got your
>> device on his commercial fishing boat.  Or, has to lose a day's production
>> while it's removed from service, updated and then recertified.
>
> I have mailed EPROMs to customers, or had products delivered back for program
> updates.  But never due to small mistakes of the sort we are discussing here.

I've *never* had to update a product after delivery.  Because the cost of
doing so would easily exceed the profit margin in the product!

I've had clients request modifications to a product; or tweeks for
specific customers.  But, those aren't "bug fixes", they're effectively
"new products" that leverage existing hardware.

I did some work for a firm in Chicago.  Big company with lots of bean
counters.  So, they could tell you what everything "costs" (them!).
I had proposed "swapping ROMs" as an upgrade path for the product.
They told me that it costs them $600 to send someone into the city
to TOUCH an installed device:
- gotta schedule the visit (can't just walk in unannounced and hope
   your customer will be eager to greet you AND have the equipment
   "out of service" at that time)
- gotta drive into the city, find a place to park the car, lug your
   test equipment (have to prove to the customer that what you're doing
   DOES work) and documentation/paperwork/workorder to the customer's
   facility
- gotta spend some time actually making the upgrade, testing it and
   reassuring the customer that it actually works
- gotta schlep all your stuff back to the car, pay the parking fee
- drive back to work and check the vehicle back in
- fill out the trip report and any expense report
- gotta pay the employee for this time (plus his share of "burden")
- gotta make sure you have enough employees with this sort of
   training on hand at all times (cuz you can't simply decide not
   to handle upgrades because Bob quit!)

$600.  And that was more than 30 years ago!  For a product that *cost*
$300 (DM+DL) to build!

"No, there will be no upgrades.  You will get it right the first time!"

>>> Consistency is a good thing - there's no doubt there.  But it is not the
>>> overriding concern in all cases - breaking with old habits is necessary
>>> in order to improve.
>>
>> People are intimidated by pointers.  I should "break that habit" because
>> of their shortcomings?  Or because some standards committee decrees?
>> Despite the fact that I produce higher quality code for less money than
>> the adherents of those standards?
>
> Break the habit if it was based on how you had to work with old tools, and the
> habit is not helpful with modern development.

Who is to say it is not helpful?  Has the quality of my work suffered?
Am I suddenly writing buggier code?

If it isn't broke, don't fix it!

>>> And remember, in this thread and context, we are giving advice to a new
>>> programmer.  It is one thing to say that /you/ want to write "if (4 ==
>>> count)" to remain consistent with the vast quantities of code you have
>>> written over the last 40 years.  It is entirely different to consider
>>> how this /new/ programmer should write the vast quantities of code he
>>> will produce over the /next/ 40 years.  /You/ have to live with the
>>> decisions from your past - the new programmer does not.
>>
>> The new programmer has to be aware of why things are the way they
>> are.  Or, fail to learn history's lessons.  What does he/she do
>> when faced with one of these tools?  Or, a build environment that
>> has turned off all warnings (does he even know that has happened)?
>
> Again, you see to assume that I am recommending programming by luck - randomly
> writing "if (x = 1)" or "if (x == 1)" and relying on the tools to fix the
> mistakes.

No.  I'm acknowledging that people make mistakes, keyboards don't always
"type" what you've told them to type, etc.  I am *very* consistent in
my design styles (hardware and software).  If I look at something that I
created and it doesn't strictly conform to "how I do things", I am
instantly on alert:  "Why is this not as it SHOULD be?"  And, I start
searching for an explanation in the accompanying commentary -- lest I
be tempted to "fix" it (which will introduce a problem and explains
why it WASN'T "as it should be" to begin with!)

> The new programmer should learn to take advantage of new tools, and concentrate
> efforts on problems that are relevant rather than problems are no longer an
> issue (to the extent that they ever /were/ an issue). And if that new
> programmer is faced with poorer tools, then he or she will have to learn the
> idiosyncrasies at the time.  And the lack of warnings on "if (x = 1)" is
> unlikely to be the most important point.

Without the warning, the developer is likely to waste a boatload of
time "seeing what he wants to see" and not what the *compiler* sees.

>> There's a reason you can look at preprocessor output and ASM
>> sources.  Because they are the only way to understand some nasty
>> bugs that may arise from your misunderstanding of what a tool
>> SHOULD be doing; *or*, from a defective tool!  (a broken tool
>> doesn't have to tell you that it's broken!)
>
> I have almost /never/ had occasion to look at pre-processor output.  But I do
> recommend that embedded programmers should be familiar enough with the assembly
> for their targets that they can look at and understand the assembly listing.

You've probably never "abused" the preprocessor in creative ways!  :>

[toc] | [prev] | [next] | [standalone]


#25035

FromDavid Brown <david.brown@hesbynett.no>
Date2016-09-13 12:25 +0200
Message-ID<nr8k74$63g$1@dont-email.me>
In reply to#25029
On 13/09/16 06:22, Don Y wrote:
> On 9/12/2016 2:11 PM, David Brown wrote:
> 
>>>>> I would NOT, for example, write:
>>>>>      x=-1;
>>>>
>>>> Neither would I - I would write "x = -1;".  But I believe I am missing
>>>> your point with this example.
>>>
>>> My example would be parsed as:
>>>     x =- 1 ;
>>
>> Parsed by who or what?  A compiler would parse it as "x = -1;".  I
>> assume we
>> are still talking about C (or C++) ?
> 
> No.  Dig out a copy of Whitesmith's or pcc.  What is NOW expressed as
> "x -= 1" was originally expressed as "x =- 1".  Ditto for =+, =%, etc.
> So, if you were a lazy typist and liked omitting whitespace by thinking it
> redundant, you typed:
>     x=-1;
> and got:
>     x=x-1;
> instead of:
>     x = (-1);
> 
>> When writing, I would include appropriate spaces so that it is easy to
>> see what
>> it means.
> 
> My point is that most folks would think x=-1 (or x=+2, etc.) bound the
> sign to the value more tightly than to the assignment operator.

Of course they think "x=-1" means "x = -1" !  It has been almost forty
years since "x =- 1" has been standard C.  Most people also think that
television is in colour, you can communicate to Australia by telephone,
and flares are no longer in fashion.  Live moves on.

In this particular case, the number of people who ever learned to write
"x =- 1", and are still working as programmers (or even still alive) is
tiny.  And the number of those who failed to learn to use "x -= 1" at
least 35 years ago, must be tinier still.  Sure, you can /remember/ it -
and remember having to change old code to suit new compilers.  An old
shopkeeper may remember when he made deliveries with a horse and cart -
but he does not insist that new employees know about grooming horses.

Backwards compatibility, and compatibility with existing code, is
important.  That is why we still have many of the poor choices in the
design of C as a language - for compatibility.  But with each passing
year or decade, compatibility with the oldest code gets less and less
relevant - except to historians or the occasional very specialist cases.

Of all the lines of C code that are in use today, what fraction were
written in pre-K&R C when "x =- 1" was valid?  One in a million?  One in
a hundred million?  If we exclude code lines that have been converted to
later C standards, then I doubt if it is nearly that many.

> 
> The same sort of reasoning applies to
>    x=y/*p;
> where the '*' ends up binding more tightly to the '/' to produce the
> comment introducer, "/*".  Note that the problem persists in the
> language's current form -- but compilers often warn about it
> (e.g., detecting "nested" comments, etc.)

That is different in that the parsing rules for C are quite clear here,
and are the same as the always have been - /* starts a comment.  But
unless you have carefully created a pathological case and use a
particularly unhelpful compiler (and editor - in this century, most
programmers use editors with syntax highlighting), you are going to spot
the error very quickly.

C provides enormous opportunity for accidentally writing incorrect code
- in many cases, the result is perfectly acceptable C code and will not
trigger any warnings.  If you were to take the top hundred categories of
typos and small mistakes in C code that resulted in compilable but
incorrect code, "x=y/*p" would not feature.  It /might/ make it onto a
list of the top thousand mistakes.  It really is that irrelevant.

And it is preventable by using spaces.  There is a reason that the space
bar is the biggest key on the keyboard.

> 
>>> Nowadays, you would see this as:
>>>     x -= 1 ;
>>
>> That is a completely different statement.
> 
> No.  It is what the statement above HAS BECOME!  (as the language evolved)
> 

Take your head out of your history books.  In C, "x-=1" means "x -= 1",
while "x=-1" means "x = -1".  That is it.  It is a simple fact.  It
matters little what C used to be, decades before most programmers were born.

>>> Would you have noticed that it was NOT assigning "-1" to x?
>>> Would you have wasted that precious, limited timeslot that you
>>> had access to "The Machine" chasing down a bug that you could have
>>> avoided just by adopting a style that, instead, writes this as:
>>>     x = -1;
>>
>> I am afraid I still don't get your point.  "x = -1;" is exactly how I
>> would
>> write it.  I believe spacing like that is good style, and helps make
>> it clear
>> to the reader and the writer how the statement is parsed.  And like in
>> normal
>> text, appropriate spacing makes things easier to read.
> 
> See above.
> 
> Or, better yet, google turns up:
> 
> <http://bitsavers.informatik.uni-stuttgart.de/pdf/chromatics/CGC_7900_C_Programmers_Manual_Mar82.pdf>
> 
> 
> Perhaps an interesting read for folks didn't have to write code
> "back then".

I am not as old as you, but I have been programming for about 35 years.
 I have had my share of hand-assembling code, burning eeproms, using
punched tape, and even setting opcodes with DIP switches with a toggle
switch for the clock.

But I understand the difference between what I do /now/, and what other
programmers do /now/, and what I did long ago.

> 
>>>>> And, I *would* write:
>>>>>      p = &buffer[0];
>>>>
>>>> So would I - because I think the code looks clearer.  When I want p to
>>>> be a pointer to the first element of "buffer", that's what I write.
>>>
>>> You'll more frequently encounter:
>>>       p = buffer;
>>
>> I know.  But I prefer "p = &buffer[0];", because I think it looks
>> clearer and
>> makes more sense.  To my reading, "buffer" is an array - it does not
>> make sense
>> to assign an array to a pointer-to-int.  (I'm guessing at types here,
>> since
>> they were never declared - adjust them if necessary if "buffer" was an
>> array of
>> char or something else.)
> 
> I prefer it because I am more hardware oriented.  I think of "objects"
> (poor choice of words) residing AT memory addresses.  So, it is only
> natural for me to think about "the address of the zeroth element of
> the array".

I am a hardware man too.  And I quite appreciate that interpretation as
well.

> 
>> C converts arrays or array operations into pointers and pointer
>> operations in
>> certain circumstances.  I wish it did not - but I can't change the
>> language.
>> But just because the language allows you to write code in a particular
>> way, and
>> just because many people /do/ write code in a particular way, does not
>> necessarily mean it is a good idea to do so.
>>
>>>> I'd use parens in places that you'd consider superfluous -- but that
>>>>> made bindings very obvious (cuz the compiler would do what I *told* it
>>>>> without suggesting that I might be doing something unintended):
>>>>
>>>> Me too.  But that's for clarity of code for both the reader and the
>>>> writer - not because I worry that my tools don't follow the rules of C.
>>>
>>> The problem isn't that tools don't follow the rules.  The problem is
>>> that
>>> a compiler can be conforming WITHOUT holding your hand and reminding you
>>> that what you've typed *is* "valid C" -- just not likely the valid C
>>> that you assumed!
>>
>> Again, I can only say - get a decent compiler, and learn how to use it
>> properly.  If you cannot use good compiler (because no good compilers
>> exist for
>> your target, at least not in your budget), then use an additional
>> static error
>> checker.
> 
> For how many different processors have you coded?

I can't remember - perhaps 20 or so.

Z80, 6502, 68k, x86, MIPS, COP8, 8051, PIC16, HP43000, ARM, PPC, AVR,
AVR32, MSP430, NIOS, XMOS, TMS430, 56Fxxx

That's 18 - there are several more whose names I can't remember, and
some that I have programmed on without being familiar with the assembly
language.

>  I have compilers
> for processors that never made it into "mass production".  And, for
> processors that saw very limited/targeted support.  If I'm willing to FUND
> the development of a compiler -- knowing that I may be the only
> customer for that compiler -- then I can "buy" all sorts of capabilities
> in that compiler!
> 
> OTOH, if I have to pass those costs along to a client, he may be far less
> excited about how "good the tool is" and, instead, wonder why *I* can't
> compensate for the tool's quality.

Long ago, anyone wanting to make a C compiler for a new processor would
either buy the front end and write their own code generator, or would
pay a compiler company to write the code generator to go with their
existing front end.  Only hobby developers would write their own C front
end - for professionals, it was not worth the money unless they were a
full-time compiler development company.

So you got your front-end already made, with whatever features and
warnings it supported.  Clearly, the range of features would vary here.
 And sometimes you wanted to add your own extra features for better
support of the target.

Now, anyone wanting to make a C compiler for a new processor starts with
either gcc or clang, and writes the code generator - again, the
front-end is there already.


> 
> What were tools like 20 years ago?  Could you approach your client/employer
> and make the case for investing in the development of a compiler with
> 2016 capabilities?  Running, *effectively*, on 1995 hardware and OS?
> Or, would you, instead, argue that the project should be deferred until
> the tools were more capable?

The tools I used 20 years ago were not as good as the ones I use now.
And the tools I used 20 years ago were not as good as the best ones
available 20 years ago - the budget did not stretch.

But now, the budget /does/ stretch to high quality tools - for most
microcontrollers, /everybody's/ budget stretches far enough because high
quality compiler tools are free or very cheap.  There are a few
microcontrollers where that is not the case (the 8051, the unkillable
dinosaur, being an example), but tool quality and price is a factor many
people consider when choosing a microcontroller.

And how relevant are 20 year old tools to the work I do /today/, writing
code /today/ ?  Not very relevant at all, except for occasional
maintenance of old projects.

> 
> Or, would you develop work styles that allowed you to produce reliable
> products with the tools at your disposal??

The whole point is that 20 years ago I had to have a style that made
sense 20 years ago with the tools of that era.  Now I have a style that
is suited to the tools of /this/ era.  Not a lot has changed, because
the guiding principles have been the same, but many details have
changed.  Function-like macros have morphed into static inline
functions, home-made size-specific types have changed to uint16_t and
friends, etc.  Some of my modern style features, such as heavy use of
static assertions, could also have been used 20 years ago - I have
learned with time and experience.

But I refuse to write modern code of poorer quality and with fewer
features simply because those features were not available decades ago -
or even because those features are not available on all modern compilers.

> 
>> To be used in a safe, reliable, maintainable, and understandable way,
>> you need
>> to limit the C features you use and the style you use.  (This applies
>> to any
>> programming language, but perhaps more to C than other languages.) 
>> And you use
>> whatever tools you can to help spot errors as early as possible.
>>
>>>>>      y = x / (*p);
>>>>
>>>> Me too.
>>>
>>> Because the compiler would gladly think "y=x/*p;" was THREE characters
>>> before the start of a comment -- without telling you that it was
>>> interpreting it as such.  Again, you turn the crank and then spend
>>> precious time staring at your code, wondering why its throwing an error
>>> when none should exist (in YOUR mind).  Or, worse, mangling input:
>>>
>>>          y=/*p      /* this is the intended comment */
>>>            x=3;
>>>
>>
>> Again, spaces are your friend.
> 
> Spaces (or parens) are a stylistic choice.  The language doesn't mandate
> their use.  E.g., this is perfectly valid:
>      y=/*I want to initialize two variables to the same value
>          in a single stmt*/x=3;
> 
> It's a bad coding STYLE but nothing that the compiler SHOULD complain
> about!

Compilers can, do, and should complain about particularly bad style.
It's important that such complaints are optional - and for
compatibility, they are usually disabled by default.  There is no clear
division between what is simply a stylistic choice ("x=3" vs. "x = 3",
for example), and what is a really /bad/ idea, such as putting comments
in the middle of a statement.  Thus any complaints about style need to
be configurable.

But there is no doubt that such warnings can be helpful in preventing
bugs.  Warning on "if (x = 3)" is a fine example.  Another is gcc 6's
new "-Wmisleading-indentation" warning that will warn on:

if (x == 1)
	a = 2;
	b = 3;

Code like that is wrong - it is bad code, even if it is perfectly
legitimate C code, and even if it happens to work.  It is a good thing
for compilers to complain about it.

> 
>>>> Thus I would always write:
>>>>
>>>>     if (expression == constant) { .... }
>>>>
>>>> (I'm not a fan of shouting either - I left all-caps behind with BASIC
>>>> long ago.)
>>>
>>> I ALWAYS use caps for manifest constants.
>>
>> Many people do.  I don't.  I really do not think it helps in any way,
>> and it
>> gives unnecessary emphasis to a rather minor issue, detracting from the
>> readability of the code.
> 
> Would you write:
> const zero = 0;
> const nine = 9;
>     for (index = zero; index < nine; index++)...
> Or:
> const start = zero;
> const end = nine;
>     for (index = start; index < end; index++)...
> Or:
>     for (index = START; index < END; index++)...
> 

No, I would not write any of that.

I would not write "const zero = 0" for several reasons.  First, it is
illegal C - it needs a type.  Second, such constants are usually best
declared static.  Third, it is pointless making a constant whose name is
its value.

But I /might/ write:

static const int start = 0;
static const int end = 9;

for (int index = start; index < end; index++) { ... }


Even that is quite unlikely - "start" and "end" would usually have far
better names, while "index" is almost certainly better written as "i".
(But that is a matter of style :-) ).


> The latter makes it abundantly clear to me (without having to chase down
> the declaration/definition of "start", "end", "zero" or "nine".  (who
> is to say whether "zero" actually maps to '0' vs. "273" -- 0 degrees K!)

The only thing the START and END form makes abundantly clear is that you
really, really want everyone looking at the code to see at a glance that
START and END won't change - and that is far more important than
anything else about the code, such as what it does.

If "zero" does not map to zero, don't call it "zero".  Call it "zeroK",
or "lowestTemperature", or whatever.

>>
>> And again, you are missing the point.  I am not writing code for a 40
>> year old
>> compiler.  Nor is the OP.  For the most part, I don't need to write
>> unpleasant
>> code to deal with outdated tools.
> 
> No, YOU are missing the point!  

Certainly we seem to be talking at cross-purposes here.  It is a matter
of viewpoint who is "missing the point" - probably both of us.

> I'm writing code with 40 years of
> "respectible track record".  You're arguing that I should "fix"
> something (i.e., my style preferences) that isn't broken.  Because
> it differs from what your *20* year track record has found to be
> acceptable.  Should we both wait and see what next year's
> crop of developers comes up with?  Maybe Hungarian notation will be
> supplanted by Vietnamese notation?  Or, we'll decide that using identifiers
> expressed in Esperanto is far more universally readable?

Yes, I am arguing that if something in your style is no longer the best
choice for modern programming, then you certainly should consider
changing it.  Clearly you will not do so without good reason, which is
absolutely fine.

I am also arguing against recommending new people adopt a style whose
benefits are based on ancient tools and your own personal habits.
Modern programmers should adopt a forward-looking style that lets them
make the take advantage of modern tools - there is no benefit in
adopting your habits or my habits, simply because /we/ are used to them.
 There are benefits in using, or at least being familiar with, common
idioms and styles.  But that should not be an overriding concern.  Keep
good habits, if they are still good - but drop bad habits.

> 
>> I have, in the past, used far more limited compilers.  I have worked with
>> compilers that only supported C90/ANSI, meaning I can't mix
>> declarations and
>> statements.  I have worked with compilers that have such god-awful code
>> generation that I had to think about every little statement, and limit
>> the
>> number of local variables I used.  Very occasionally, I have to work
>> on old
>> projects that were made using such tools - and I have to go back to
>> the dark
>> ages for a while.
>>
>> Perhaps, long ago when the tools I had were poor and the company I
>> worked for
>> did not have the budget for a linter, it might have made sense to
>> write "if
>> (CONSTANT == expression)".  But not now - and I don't think there will
>> be many
>> developers working today for which it would still make sense.
> 
> I can then argue that we shouldn't bother with such an archaic language,
> at all!  Look at all the cruft it brings along with it!  Why not wait to
> see what pops up tomorrow as the language (and development style) du jour?
> Or, why risk being early adopters -- let's wait a few *weeks* before
> adopting tomorrow's advances!

There is a balance between choosing something that is mature, field
proven and familiar, and choosing something that is newer and has
benefits such as efficiency, clarity, flexibility, safety, etc.

I think that the large majority of work done in C would be better
written in a different language, were it not for two factors - existing
code written in C, and existing experience of the programmer in C.  For
most programming tasks, C /is/ archaic - it is limited, inflexible, and
error prone.  For some tasks, its limitations and its stability as a
language are an advantage.  But for many tasks, if one could disregard
existing C experience, it is a poor choice of language.

Thus a lot of software on bigger systems is written in higher level
languages, such as Python, Ruby, etc.  A lot of software in embedded
systems are written in C++ to keep maximal run-time efficiency while
getting more powerful development features.  New languages such as Go
are developed to get a better balance of the advantages of different
languages and features.

For a good deal of embedded development, the way forward is to avoid
archaic and brain-dead microcontrollers such as the 8051 or the PIC.
Stick to solid but modern processors such as ARM or MIPS cores.  And
move to C++ - /if/ you are good enough to learn and understand how to
use that language well in embedded systems.

I would wait a few years, not weeks, but not decades, before adopting
new languages for embedded programming.  Maybe Go will be a better
choice in a few years.


We've been through all this with "C vs. assembly" - and there are plenty
of people that still use assembly programming for embedded systems
because "it was good enough for my grandfather, it's good enough for
me", or because they simply refuse to move forward with the times.  Like
assembly, C will never go away - but it /will/ move further and further
into niche areas, and be used "for compatibility with existing code and
systems".

In the meantime, we can try and write our C code in the best way that
modern tools allow.

> 
> Programming is still an art, not a science.  You rely on techniques that
> have given you success in the past.  When 25% of product returns are due
> to "I couldn't figure out how to USE this PoS!", that suggests current
> development styles are probably "lacking".
> <https://books.google.com/books?id=pAsCYZCMvOAC&pg=PA130&lpg=PA130&dq=product+returns+confusion&source=bl&ots=P_v4nTI0m8&sig=XZ6VGEOtuyJOG7Kwkcd2SMV2_6w&hl=en&sa=X&ved=0ahUKEwiDwtDKt4vPAhVk0YMKHfO-C-AQ6AEINjAD>
> 

We have only been talking about coding styles, which are a small part of
development styles.  And development styles are only a small part of
products as a whole.

Learning to use spaces appropriately and not using Yoda-speak for your
conditionals will not mean end-users will automatically like your product!

> 
>>>>> [would you consider "if (foo==bar())" as preferred to "if
>>>>> (bar()==foo)"?]
>>>>
>>>> I'd usually try to avoid a function call inside an expression inside a
>>>> conditional, but if I did then the guiding principle is to make it
>>>> clear
>>>> to read and understand.
>>>
>>> Which do you claim is cleared?
>>> Imagine foo is "errno".
>>> After answering, rethink it knowing that errno is actually a function
>>> invocation on this platform.
>>
>> Neither is clear enough.
> 
> So, what's your solution?

It would depend on the rest of the context, which is missing here, but
I'd guess it would be something like:

int noOfWhatsits = bar();
if (noOfWhatsits == foo) { ... }

Local variables are free, and let you divide your code into clear and
manageable parts, and their names let you document your code.  I use
them a lot.

(I have also used older and weaker compilers that generated poorer code
if you had lots of local variables - I am glad my current style does not
have to handle such tools.)

> 
>>>>> Much of this is a consequence of how I learned to "read" (subvocalize)
>>>>> code to myself:
>>>>>      x = y;
>>>>> is "x gets the value of y", not "x equals y".  (how would you read
>>>>> x ::=
>>>>> y ?)
>>>>>      if ( CONSTANT == expression )
>>>>> is "if expression yields CONSTANT".  Catching myself saying "if
>>>>> CONSTANT
>>>>> gets
>>>>> expression" -- or "if variable gets expression":
>>>>>      if ( CONSTANT = expression )
>>>>>      if ( variable = expression )
>>>>> is a red flag that I'm PROBABLY not doing what I want to do.
>>>>>
>>>>> I'll wager that most folks read:
>>>>>      x = y;
>>>>> as:
>>>>>      x equals y
>>>>
>>>> I can't say I vocalize code directly - how does one read things like
>>>> brackets or operators like -> ?  But "x = y" means "set x equal to y".
>>>
>>> And, x ::= y effectively says the same -- do you pronounce the colons?
>>> Instead, use a verb that indicates the action being performed:
>>>       x gets y
>>
>> I don't pronounce colons.  I also don't use a programming language
>> with a ::=
>> operator.  But if I did want to pronounce it, then "x gets y" would be
>> fine.
> 
> Then you come up with alternative ways of conveying the information
> present in that symbology.
> 
> E.g., "::=" (used to initialize a variable) vs '=' (used to define
> *constants*, but not variables, and test for value equality) vs ":=:"
> (to test for address equality) vs ":=" (chained assignment) in Algol;
> '=' vs "==" in C; ":=" vs. '=' and ':' and "==" in Limbo; etc.
> 

Different languages have different symbols - yes, I know that.

> When conversing with someone not fluent in a language, the actual
> punctuation plays an important role.

I am lucky enough to have full use of my hands and my eyes, as well as
my mouth.  The same applies to other people I discuss code with.  I
would not try to distinguish "x = y" and "x == y" verbally - I would
/write/ it.

>  Saying "x gets y" to someone
> who isn't familiar with Algol's "::=" would PROBABLY find them
> writing "x = y".  When "reading" Limbo code to someone, I resort
> to "colon-equals", "equals" and "colon" so I'm sure they know
> exactly what I'm saying (because the differences are consequential)
> 
>>> I learned to code with left-facing arrows instead of equal signs
>>> to make the "assignment" more explicit.
>>
>> I think that <- or := is a better choice of symbol for assignment.  The
>> designers of C made a poor choice with "=".
>>
>>>>> and subtly change their intent, but NOT their words, when
>>>>> encountering:
>>>>>      if ( x == y )
>>>>> as:
>>>>>      if x equals y
>>>>
>>>> "if x equals y", or "if x is equal to y".
>>>>
>>>>> (how would they read "if ( x = y )"?)
>>>>
>>>> I read it as "warning: suggest parentheses around assignment used as
>>>> truth value" :-)
>>>
>>> No, your *compiler* tells you that.  If you've NEVER glossed over
>>> such an assignment in your code, you've ALWAYS had a compiler holding
>>> your hand for you.  I'm glad I didn't have to wait 10 years for such
>>> a luxury before *I* started using C.
>>
>> I have used warnings on such errors for as long as I have used
>> compilers that
>> conveniently warned about them.  But I can say it is very rare that a
>> compiler
>> /has/ warned about it - it is not a mistake I have made more than a
>> couple of
>> times.  Still, I want my tools to warn me if it were to happen.
> 
> I want my tools to warn me of everything that they are capable of
> detecting.

Good.  Then we agree - make the best use of the best tools available.

> INCLUDING the tool that occupies my cranial cavity!

I agree.  That means not distracting it with things that are easily
found automatically by compilers and other tools, so that your mind can
concentrate on the difficult stuff.

> 
>>> I'll frequently store pointers to functions where you might store
>>> a variable that you conditionally examine (and then dispatch to
>>> one of N places in your code).  In my case, I just invoke the
>>> function THROUGH the pointer -- the tests were done when I *chose*
>>> which pointer to stuff into that variable (why should I bother to
>>> repeat them each time this code fragment is executed?)
>>>
>>> When you do code reviews, do you all sit around with laptops and
>>> live code copies?  Or, do you pour over LISTINGS with red pens?
>>> Do you expect people to just give the code a cursory once-over?
>>> Or, do you expect them to *read* the code and act as "human
>>> compilers/processors"?
>>
>> I expect code to be as simple to understand as possible, so that it
>> takes as
>> little time or effort as possible for other people to read. That way
>> others can
>> spend their effort on confirming that what the code does is the right
>> thing,
>> rather than on figuring out what the code does first.
> 
> What's simple to me might not be simple to you!  E.g., I naturally
> think in terms of pointers.  Others prefer array indexes.  For me
> to jump/call *through* a pointer is far more obvious than encoding some
> meaning into a flag at some point in the program.  Then, decoding that
> flag at another point and dispatching based on that decode!  The latter
> requires keeping two pieces of code in sync (encode & decode).  The
> former puts everything in one place (encoding).

Agreed - there is plenty of scope for personal variation and style here.

> 
> Should I write code at a level that a newbie developer can understand?
> Should I limit myself to how expressive and productive I can be out of fear
> that someone might not be quick to grasp what I've written?

The right balance here will vary depending on the circumstances - there
is no single correct answer (but there are many wrong answers).

> 
>>> There is no such thing as a perfect style.  You adopt a style that
>>> works for you and measure its success by how buggy the code is (or
>>> is not) that you produce and the time that it takes you to produce it.
>>
>> Yes.
>>
>>>
>>> I suspect if I sat you down with some of these early and one-of-a-kind
>>> compilers, you'd spend a helluva lot more time chasing down bugs that
>>> the compiler didn't hint at.  And, probably run the risk of some
>>> creeping
>>> into your release (x=y=3) that you'd never caught.
>>
>> No.
>>
>> Static checking by the compiler is not a substitute for writing
>> correct code.
> 
> Where am I writing "INcorrect code"?  It meets the specifications of the
> language.  It compiles without errors or warnings.  It fulfills the goals
> of the specification.

There is more to writing good code than that (and I know you know that).
 Whether you call bad code that happens to work "correct" or "incorrect"
is up to you.

But my point here was that you seem to imply I write code with little
regard for it being correct or incorrect, and then rely on the compiler
to find my errors.

> 
> It's just that *you* don't like my style!  Is that what makes it "not
> correct"?

I suspect that in the great majority of cases where I don't like your
style, then it is nothing more than that.  I might think it is not clear
or easy to understand, or not as maintainable as it could be, or simply
looks ugly and hard to read, or that it is not as efficient as other
styles.  I can't say for sure, since about the only things I know for
sure about your style is that you like to write "if (3 == x)" rather
than "if (x == 3)", and that you like function pointers.

It takes a lot more than that for me to label code as "incorrect" or
"bad" (assuming the final result does the job required).

> If I replaced the identifiers for manifest constants with lowercase
> symbols,
> would that make it MORE correct?  Should I use camelcase identifiers?
> Hungarian notation?  Embedded underscores?   How do any of these make the
> code more or less "correct"?

If a change makes code clearer, then it is a good thing.  Visually
splitting the words in a multi-word identifier makes code clearer -
whether that is done using camelCase or underscores is a minor issue.
Small letters are easier to read (that's why they exist!), and avoid
unnecessary emphasis - that makes them a good choice in most cases.  And
there is rarely any benefit in indicating that an identifier is a
constant or a macro (assuming it is defined and used sensibly) - so
there is no point in making such a dramatic distinction.

> 
>> You make it sound like I program by throwing a bunch of random symbols
>> at the
>> compiler, then fixing each point it complains about.  The checking is
>> automated
>> confirmation that I am following the rules I use when coding, plus
>> convenient
>> checking of silly typos that anyone makes on occasion.
>>
>>> Instead of pushing an update to the customer over the internet, you'd
>>> send someone out to their site to install a new set of EPROMs.  Or,
>>> have them mail the product back to you as their replacement arrived
>>> (via USPS).  Kind of annoying for the customer when he's got your
>>> device on his commercial fishing boat.  Or, has to lose a day's
>>> production
>>> while it's removed from service, updated and then recertified.
>>
>> I have mailed EPROMs to customers, or had products delivered back for
>> program
>> updates.  But never due to small mistakes of the sort we are
>> discussing here.
> 
> I've *never* had to update a product after delivery.  Because the cost of
> doing so would easily exceed the profit margin in the product!
> 
> I've had clients request modifications to a product; or tweeks for
> specific customers.  But, those aren't "bug fixes", they're effectively
> "new products" that leverage existing hardware.

And those are updates after delivery.  There are many perfectly good
reasons for updating software after delivery.  All I said was that I
have provided updates in a variety of ways, and for a variety of reasons
- but never for the sort of mistakes that you seem to think you are
immune to because you learned to program with limited tools, while you
think /I/ make them all the time because I take advantage of modern tool
features.

> "No, there will be no upgrades.  You will get it right the first time!"
> 

That is fine for some projects.  I have had cards that have been
cemented into the ocean floor - upgrades are not physically possible.
And on other projects, customers want to be able to have new features or
changes at a later date.

I think everyone agrees that shipping something that does not work
correctly, and updating for bug fixes, is always a bad idea - just /how/
bad it is will vary.

>> The new programmer should learn to take advantage of new tools, and
>> concentrate
>> efforts on problems that are relevant rather than problems are no
>> longer an
>> issue (to the extent that they ever /were/ an issue). And if that new
>> programmer is faced with poorer tools, then he or she will have to
>> learn the
>> idiosyncrasies at the time.  And the lack of warnings on "if (x = 1)" is
>> unlikely to be the most important point.
> 
> Without the warning, the developer is likely to waste a boatload of
> time "seeing what he wants to see" and not what the *compiler* sees.

Without decent warnings, developers (especially new ones) are likely to
spend a good deal more time chasing small bugs than they would if the
compiler or linter helped them out.  But why do you think this
particular issue is so important?  New C programmers are often told how
important it is to distinguish between = and ==, so it is something they
look out for, and avoid in most cases.  And the Yoda rule only helps in
/some/ cases where you have comparisons - you still need to get your =
and == right everywhere else.

> 
>>> There's a reason you can look at preprocessor output and ASM
>>> sources.  Because they are the only way to understand some nasty
>>> bugs that may arise from your misunderstanding of what a tool
>>> SHOULD be doing; *or*, from a defective tool!  (a broken tool
>>> doesn't have to tell you that it's broken!)
>>
>> I have almost /never/ had occasion to look at pre-processor output. 
>> But I do
>> recommend that embedded programmers should be familiar enough with the
>> assembly
>> for their targets that they can look at and understand the assembly
>> listing.
> 
> You've probably never "abused" the preprocessor in creative ways!  :>
> 

I have abused preprocessors a bit (any use of ## is abuse!), but I
haven't had to look at the output directly to debug that abuse.  Maybe I
haven't been creative enough in my abuses here.

[toc] | [prev] | [next] | [standalone]


#25037

FromDennis <dennis@none.none>
Date2016-09-13 10:22 -0500
Message-ID<nr95j0$lu$1@dont-email.me>
In reply to#25035
On 09/13/2016 05:25 AM, David Brown wrote:

>
>
> If a change makes code clearer, then it is a good thing.  Visually
> splitting the words in a multi-word identifier makes code clearer -
> whether that is done using camelCase or underscores is a minor issue.

I'll go off on a tangent - it can be an important issue. I once worked 
with a guy that was visually impaired and used a screen reader for much 
of his work. The underscore form would read as (spoken)word 
(spoken)underscore (spoken)word... where the camelCase would cause it to 
give up and spell it all out. We referred to the underscore form as 
"easy reader code". This was over a decade ago so screen readers may be 
smarter now.

> Small letters are easier to read (that's why they exist!), and avoid
> unnecessary emphasis - that makes them a good choice in most cases.  And
> there is rarely any benefit in indicating that an identifier is a
> constant or a macro (assuming it is defined and used sensibly) - so
> there is no point in making such a dramatic distinction.
>

[toc] | [prev] | [next] | [standalone]


#25038

FromDavid Brown <david.brown@hesbynett.no>
Date2016-09-13 20:08 +0200
Message-ID<nr9fa7$5gf$1@dont-email.me>
In reply to#25037
On 13/09/16 17:22, Dennis wrote:
> On 09/13/2016 05:25 AM, David Brown wrote:
>
>>
>>
>> If a change makes code clearer, then it is a good thing.  Visually
>> splitting the words in a multi-word identifier makes code clearer -
>> whether that is done using camelCase or underscores is a minor issue.
>
> I'll go off on a tangent - it can be an important issue. I once worked
> with a guy that was visually impaired and used a screen reader for much
> of his work. The underscore form would read as (spoken)word
> (spoken)underscore (spoken)word... where the camelCase would cause it to
> give up and spell it all out. We referred to the underscore form as
> "easy reader code". This was over a decade ago so screen readers may be
> smarter now.

Unless it is a screen reader specially designed for code, then I'd 
imagine it would have trouble with camelCase words.  I think Don knows 
more about this sort of program.

But you are absolutely right that there can be particular circumstances 
that determine our choices here, and have overriding importance.


>
>> Small letters are easier to read (that's why they exist!), and avoid
>> unnecessary emphasis - that makes them a good choice in most cases.  And
>> there is rarely any benefit in indicating that an identifier is a
>> constant or a macro (assuming it is defined and used sensibly) - so
>> there is no point in making such a dramatic distinction.
>>
>

[toc] | [prev] | [next] | [standalone]


#25009

Fromrwood <rwoodl@nowhere.com>
Date2016-09-12 16:50 +0800
Message-ID<coudnTnsMJjS8UvKnZ2dnUU7-cOdnZ2d@westnet.com.au>
In reply to#25000
On 11-Sep-16 10:58 PM, David Brown wrote:
> On 11/09/16 16:32, Don Y wrote:
>> On 9/11/2016 4:35 AM, David Brown wrote:
>>> Also consider:
>>>      static const uint8_t my_variable = 0b10000000;
>>>
>>> instead of the #define, unless you really need it to be a #define'd
>>> value (such
>>> as to give the size of an array, or because you have a crap compiler).
>>
>> A drawback to this approach is it allows the OP to continue to think
>> of it as a "variable".  Either rename it ("my_constant" or "MY_CONSTANT")
>> or use a manifest constant so each reference is ACTUALLY replaced with
>> the PREPROCESSOR SUBSTITUTION:
>>       MY_CONSTANT = 7;  (wrong!)
>> becomes:
>>       128 = 7;
>> (which is CLEARLY wrong!)
>>
>> [Time for bed...]
>>
>>
>
> Well, clearly he needs to pick a better name for his "variable".  I
> don't know if he just picked a bad name, or if he is confused about
> variables and constants.
>
> But if "my_variable" is declared as a "const", then writing "my_variable
> = 7" will give a compile-time error just as surely as it would with a
> pre-processor symbol.
>


Yep - poor form on my part I should have referred to it as a constant 
rather than variable.

[toc] | [prev] | [next] | [standalone]


#25001

FromTom Gardner <spamjunk@blueyonder.co.uk>
Date2016-09-11 17:13 +0100
Message-ID<EofBz.519583$tK.358369@fx36.am4>
In reply to#24997
On 11/09/16 15:32, Don Y wrote:
> On 9/11/2016 4:35 AM, David Brown wrote:
>> Also consider:
>>      static const uint8_t my_variable = 0b10000000;
>>
>> instead of the #define, unless you really need it to be a #define'd value (such
>> as to give the size of an array, or because you have a crap compiler).
>
> A drawback to this approach is it allows the OP to continue to think
> of it as a "variable".  Either rename it ("my_constant" or "MY_CONSTANT")
> or use a manifest constant so each reference is ACTUALLY replaced with
> the PREPROCESSOR SUBSTITUTION:
>       MY_CONSTANT = 7;  (wrong!)
> becomes:
>       128 = 7;
> (which is CLEARLY wrong!)
>
> [Time for bed...]

Except, of course, that 0b10000000 == 512, which is probably the
source of the original "warning: (752) conversion to shorter
data type"

Everybody should occasionally re-read the "Frequently Questioned
Answers" http://yosefk.com/c++fqa/

[toc] | [prev] | [next] | [standalone]


#25002

FromTom Gardner <spamjunk@blueyonder.co.uk>
Date2016-09-11 17:19 +0100
Message-ID<KufBz.519584$tK.510392@fx36.am4>
In reply to#25001
On 11/09/16 17:13, Tom Gardner wrote:
> On 11/09/16 15:32, Don Y wrote:
>> On 9/11/2016 4:35 AM, David Brown wrote:
>>> Also consider:
>>>      static const uint8_t my_variable = 0b10000000;
>>>
>>> instead of the #define, unless you really need it to be a #define'd value (such
>>> as to give the size of an array, or because you have a crap compiler).
>>
>> A drawback to this approach is it allows the OP to continue to think
>> of it as a "variable".  Either rename it ("my_constant" or "MY_CONSTANT")
>> or use a manifest constant so each reference is ACTUALLY replaced with
>> the PREPROCESSOR SUBSTITUTION:
>>       MY_CONSTANT = 7;  (wrong!)
>> becomes:
>>       128 = 7;
>> (which is CLEARLY wrong!)
>>
>> [Time for bed...]
>
> Except, of course, that 0b10000000 == 512, which is probably the
> source of the original "warning: (752) conversion to shorter
> data type"

Oops. Please ignore my dyslexia, or maybe my eyesight is going.


> Everybody should occasionally re-read the "Frequently Questioned
> Answers" http://yosefk.com/c++fqa/

[toc] | [prev] | [next] | [standalone]


#25008

FromDavid Brown <david.brown@hesbynett.no>
Date2016-09-12 09:00 +0200
Message-ID<nr5jpp$4e1$1@dont-email.me>
In reply to#25002
On 11/09/16 18:19, Tom Gardner wrote:
> On 11/09/16 17:13, Tom Gardner wrote:
>> On 11/09/16 15:32, Don Y wrote:
>>> On 9/11/2016 4:35 AM, David Brown wrote:
>>>> Also consider:
>>>>      static const uint8_t my_variable = 0b10000000;
>>>>
>>>> instead of the #define, unless you really need it to be a #define'd
>>>> value (such
>>>> as to give the size of an array, or because you have a crap compiler).
>>>
>>> A drawback to this approach is it allows the OP to continue to think
>>> of it as a "variable".  Either rename it ("my_constant" or
>>> "MY_CONSTANT")
>>> or use a manifest constant so each reference is ACTUALLY replaced with
>>> the PREPROCESSOR SUBSTITUTION:
>>>       MY_CONSTANT = 7;  (wrong!)
>>> becomes:
>>>       128 = 7;
>>> (which is CLEARLY wrong!)
>>>
>>> [Time for bed...]
>>
>> Except, of course, that 0b10000000 == 512, which is probably the
>> source of the original "warning: (752) conversion to shorter
>> data type"
> 
> Oops. Please ignore my dyslexia, or maybe my eyesight is going.
> 

Actually, you raise a good point - 0b10000000 is hard to read.  0b
constants are fine for small values, and okay for bigger values if there
are plenty of 0's and 1's.  But your eyes need a transition every 4 or 5
digits for clock recovery.  So numbers like this are often better
expressed as hex (0x80), or with shifts (1u << 7) or perhaps (0b1000 <<
4), if that suits a pattern with other defined constants in the code.

Or use C++14, and write 0b1000'0000.  (The ' separator the C++ standards
folks picked may not be the nicest choice, but it is better than nothing.)

[toc] | [prev] | [next] | [standalone]


#24996

FromDon Y <blockedofcourse@foo.invalid>
Date2016-09-11 07:28 -0700
Message-ID<nr3pmc$1ue$1@dont-email.me>
In reply to#24989
On 9/11/2016 3:25 AM, rwood wrote:
> On 11-Sep-16 5:55 PM, Don Y wrote:
>> On 9/11/2016 12:02 AM, rwood wrote:
>>> Novice question using MPLABx + XC8
>>>
>>> If i define my_variable using;
>>>
>>> #define my_variable 0b10000000
>>>
>>> And then I use it in a function that expects a 'char';
>>>
>>> void my_function(char i);
>>>
>>>
>>>
>>> I get a compiler warning;
>>>
>>> warning: (752) conversion to shorter data type
>>>
>>> By changing the function prototype to expect an 'int' the warning goes
>>> away so
>>> I think the defined my_variable is being assigned as an 'int'
>>>
>>> So my question is how or can I structure my define so the defined
>>> my_variable
>>> is assigned as a 'char'..
>>>
>>> I cannot see anything useful in the mplabx documentation.
>>
>> Why not explicitly cast the value to a "char" in the define-ition
>> (*if* you expect to always use it as such)?
>>
>> Note that you should decide if you do/don't care about signedness
>> of the value (i.e., is this value 128 or -127?) as "char" can vary

Grrrr.... s/-127/-128/

(Moral:  don't mix physical activities with mental ones!  :<)

>> from implementation to implementation.
>
> Hi Don, I tried using:
>          #define my_variable (char)0b10000000
> and also:
>          #define my_variable ((char)0b10000000)
>
> Both of which compile without issue but still the warning  about converting to
> a shorter data type persists.

Would you expect no warnings on:
   signed short int my_counter = 32768;
(i.e., to use your notation:  0b1000 0000 0000 0000)?

Hint:  signed shorts are effectively [-32768,32767].

Any time the compiler has latitude to "make up its own mind" about
something, you should DEPRIVE it of that latitude!  If you expect
something to never be negative, then declare it as unsigned (there
are some issues on some platforms where you can incur a small
performance penalty but, chances are, YOU aren't going to be
dealing with those).  Otherwise, DECLARE it to be signed -- as
a reminder that it's range of values includes negative ones
(at the expense of some POSITIVE ones!)

[Elsewhere (this newsgroup?) we discussed using TFTP as a file
transfer protocol.  It uses a 16 bit "block counter" in the
protocol.  There are implementations that have defined it as
"short int" -- or just "short".  See the problem?  It's a
*counter* so it's always intended to have positive values
(you can't have "negative items") so never exceeds 32767!
The next value in the "count sequence" is -32768!]

Imagine you'd written my example above as:
   #define ITERATIONS (32768)
   ...
   signed short int my_counter = ITERATIONS;
wouldn't you *want* the compiler to let you know that "it can't count
that high" (with a signed short)?

Or, more indirectly:
    counter_t my_counter = ITERATIONS;

[imagine someone changes the declaration for counter_t and/or ITERATIONS]

That's why you should treat warnings as errors -- not errors in
the code, per se, but, rather, errors in your thinking and
expectations!

(the code will almost always *run* -- but not the way you had *hoped*
it would run!)

As you tweak the syntax to make the error go away, you should be asking
yourself, "why do I *have* to do this?  What is the compiler trying to
DISCOURAGE me from doing??"  (HInt: chances are, it is SMARTER than you!)

Kinda like looking down the barrel of a gun and your friend saying,
"Are you SURE you want to be doing that?? (with one in the chamber)"

As an exercise, you should also play with:
    (signed) <value>
    (char) (unsigned) <value>
    (unsigned char) <value>
etc. with differing (signed and unsigned) <value>s and notice how the
compiler treats each variant.

[toc] | [prev] | [next] | [standalone]


#24990

Fromupsidedown@downunder.com
Date2016-09-11 13:56 +0300
Message-ID<akdatb130h95brnf1ks49svim7oiss97s9@4ax.com>
In reply to#24988
On Sun, 11 Sep 2016 02:55:23 -0700, Don Y
<blockedofcourse@foo.invalid> wrote:

>On 9/11/2016 12:02 AM, rwood wrote:
>> Novice question using MPLABx + XC8
>>
>> If i define my_variable using;
>>
>> #define my_variable 0b10000000
>>
>> And then I use it in a function that expects a 'char';
>>
>> void my_function(char i);
>>
>>
>>
>> I get a compiler warning;
>>
>> warning: (752) conversion to shorter data type
>>
>> By changing the function prototype to expect an 'int' the warning goes away so
>> I think the defined my_variable is being assigned as an 'int'
>>
>> So my question is how or can I structure my define so the defined my_variable
>> is assigned as a 'char'..
>>
>> I cannot see anything useful in the mplabx documentation.
>
>Why not explicitly cast the value to a "char" in the define-ition
>(*if* you expect to always use it as such)?
>
>Note that you should decide if you do/don't care about signedness
>of the value (i.e., is this value 128 or -127?) as "char" can vary
>from implementation to implementation.


Are there still some idiotic systems that are defining char as
_signed_ ????

If we really have to use such outdated systems, why aren't we using 6
bit characters with all upper case (or all lower case) ? In fact why
not use 5 bit Baudot as in Manchester computers ?

[toc] | [prev] | [next] | [standalone]


#24991

FromDavid Brown <david.brown@hesbynett.no>
Date2016-09-11 13:28 +0200
Message-ID<nr3f41$ur9$1@dont-email.me>
In reply to#24990
On 11/09/16 12:56, upsidedown@downunder.com wrote:
> On Sun, 11 Sep 2016 02:55:23 -0700, Don Y
> <blockedofcourse@foo.invalid> wrote:
>
>> On 9/11/2016 12:02 AM, rwood wrote:
>>> Novice question using MPLABx + XC8
>>>
>>> If i define my_variable using;
>>>
>>> #define my_variable 0b10000000
>>>
>>> And then I use it in a function that expects a 'char';
>>>
>>> void my_function(char i);
>>>
>>>
>>>
>>> I get a compiler warning;
>>>
>>> warning: (752) conversion to shorter data type
>>>
>>> By changing the function prototype to expect an 'int' the warning goes away so
>>> I think the defined my_variable is being assigned as an 'int'
>>>
>>> So my question is how or can I structure my define so the defined my_variable
>>> is assigned as a 'char'..
>>>
>>> I cannot see anything useful in the mplabx documentation.
>>
>> Why not explicitly cast the value to a "char" in the define-ition
>> (*if* you expect to always use it as such)?
>>
>> Note that you should decide if you do/don't care about signedness
>> of the value (i.e., is this value 128 or -127?) as "char" can vary
>>from implementation to implementation.
>
>
> Are there still some idiotic systems that are defining char as
> _signed_ ????
>
> If we really have to use such outdated systems, why aren't we using 6
> bit characters with all upper case (or all lower case) ? In fact why
> not use 5 bit Baudot as in Manchester computers ?
>

Yes, there are "idiotic" systems that have signed plain char.  Most 
older, bigger systems (x86, PPC, MIPS, etc.) seem to have char signed by 
default.

The way to handle it is to only ever use "char" when you really mean a 
simple ASCII character.  For anything else, use "uint8_t" or "int8_t" as 
appropriate.  If you have a weird fascination for meaningless names, you 
can also use "unsigned char" or "signed char".  But every time I see a 
function that takes a "char" and is not either a legacy C library 
function, or clearly looking for an ASCII character with a name like 
"debugPrintChar()", I know the code is bad.

[toc] | [prev] | [next] | [standalone]


#24993

FromHans-Bernhard Bröker <HBBroeker@t-online.de>
Date2016-09-11 13:36 +0200
Message-ID<e3ku00F2ulaU1@mid.dfncis.de>
In reply to#24990
Am 11.09.2016 um 12:56 schrieb upsidedown@downunder.com:
> On Sun, 11 Sep 2016 02:55:23 -0700, Don Y
> <blockedofcourse@foo.invalid> wrote:

> Are there still some idiotic systems that are defining char as
> _signed_ ????

Given that such systems are explicitly allowed by the C standard, 
there's nothing particularly idiotic about them.

But are there still idiotic programmers who use plain "char" in 
situations where they care about signedness?  Well, yes, there are. 
Which is why coding standards such as MISRA forbid using plain char.

> If we really have to use such outdated systems, why aren't we using 6
> bit characters with all upper case (or all lower case) ? In fact why
> not use 5 bit Baudot as in Manchester computers ?

For starters: because those _are_ forbidden under the rules of the language.

Anyway, making plain char unsigned does not really solve any problem, so 
IMHO it's by no means idiotic to keep it signed.

It may appear to provide a solution to the issue: "How to keep non-ASCII 
characters in a plain char?"  Except that it does so very incompletely, 
at best, because there are way more non-ASCII characters than an 8 bits 
unsigned char can possibly hold.

If one designed a new language like C today, 'char' would probably be 
called 'byte', or it would be emitted in favour of {u,}int8_t, whereas 
char would be 16 or 32 bits wide, and character and string constants 
UTF-8.  But that's 20/20 hind sight, 30 years after the fact.

[toc] | [prev] | [next] | [standalone]


#24995

Fromupsidedown@downunder.com
Date2016-09-11 16:14 +0300
Message-ID<6kjatbdjkpno310kc1e2hgl2ebd097dj67@4ax.com>
In reply to#24993
On Sun, 11 Sep 2016 13:36:59 +0200, Hans-Bernhard Bröker
<HBBroeker@t-online.de> wrote:

>Am 11.09.2016 um 12:56 schrieb upsidedown@downunder.com:
>> On Sun, 11 Sep 2016 02:55:23 -0700, Don Y
>> <blockedofcourse@foo.invalid> wrote:
>
>> Are there still some idiotic systems that are defining char as
>> _signed_ ????
>
>Given that such systems are explicitly allowed by the C standard, 
>there's nothing particularly idiotic about them.
>
>But are there still idiotic programmers who use plain "char" in 
>situations where they care about signedness?  Well, yes, there are. 
>Which is why coding standards such as MISRA forbid using plain char.
>
>> If we really have to use such outdated systems, why aren't we using 6
>> bit characters with all upper case (or all lower case) ? In fact why
>> not use 5 bit Baudot as in Manchester computers ?
>
>For starters: because those _are_ forbidden under the rules of the language.
>
>Anyway, making plain char unsigned does not really solve any problem, so 
>IMHO it's by no means idiotic to keep it signed.

While this have been true for more than 30 years ago when everything
was 7 bit ASCII or  at least ISO646,

Of course EBCDIC had also some extended ranges.

Later on, VT220 multinational and later on Latin1 character sets
utilized the while 8 bit range as a single _unsigned_ linear range.
 
>It may appear to provide a solution to the issue: "How to keep non-ASCII 
>characters in a plain char?"  

Unsigned char was the answer for at least 5-10 years before UCS2.

>Except that it does so very incompletely, 
>at best, because there are way more non-ASCII characters than an 8 bits 
>unsigned char can possibly hold.

That is true. 

For correctly storing Unicode characters, a 21 bit data type is
required. 

There are some more or less workarounds for storing these Unicode
characters, such as UTF-8 (1-3 bytes), UTF-16 (2-4 bytes) or as I once
suggested UTF-64 on the Unicode list (three 21 bit characters in a 64
bit computer word e.g. Itanium.

>If one designed a new language like C today, 'char' would probably be 
>called 'byte', or it would be emitted in favour of {u,}int8_t, 

that would be OK. {u,}int8_t, please.

>whereas 
>char would be 16 or 32 bits wide, 

actually 21 bit values.

>and character and string constants 
>UTF-8.  

UTF-8 is a quite reasonable compromize for most lnguages.

>But that's 20/20 hind sight, 30 years after the fact.

Having done IT applications for more than 30 years, the problem was
well known in those days. 

The video (dot matrix) display units of those days were not capable of
displaying very good glyphs, but still good for Latin, Cyrillic or
Arabic glyphs, but ware quite bad on Est-Asian glyphs.

[toc] | [prev] | [next] | [standalone]


#24999

FromDon Y <blockedofcourse@foo.invalid>
Date2016-09-11 07:57 -0700
Message-ID<nr3rd1$80k$1@dont-email.me>
In reply to#24995
On 9/11/2016 6:14 AM, upsidedown@downunder.com wrote:
> The video (dot matrix) display units of those days were not capable of
> displaying very good glyphs, but still good for Latin, Cyrillic or
> Arabic glyphs, but ware quite bad on Est-Asian glyphs.

Not a problem with a PDS-1 (mid 70's vintage) -- *if* you could
afford one!  :>

[toc] | [prev] | [next] | [standalone]


#25025

FromHans-Bernhard Bröker <HBBroeker@t-online.de>
Date2016-09-12 22:52 +0200
Message-ID<e3oiskFtrj5U1@mid.dfncis.de>
In reply to#24995
Am 11.09.2016 um 15:14 schrieb upsidedown@downunder.com:
> On Sun, 11 Sep 2016 13:36:59 +0200, Hans-Bernhard Bröker
> <HBBroeker@t-online.de> wrote:

>> It may appear to provide a solution to the issue: "How to keep non-ASCII
>> characters in a plain char?"

> Unsigned char was the answer for at least 5-10 years before UCS2.

It really wasn't, because as a solution it was incoherent, incomplete, 
and insular.  Anyway, there really weren't that many years between C90 
and UCS2.

8-bit unsigned char for non-ASCII characters created more problems than 
it ever solved.  Instead of having one obvious, while painful 
restriction, we now had

*) dozens of conflicting interpretations of the same 256 values,
*) no standard way of knowing which of those applied to given input
*) almost no way of combining multiple such streams internally
*) no useful way of outputting a combined stream

> For correctly storing Unicode characters, a 21 bit data type is
> required.

Not quite.  You need a type with _at_least_ 21 bits.  It doesn't have to 
be a 21-bit data type.

> Having done IT applications for more than 30 years, the problem was
> well known in those days.

The problem: yes.  But essentially nobody dared to implement an actual 
solution.

C itself has had some support for wider character representations and 
all that from the get-go (i.e. the first actual standard in 1990), but I 
don't think I've ever seen anyone use that in anger.

> The video (dot matrix) display units of those days were not capable of
> displaying very good glyphs, but still good for Latin, Cyrillic or
> Arabic glyphs, but ware quite bad on Est-Asian glyphs.

But they could generally only display Latin, Cyrillic, _or_ Arabic, but 
not all of them on the same screen.  I.e. they suffered from the same 
problem as using 8-bit unsigned for 'char' does: one more bit just isn't 
enough to do the job.

[toc] | [prev] | [next] | [standalone]


#25032

Fromupsidedown@downunder.com
Date2016-09-13 10:11 +0300
Message-ID<136ftbd1f2usqrlh48ps1o23383pktg2o6@4ax.com>
In reply to#25025
On Mon, 12 Sep 2016 22:52:00 +0200, Hans-Bernhard Bröker
<HBBroeker@t-online.de> wrote:

>Am 11.09.2016 um 15:14 schrieb upsidedown@downunder.com:
>> On Sun, 11 Sep 2016 13:36:59 +0200, Hans-Bernhard Bröker
>> <HBBroeker@t-online.de> wrote:
>
>>> It may appear to provide a solution to the issue: "How to keep non-ASCII
>>> characters in a plain char?"
>
>> Unsigned char was the answer for at least 5-10 years before UCS2.
>
>It really wasn't, because as a solution it was incoherent, incomplete, 
>and insular.  Anyway, there really weren't that many years between C90 
>and UCS2.
>
>8-bit unsigned char for non-ASCII characters created more problems than 
>it ever solved.  Instead of having one obvious, while painful 
>restriction, we now had
>
>*) dozens of conflicting interpretations of the same 256 values,
>*) no standard way of knowing which of those applied to given input
>*) almost no way of combining multiple such streams internally
>*) no useful way of outputting a combined stream

Exactly the same problems existed with the 7 bit ISO646 from the
1960/70's.

In ISO 646 some of the US-ASCII code points were replaced by a
national character, such as @ [ \ ] { | } _ ^  ~ $ #

The replacement characters were typically different for each country
or at least each language. Try to combine texts from different
languages produced a mess. This was a problem especially in countries
with multiple official languages. Also writing names of foreign origin
caused problems.

Think about Pascal or C-programming, with missing [ \ ] { | }  ^
characters, which in one code page might have been displayed as Ä Ö Å
ä ö å in one code page but  something different in an other code page.
This was especially problematic for printing with a language specific
printer (e.g. daisy chain) giving quite different looking printouts
depending on which printer was used.

For programming, the most convenient way was to switch the terminal to
US-ASCII, but unfortunately the keyboard layout also changed.

Digraphs and trigraphs partially solved this problem but was ugly.

With the introduction of the 8 bit  ISO Latin, a large number of
languages and programming could be handled with that single code page,
greatly simplifying data exchange in Europe,  Americas, Africa and
Australia.

[toc] | [prev] | [next] | [standalone]


Page 2 of 3 — ← Prev page 1 [2] 3  Next page →

Back to top | Article view | comp.arch.embedded


csiph-web