Best type for a long
Dr_Acula
Posts: 5,484
What would be the best way to work with a standard propeller long?
I've tried using a "long" and it works fine and I can input 0b11111111_11111111_11111111_11111110 and it will print FFFFFFFE in hex.
But looking through some of the example code I found "unsigned int" and also "uint32_t"
long is probably the easiest as it is the same as spin but please let me know if it would be better to use a different type of variable.
I've tried using a "long" and it works fine and I can input 0b11111111_11111111_11111111_11111110 and it will print FFFFFFFE in hex.
But looking through some of the example code I found "unsigned int" and also "uint32_t"
long is probably the easiest as it is the same as spin but please let me know if it would be better to use a different type of variable.
Comments
What is a "standard propeller long"?
Be careful, a LONG in Spin is a signed number. A LONG in PASM need not be. You will get different results some times when changing from uint32_t to int32_t in C. Clearly comparisons work differently, less clearly things like the shift right operator work differently for singed an unsigned ints.
I like to use the standard types defined in the C header file stdint.h. Like int32_t, uint8_t etc.
If you ever want to run your C functions anywhere other than the Prop it is a well to stay away from the "int" and "long" etc as they have a habit of changing size from compiler to compiler, machine to machine.
Hmm. I'm a binary sort of chap. A standard propeller long is something between %00000000_00000000_00000000_00000000 and %11111111_11111111_11111111_11111111
Of course, that might be a moot point when the 64 bit propeller comes out, but it should do for a little while yet.
WRT comparisons and rotates, I guess the best solution would be to replicate what happens in Spin as closely as possible. That should simplify translating code over to C.
Just to muddy the waters, maybe add "unsigned long" to the list as that is what I was using in Catalina.
int32_t would be best then?
Definition for int and long are the same for P8x32a propeller-gcc.
Generally you want to follow heater's advice
Typedefs like uint32_t (unsigned 32 bit integer) found in stdint.h should be used. We don't always do that in our demos though.
It's much easier to change a few typedef entries for porting than to change hundreds of lines of code. If your other compiler offers stdint.h the type is automatically ported for you.
Did you actually use the underscores as seperators? I thought I had tried than and got an error.
I know it gives an error in .s files maybe it's OK in .c files.
C.W.
The uint32_t types are a new construct for programmers that want types that are rigidly defined and very obvious, like for embedded programming. That said, a lot of existing C code doesn't use these types and the programmers assume int is 32 bits.
I don't see any problem with using long to describe a 32 bit signed variable ala SPIN.
BTW, the embedded underscore don't work in a C program. I get a compiler error if I try that.
I'm pretty sure it's a GNU extension. It's one of those promiscuous things your parents and strict C89 advocates warned you about. Once you've been there you're spoiled. Best to put #ifdef GNUC around it.
This is for SimpleIDE. I'll put some tools/build instructions on the wiki.
That makes me smile
It is all very well for the purists where hex is just fine and hex got me through until Basic Stamp/Picaxe/Propeller chips came along, but these are languages that appear to have been designed before the age of single chip microcontrollers where many times you want to map variables directly to pins. In other words, turn a led on and off. And of course you can do it in hex or decimal or octal or whatever base you want, but binary is the most visual way to describe some things like turning pins on and off, logical OR and AND, and bitshifts.
So 0b10101010 does work in GCC. I'm not sure about the underscores though. I'm actually using BCX basic (which does not have 0b1010101) but I added it because it is so useful, and then added the underscores as well because it is a feature from Spin that I really like.
I wrote an IDE for BCX Basic last night which can do a one click compile/download to SD XMM (by reverse engineering the commands the SIDE sends, building a batch file then running the batch file). Apart from one minor bug in vb.net which insists on sending a 100ms pulse to the DTR line when a com port is opened and resetting the propeller (this is apparently a 'feature') it all works fine and I have one button for 'compile to ram' and another for 'compile to eeprom'. It opens a terminal but you have to compile to eeprom to use the terminal in vb.net. However, with a touchscreen the debug can be on the screen. I wanted to do this to see how hard it was to do. In the process the BCX file goes through a couple of text preprocessor programs (like the one to fix the binary variables) and there are also some tweaks so it plays nicely with GCC. But what my IDE does not have is fast color syntax highlighting, plus it ends up a rather bloated vb.net program. I have an idea it would not be too hard to add BCX Basic to SIDE. It could exist in a separate tab, and you hit compile and it would update the C tab in the process. It could shell out to a couple of simple command line programs that input a text file and output a text file for things like the binary tweaks and any other things that might show up along the way (itoa is another). I'll keep testing a few things, but I think this opens up huge Basic programs for the propeller. And also it is a good way for Basic programmers to learn C as you can see the C program evolve as you write the Basic, and sometimes it is then easier to write inline C in the BCX basic program. You can even write the whole program as inline C if you want. The C89 purists will probably be getting out the flaming brands and pitchforks by now!
Actually: long is at least 32 bits, but could be more. short is at least 16 bits, but could be more. The size of char is not defined, but is typically 8 bits. long and short are signed, char is signed or unsigned depending on the compiler.
Why should you care? If you're writing code only for the Propeller and promise yourself you'll never port it, then don't worry about it - get your program to work then kick back and have a beer to celebrate.
However, if you ever want to port your code to a different chip and/or compiler, then the esoteric issues regarding actual length (vs minimum length) and the signed/unsigned nature of each of the "standard" types (int, long, short, char) will matter greatly - there are all kinds of porting bugs out there just waiting to happen to you.
On the other hand, if you use int32_t, uint32_t, int16_t, uint16_t, int8_t, uint8_t, and are very careful about how you use casts, then you can largely avoid bunches of potential porting bugs with very little work on your part.
I've added information on building SimpleIDE from source here: http://code.google.com/p/propside/wiki/BuildingSimpleIDE
Thanks,
--Steve
I'm somwhat against the idea of a BASIC IDE bolted into SimpleIDE. After all it is supposed to be simple. Once we have thrown in BASIC and Spin and Forth and whatever we might as well use Eclipse.
The bigger issue is that a subsystem or module or plugin like that written in VB is a non-starter as it is not cross platform and it is not open source.
Perhaps if you would implement your IDE in C++ using the Qt libs as SimpleIDE is it might become a contender.
Qt has some nice edit widgets with syntax highlighting support.
You are correct, however the convention has been, char, short, long, and long long.
I think ANY TYPE of IDE for an embedded Forth would be IMPOSSIBLE!!
Dang, and there I was half done ...
Not really. And I suspect that is not quite what you meant. We have to be more rigorous:
In twos complement representation as used by Spin
The binary %00000000_00000000_00000000_00000000 is the representation of zero (0)
That %11111111_11111111_11111111_11111111 is the representation of minus one (-1)
So your statement becomes "A standard propeller long is something between zero and minus one" which would not be very useful if true. (By the way, I could go on and say there are no values between zero and minus one in this representation so the statement gets even more meaningless).
In twos comp the top bit is regarded as the sign bit and the rest as the value (sort of) the lowest value is
-2^31 or %10000000_00000000_00000000_00000000 or -2147483648
The highest value is:
+2^31 - 1 or %01111111_11111111_11111111_11111111 or 2147483647
Note that this is not symmetrical around zero. There are more negative numbers. That's because there is no -0.
You cannot just set the top bit of the value zero and turn it into minus zero.
Or indeed you cannot set the top bit of any positive number and turn it into it's negative counterpart. Hence my "sort of" above.
I'll leave it for you to google how to negate in twos comp.
Now, a gotcha here is that if you shift a signed two's comp number right, the sign will be preserved in the result so shifting a negative number may not give what you expect. For negative numbers one's will be filling up the top end. Had you declared it unsigned there is no sign to preserve and zeros are shifted into the top end.
That is why I like to think in binary - to avoid that sort of confusion. My first processor was 8 bit so -1 to me is binary %11111111, not %11111111_11111111_11111111_11111111.
As I moved to bigger processors, and every processor (8, 16, 32 bit) defined -1 as the biggest number that processor could represent, I decided none of them were right and started trying to avoid -1 altogether in code. I tend to use binary if working with bitbanging, and or hex. So where someone might write "if a == -1" I would write "if a == 0xFFFFFFFF". Just my personal preference though.
I tend to only use negative numbers when working with floating point variables.
For the C variable type, uint32_t seems the least ambiguous. It is unsigned and 32 bits.
heater said
Excellent advice there. And programs may well be run on other compilers - eg in the IDE I'm using I've got TinyC added which is very handy for a quick test that a function does what it is meant to.