We are running a survey to help us improve the experience for all of our members. If you see the survey appear, please take the time to tell us about your experience if you can.
Hi all Below is the result of some debugging. I have isolated some code from a bigger project and have put it into a stand-alone project.
I basically don't understand why I can do right bit-shifting and AND'ing on single line, when I can't do left bit-shifting and AND'ing on single line.
If it isn't a bug, then what have I missed?
I have included many comments to describe my problem
#include <ADUC832.H> #include <string.h> void main(void) { char ascii[] = "MC"; unsigned char pdu[3]; int w=0, r=0, len; char ch1, ch2, rr, rl; /* This is what I want to do: while-loop run 1: 1: Assign to var 'ch1': ch1 = 'M' (= 0x4D = 0100 1101) 2: Assign to var 'ch2': ch2 = 'C' (= 0x43 = 0100 0011) 3: Assign to var 'w' : w = 0 4: OR together the following: ((ch1 >>(w%7))&0x7F) | ((ch2 <<(7-(w%7)))&0xFF); <=> 0100 1101 | 1000 0000 <=> 1100 1101 <=> 0xCD while-loop run 2: 1: Assign to var 'ch1': ch1 = 'C' (= 0x43 = 0100 0011) 2: Assign to var 'ch2': ch2 = 0x00 3: Assign to var 'w' : w = 1 4: OR together the following: ((ch1 >>(w%7))&0x7F) | ((ch2 <<(7-(w%7)))&0xFF); <=> 0010 0001 | 0000 0000 <=> 0010 0001 <=> 0x21 */ len=strlen(ascii); while (r<len) { // ------ First OR-part ----------------------- // -------Both versions below are OK ---------- // -- VER 1: OK // ch1 = ascii[r]; // rr = (w%7); // ch1 = (ch1 >> rr) & 0x7F; // -- VER 2: OK ch1 = (ascii[r] >> (w%7)) & 0x7F; // Bit-shifting and AND'ing // may be done in one line // ------ Second OR-part ----------------------------- //------- Both versions below are NOT OK ?? ---------- // -- VER 1: OK ch2 = ascii[r+1]; rl = (7-(w%7)); ch2 = (ch2 << rl) & ((char)0xFF); // Bit shift and AND'ing can be // done in one line, IF type cast // is used - why? // ch2 = ch2 & 0xFF; // If splitting into new line // type cast is not required? // -- VER 2: NOT OK // ch2 = (ascii[r+1] << (7-(w%7))) & 0xFF; // type cast doesn't help // ch2 = ch2 & 0xFF; // AND'ing must be on seperate line ? //---------------------------------------------------------------- // IS THIS A BUG ?? //---------------------------------------------------------------- // Why can we bit-shift and do the AND'ing in a single line // for the first OR-part above, but cannot do it for the second // OR-part where bit-shifting and AND'ing must be on two seperate // lines ??? //---------------------------------------------------------------- // ------ Do the actual OR'ing ------- pdu[w]= (ch1 | ch2) ; if ((w%7)==6) r++; r++; w++; } pdu[w]=0; // terminator //---------------------------------------------------------------- // Run to here in debugger and look at content of // local variable 'pdu'. // When using 'NOT OK' versions from above // pdu will contain {0x4D, 0x21, 0x00} // and not {0xCD, 0x21, 0x00} as the 'OK' versions // produce. //---------------------------------------------------------------- while(1); }
It is a bit dangerous to look at the assembler output and use that as the definition of "bug-free". No argument with that. However, if you have doubts about a construct, looking at the assembler can often alleviate your doubts. Would I recommend that method as a general modus operandi, of course not. However, I only run into uncharted waters (what will this do?) about once or twice a year (contradicting Jack, I am, actually, quite proficient in C) and when I have no idea about what keyword to look for in the manuals, it can be quite helpful to look at the assembler generated.
It may only be used to check for "expected" behaviour. The C standard mentions a number of implementation-specific behaviour, where great care is needed. The next version of a compiler may change it's behaviour, generating "buggy" - or actually unexpected (by the developer) - instruction sequences without being wrong. The original bug (or incorrect assumption) in the source code is woken, and the application stops behaving as expected. exactly, and for that reason, looking at the assembler should not be the primary source of information, but on a rare occasion of doubt and no "keyword knowledge" it is way better than nothing.
Erik
PS to Jack; if you suggest that in such a case one should read the manual from beginning to end to find the applicable, you must be a raw amateur to have that much time on hand.
However, I only run into uncharted waters (what will this do?) about once or twice a year (contradicting Jack, I am, actually, quite proficient in C) and when I have no idea about what keyword to look for in the manuals, it can be quite helpful to look at the assembler generated.
I'm curious. If you don't know what keyword to look up in the manual, how do manage to type it in, compile it and look at the assembler output?
I'm curious. If you don't know what keyword to look up in the manual, how do manage to type it in, compile it and look at the assembler output? have you sever typed "integer promotion" in a program?
have you sever typed "integer promotion" in a program?
No, that would be silly. 'integer promotion' is not a keyword.
What's your point?
You said If you don't know what keyword to look up in the manual, how do manage to type it in, compile it and look at the assembler output?
As an example, if the problem is 'integer promotion' and someone, while being fully aware of the concept has no idea what it is called, how do you suggest they "look it up in the manual". As an example, it is possible to Oh, now I get it: stop working for a couple of days and study K&R, their boss will appreciate that.
As an example, if the problem is 'integer promotion' and someone, while being fully aware of the concept has no idea what it is called, how do you suggest they "look it up in the manual".
The example you posted shows that you are not aware of the concept. I would have thought that after 15 years of using 'C' you would have taken the time to learn the basics.
Oh, now I get it: stop working for a couple of days and study K&R, their boss will appreciate that.
Learning how to use the tools of your trade is part of the job. Do you really work for a company that prefers you to 'have a go' rather than read the documentation?
The example you posted shows that you are not aware of the concept. I would have thought that after 15 years of using 'C' you would have taken the time to learn the basics. bullshit, horsefeathers and whatever.. I am very much aware of the concept, that I may not have 'perfect understanding' of a limitation is another issue.
Were I "not aware of the concept", how come that my first change was inserting a typecast?
Of course, you NEVER run into such an issue
Learning how to use the tools of your trade is part of the job. now you are just way too crappy. I know very well "how to use the tools", that I prefer to write understandable instead of Cidiotic code, has nothing to do with that.
Now, explain to mme how someone that "do not know how to use the tools" would immediately insert a typecast when something gave the wrong result.
The problem is that you did not understand why the cast was necessary. You assumed it was an 'inconsistency' in the compiler behaviour and reported it to Keil.
Of course I do. When I do I consult the documentation to understand why I am experiencing the issue and modify my code accordingly. I don't just chuck in a cast and conclude that I've found an 'inconsistency'.
I know very well "how to use the tools", that I prefer to write understandable instead of Cidiotic code, has nothing to do with that.
You keep demonstrating that you do not in fact understand the tools. It is most commendable that you write understandable code but you would be well advised to read the manual and learn how to write correct code.