EmbeddedRelated.com
Forums

XC8 novice question

Started by rwood September 11, 2016
Il giorno lunedì 12 settembre 2016 14:56:24 UTC+2, David Brown ha scritto:

> compiler error. If the constant is not actually a constant, but a > variable, you get a warning.
not always, it depends on the compiler. Bye Jack
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: >>>> On 9/11/2016 7:58 AM, David Brown wrote: >>>>> 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. >>>> >>>> Yes, but IME much easier to see whay you've done wrong (looking at the >>>> cpp(1) output). >>>> >>>> Similar to writing: >>>> if (4 == count)... >>>> instead of: >>>> if (count == 4)... >>> >>> Well, there may be differences of opinion here - and certainly >>> experience and preferences are personal, making it hard to say "you are >>> wrong". >>> >>> But you are wrong. >>> >>> Writing "if (4 == count)" is wrong. The last thing you need in your >>> code is to write it backwards - it messes with your thinking, your >>> writing, your reading and your understanding. >>> >>> There are only three reasons why you would want to write "if (4 == >>> count)". Either /all/ of these are true: >> >> No, the answer is much simpler than any of that! >> >> I started writing code in C (almost exactly) 40 years ago. Owning >> my first "personal" SysV machine more than 30 years ago. >> >> Compilers "back then" were far less "helpful" than what folks >> are used to using, today. And, far less "accessible" (imagine >> writing your code on a piece of PAPER and frantically typing >> it in when you get a chance -- so you can actually RUN it a few >> times, TODAY). Does your pen/paper "run lint"? > > Yes, long ago compilers had little in the way of helpful warnings or > checks. And long ago, lint was not as good (though it's history is > nearly 40 years old), and not as easily available. > > But /today/, there is no reason not to have reasonable error checking > and warnings on your compiler. And if you compiler doesn't do a good > enough job by itself, you can use PC-Lint, splint, or even gcc/clang for > a different target in order to get good checking. (It's not needed here > - XC8 will report "if (count = 4)" errors.) > >> >> [Do you remember when C didn't have a "void" type? Or, using '\!' >> and '\!!' in your sources? Or, when members of one type of >> struct had to have different names from any members of any >> OTHER structs (i.e., all tags shared a SINGLE namespace)?] > > The earliest C I have worked with is C89/C90/ANSI. It is fortunately > rare that I have to work with such old tools, and I think it would be > madness to limit my modern programming to suit such tools.
Try 10 years earlier. Try writing on a PDP-11 that you SHARED with others (including PAYROLL!)
>> 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 ; Nowadays, you would see this as: x -= 1 ; 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;
>> 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'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!
>> 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; seen, instead, as (error-free!): y=x=3;
>> (*f)(); > > I'd write > > f(); > > Though I'd use a better name than "f" for a function pointer, and I try > to avoid function pointers where possible. > >> Or, lengthy expressions laid out as: >> foo = ( a + b ) >> / ( c * d ) >> - ( e % f ); > > If the expression were complicated enough, I would write: > > int x = a + b; > int y = c * d; > int z = e % f; > foo = x / y - z; > >> 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...
> 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.
> 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!
>> [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.
>> 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 learned to code with left-facing arrows instead of equal signs to make the "assignment" more explicit.
>> 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.
> It's simply a mistake, and I would not read it at all without mentioning > the error. >> >> People reading my code never seem to have any problem understanding >> that: >> if ( NULL == malloc(...) ) >> is testing for a NULL result from malloc (i.e., "malloc yielding NULL"). > > Certainly people will know what the code does. That does not mean it is > the clearest choice of code for the job.
What you care about is: - does it do what it is intended to do - can others "skilled in the art" understand its intent 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"?
>> [They also don't seem to find parallel loading a (hardware) counter with >> 0 as the same as "clearing" it.] >> >> This sort of "reading" makes it easy to discuss: >> (x, y) := cursor_position(); >> ("instantiate an x,y tuple with the current cursor position") vs. >> (x, y) = cursor_position(); >> ("the x,y tuple gets the current cursor position") or: >> x = cursor_X_coordinate(); >> ("x gets the cursor's X coordinate") >> >> What's important is consistency. It takes very little time for someone to >> pick up on a particular style -- if it is used CONSISTENTLY throughout a >> document/project. Ever notice code that walks an array using an index >> into the array; then, somewhere else, a pointer into it? As if the >> decision was arbitrary (or, made by someone other than the original >> developer -- having a different style?) Or, that refers to screen >> coordinates >> as "(x,y)" in some places, "(row,column)" in others (did you notice that >> row,column is really y,x?) and "(r,c)" in still others? >> >> You can read my code over the years and see the same style propagated >> throughout (discounting changes to the language, as alluded to earlier). >> It doesn't change when the "style du jour" comes -- and goes! -- along >> the way! (though identifiers have lengthened as the tools have supported >> them) > > My code style has been fairly similar over the 20 years I have been > professionally programming C, as the guiding principles have been > consistent. But a number of aspects have changed over time - when a > change of style has made sense and led to better or clearer code, I have > made that change. And when newer and better tools or language features > have allowed better or clearer code, then I have embraced those features > and changes. I certainly don't believe I started my career with a > perfect style that must be maintained for ever.
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. 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. 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.
> 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?
> 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)? 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!)
On 9/12/2016 5:16 AM, Mike Perkins wrote:
> On 12/09/2016 10:41, Don Y wrote: >> And, to catch (some) '=' instead of "==" errors, write tests as: >> if ( CONSTANT == expression ) ... > > This is why I now write to this form. As someone who also writes VHDL where a > single '=' is used in a conditional statement, it's all too easy to forget the > '==' when reverting back to writing C.
On a daily basis, I use: foo = bar foo := bar foo == bar all as variants of what some would read as "equals". I don't want to be casual in what I type. And, I don't want folks reading it to be casual in what they read: what EXACTLY is he saying, here? Why the colon? Why the extra '='? Why *not* a colon/extra '='? It's far too easy to see what you WANT to see when "proofreading". And, for folks who've been coerced into performing a function (e.g., not many folks are eager to participate in a code review: "*MY* code isn't getting written while I'm sitting here CHECKING YOURS!"), there's even less incentive to "read carefully".
> If, by accident, I write in 'c' > if ( CONSTANT = expression ) > I get a compiler error rather than getting entirely different behaviour to that > intended. > > It is a style often recommended for safety critical applications.
Often, safety critical (and other "regulated" application domains) have few compiler releases. Because the compiler must be formally certified/qualified. So, you don't benefit from the most recent product offerings of company's X, Y and Z. And, you almost surely never get a chance to recompile code just to see how it behaves with the NEW code generator. You probably won't even be allowed to bring the tool on-site out of fear that it will be used and its use not discovered before product has been affected. "Are we SURE these libraries weren't compiled with that ALIEN compiler?" And, you're probably not likely to be allowed to take The Company Jewels home with you so you can test them on YOUR (uncertified) compiler: "Just to see what it says about the code" "Trust me, Mr Casino Operator, my tools didn't generate machine code that was ANY different from the code that was generated by the APPROVED compiler. Then why did I use it if the binaries are exactly the same? <shrug> I wanted to see if it produced any warnings that the other compiler didn't... Oh, you want me to PROVE that the output is identical? By running it through the APPROVED compiler for the deliverable??"
On 2016-09-11, rwood <rwoodl@nowhere.com> 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
It's a known issue with the compiler. The support team has logged it, so it may get fixed at some point. If you Google the warning, you will find many threads discussing the issue on the Microchip support forum.
On 12/09/16 16:50, Jack wrote:
> Il giorno luned&igrave; 12 settembre 2016 14:56:24 UTC+2, David Brown ha scritto: > >> compiler error. If the constant is not actually a constant, but a >> variable, you get a warning. > > not always, it depends on the compiler. >
Yes, I know. If your compiler is not good enough to catch basic errors like this, it is wise to use an additional static error checker such as PC-Lint, splint, or simply use gcc or clang for a different target (you are not interested in the output, merely the error messages and warnings). Note that you also need to know how to use your compiler, and how to enable such warnings - most will not warn much by default.
David Brown wrote:
> On 12/09/16 14:16, Mike Perkins wrote:
<snip>
> > No, it is a style recommended by people who think other people don't > understand their tools properly. >
It's a harmless, free-floating heuristic. "Free-floating" in that , as you note, there may be other mechanisms for catching this. <snip> -- Les Cargill
Am 11.09.2016 um 15:14 schrieb upsidedown@downunder.com:
> On Sun, 11 Sep 2016 13:36:59 +0200, Hans-Bernhard Br&#4294967295;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.
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++) ? 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.
> >>> 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.) 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. 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.
> 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.
> >> 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. 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. 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.
> >>> [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.
> >>> 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.
> > 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.
> >> It's simply a mistake, and I would not read it at all without mentioning >> the error. >>> >>> People reading my code never seem to have any problem understanding >>> that: >>> if ( NULL == malloc(...) ) >>> is testing for a NULL result from malloc (i.e., "malloc yielding NULL"). >> >> Certainly people will know what the code does. That does not mean it is >> the clearest choice of code for the job. > > What you care about is: > - does it do what it is intended to do > - can others "skilled in the art" understand its intent
Those are certainly important - but they are not the only criteria in judging the best way to write a piece of code.
> > 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.
> >>> [They also don't seem to find parallel loading a (hardware) counter with >>> 0 as the same as "clearing" it.] >>> >>> This sort of "reading" makes it easy to discuss: >>> (x, y) := cursor_position(); >>> ("instantiate an x,y tuple with the current cursor position") vs. >>> (x, y) = cursor_position(); >>> ("the x,y tuple gets the current cursor position") or: >>> x = cursor_X_coordinate(); >>> ("x gets the cursor's X coordinate") >>> >>> What's important is consistency. It takes very little time for >>> someone to >>> pick up on a particular style -- if it is used CONSISTENTLY throughout a >>> document/project. Ever notice code that walks an array using an index >>> into the array; then, somewhere else, a pointer into it? As if the >>> decision was arbitrary (or, made by someone other than the original >>> developer -- having a different style?) Or, that refers to screen >>> coordinates >>> as "(x,y)" in some places, "(row,column)" in others (did you notice that >>> row,column is really y,x?) and "(r,c)" in still others? >>> >>> You can read my code over the years and see the same style propagated >>> throughout (discounting changes to the language, as alluded to earlier). >>> It doesn't change when the "style du jour" comes -- and goes! -- along >>> the way! (though identifiers have lengthened as the tools have >>> supported >>> them) >> >> My code style has been fairly similar over the 20 years I have been >> professionally programming C, as the guiding principles have been >> consistent. But a number of aspects have changed over time - when a >> change of style has made sense and led to better or clearer code, I have >> made that change. And when newer and better tools or language features >> have allowed better or clearer code, then I have embraced those features >> and changes. I certainly don't believe I started my career with a >> perfect style that must be maintained for ever. > > 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. 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.
> >> 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.
> >> 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. 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.
> > 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.
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. >
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.