Hello,
how can I achieve
long l = WHAT_EVER_MACRO (-12.5); main() { printf("%X",l); }
resulting in output "0xC1480000" the binary representation of the float -12.5 . Without that MACRO the value is 0xFFFFFFF4 = -12 for integers .
Because of given circumstances in an existing project I have to store float values during initialization in long variables.
Is there any possibility?
Thanks in advance
Jürgen
use a union of unsigned long / float / double (assuming 32-bit format).
If you choose to use a union, be sure to store the _type_ of the data residing in the union alongside the data itself; there is no other way for you know which field contains valid data.
Initialize long with floats binary representation
My opinion: not possible. One option is to do source preprocessing with something other than the C preprocessor.
It's only if you have stored the float into memory that you could then take the address of the variable and typecast into a pointer to long.
While just being a numeric constant, it doesn't have any storage format so it obviously doesn't have any binary pattern.
here would be an example:
typedef union { unsigned long ul; double f; } F2UL_TYPE; ... F2UL_TYPE tmp; unsigned long tmp_ul; unsigned double tmp_f; //f to ul conversion tmp.f=32.4210; //tmp_ul has the int representation of 32.4210 send_ul(tmp.ul); //send the binary representation //ul to f conversion tmp.ul = receive_ul(); //receive the binary representation of a double type tmp_f = tmp.f; //tmp_f has a valid double value
there is no other way for you know which field contains valid data.
wouldn't your union's definition contain that information?
I don't see why you need the "type" information, and why you think it will help maintain data integrity / validity.
"My opinion: not possible."
in my example above:
F2UL_T tmp={0x00000015}; //2.942727e-044's int representation
what do you think tmp.f would be initialized to?
:)
yes, you can also initialize tmp with a double type too.
"I don't see why you need the "type" information, and why you think it will help maintain data integrity / validity."
Think about it. Storing a type field isn't meaningful when a union is used for instant assign/read out, and with the special case that the two data types in the union are expected to be same size and just represent a form of type cast.
But when data is stored in a union in one section of the code and processed in other sections, it is avery common error that a developer assumes that a union contains data of one format, while it is actually containing data of another format. A union is very often used not as type converter but to allow multiple variables to reuse the same memory space in which case it is important to know if the union contain valid data or not.
"it is avery common error that a developer assumes that a union contains data of one format, while it is actually containing data of another format."
1) it sounds like a case of human error and no amount of inclusion of "type" data can prevent developers from writing stupid code. 2) that particular case isn't relevant here.
"A union is very often used not as type converter but to allow multiple variables to reuse the same memory space in which case it is important to know if the union contain valid data or not."
I am not sure about that one. I have to confess that I rarely (never?) used union as a way to reuse space - the compiler does a better job than I do there - and I use unions extensively to as a way to shift data fast.
1) The inclusiion of a type field means that the source code can test this fieald to verify what data is there.
function get_calibration(my_union) { if (my_union.type != TYPE_CALIBRATION) return NULL; else return my_union.fancy_calibration; }
2) Irrelevant if something may not be needed in this case. People will still regularly come and revisit threads at a later time. Then it is helpful to mention the use of a 'type' field to let people remember what contents that are used in the union.
"I am not sure about that one. I have to confess that I rarely (never?) used union as a way to reuse space - the compiler does a better job than I do there - and I use unions extensively to as a way to shift data fast."
But union as type converters are still just one usage alternative.
They are quite often used in C code for abstraction, to create polymorphic objects. A device may support multiple different sensor types. So it might be useful to combine all the information into generic methods.
function get_measurement(sensor) { switch (sensor.type) { case TYPE_TEMP: sprintf(res,"%u.%u C",sensor.val.temp.value/10,sensor.val.temp.value%10); break; case TYPE_VOLT: v = sensor.val.volt.value; v += sensor.val.volt.offset; v *= sensor.val.volt.scale; if (sensor.val.volt.scale >= 1000) sprintf(res,"%u V",v); else sprintf(res,"%u.%03u V",v/1000,v%1000); break; case TYPE_ENERGY: v = sensor.val.energy.value; if (sensor.val.energy.high_gain) { v /= 10; sprintf(res,"%u.%u Ah",v/10,v%10); } else { sprintf(res,"%u2u mAh",v); } break; case TYPE_LIGHT: sprintf(res,"%u lx",normalize_to_lux(&sensor.val.light); break; default: // Unused sensor position. strcpy(res,"-"); } switch (sensor.if_type) { case IF_ONEWIRE: strcat(res,", addr:"); format_onewire_addr(res+strlen(res),sensor.addr.onewire); break; case IF_ETH: strcat(res,", addr:"); format_ip_addr(res+strlen(res),sensor.addr.ip); break; } return res; }
The original reason for unions (they exists in quite a number of languages) is for polymorphic use - not for type conversion. It's just that for low-level programming, they are very much liked as for type conversion.
"But union as type converters are still just one usage alternative."
sure.
"So it might be useful to combine all the information into generic methods."
it "might". I was just objecting to the notion that a union is very often used to share space, based on my experience.
I didn't say that it is NOT helpful to include type information in any application.
"I was just objecting to the notion that a union is very often used to share space, based on my experience."
But that would obviously depend on: - how many different types of programs you have looked at. - how many different developers who have designed the programs. - how many different types of platforms. - ...
The use of unions for polymorphic objects obviously happens more when writing object-oriented programs in C. But object-oriented programs tends to expect object pointers. And the 8051 is lousy with indexing around pointers making it a very expecnsive concept for the 8051 architecture. Lots of other architectures are great at handling pointer+offset addressing but have had to wait lots of years for a [good] C++ compiler.
"I didn't say that it is NOT helpful to include type information in any application."
So why did you write "and why you think it will help maintain data integrity / validity." instead of something like: "But in this case, the union is used as a temporary and lives for such a short time, that there is no need to flag it as used or what type that was originally assigned"?
"But that would obviously depend on:"
sure. but why is it relevant here?
"So why did you write "and why you think it will help maintain data integrity / validity.""
because I presumed that we were talking about THIS PARTICULAR case in this very discussion, not ALL cases.
maybe that's an assumption not applicable to you guys?
tmp.ul = receive_ul(); //receive the binary representation of a double type
In my opinion, this is a very dangerous way to deal with union. In this case, you are interested in the binary representation of a double - but somebody else might copy-paste this innocent looking code expecting the actual value to be in integer form. Without checking the stored data type, this is a recipe for a bug.
"somebody else might copy-paste this innocent looking code expecting the actual value to be in integer form."
I think we have gone through this multiple times by now:
1) you are right, as always;
2) that's a risk you have to take, until you have figure out a way to outlaw stupidity.
it is just impossible to write fool-proof code. whatever you write, someone somewhere will have figured out a way to mis-use your code.
stupidity is without limit, remember that next time.
thanks for such vivid discussion.
I know about the possibilities of unions but my problem is not the handling of types during run time. My problem is the initializing value.
We in fact have not this simple case of my first writing. We have an array of structure which contains among others a value for the type of value, a pointer to the value itsself and - the problem - an initializing value.
We use this construction since several years for different integer data types (8, 16, 32 bits signed and unsigned) but now it is the first time to use a float variable. This value will be passed through many function calls as a long value. It would not be a good idea to change all these function calls.
But it also is not a good idea to let the workmates compute the initializing value by hand if for example the value has to be changed from 2.31415 (0xabc) to -1.70987 (0xxyz).
Therefor my question for a computing macro or a compiler directive not to convert the float to an integer.
Is there any suggestion?
I am afraid you are right with : not possible!
greetings