By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
459,510 Members | 1,141 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 459,510 IT Pros & Developers. It's quick & easy.

Polymorphism in C (very basic)

P: n/a
Greetings,

I have an array of 32 values. This makes it extremely fast to access
elements in this array based on an index provided by a separate enum. This
array is defined of type "unsigned long int". I have a typedef for this:

typedef unsigned long int Uint32;
typedef float Float32;
Uint32 myArray[100];

In C++ there are casting operators, however I'm writing my software in C.
I'm trying to tell the compiler to interpret a value as a float (32-bit
entity on this platform), but store it into the Uint32 array, which I later
take and convert back to float. (I don't want to have type promotion or
demotion, just have the compiler change its interpretation of the type).

This can be easily done by

Uint32 u32;
Float32 f32;

f32=3.1415;
u32 = *(Uint32 *)(&f32);

So now, if you print u32 to the console it will print what looks like
garbage (definitely not the number 3), but the binary representation remains
the same.

The same could be done also with Union structs (but the above is nicer I
think).

But for readability I would like to combine all this into something that
appears on one line without having to first put the number into a variable
or register, so that:

u32 = ConvertToFloat(3.14159);

I don't want to write a function - the overhead is high and I now need to
put this function in a library that will need to be linked (this is being
used by multiple binaries, somewhat like a "plugin" architecture). Also,
it's dependent on the compiler if such a function would be inline'd or not
(C doesn't provide inline as far as I know, and I still want everything in a
header file if possible). It would be convenient to have a macro in a header
file that could do this.

Does anyone know how to write such a macro?

Is there something that can be written in assembly for Microsoft Visual C++?
I don't know anything about Intel Assembly.

The other alternative I can think is an array of 32-bit values that derives
its type from something I explicitly set it to.
Nov 14 '05 #1
Share this Question
Share on Google+
10 Replies


P: n/a

On Thu, 8 Jul 2004, Jason Curl wrote:

typedef unsigned long int Uint32;
typedef float Float32;
Uint32 myArray[100];

In C++ there are casting operators, however I'm writing my software in C.
C has type-casting operators, too; there just aren't as many of them
and they aren't as ugly. :)
I'm trying to tell the compiler to interpret a value as a float (32-bit
entity on this platform), but store it into the Uint32 array, which I later
take and convert back to float. (I don't want to have type promotion or
demotion, just have the compiler change its interpretation of the type). The same could be done also with Union structs (but the above is nicer I
think).
Much less portable, though. For that matter, why are you using an
array of *integers* to store *float* values?! Just use an array of
floats! It's not like there's a penalty for it!
But for readability I would like to combine all this into something that
appears on one line without having to first put the number into a variable
or register, so that:

u32 = ConvertToFloat(3.14159);
*(Float32*)u32 = 3.14159;

or the obvious macro-ization of the above.
I don't want to write a function - the overhead is high and I now need to
put this function in a library that will need to be linked (this is being
used by multiple binaries, somewhat like a "plugin" architecture). Also,
it's dependent on the compiler if such a function would be inline'd or not
(C doesn't provide inline as far as I know, and I still want everything in a
header file if possible). It would be convenient to have a macro in a header
file that could do this.
C99 provides the 'inline' keyword; in C90 you can write

#ifndef CNVT2FLOAT
#define CNVT2FLOAT
static Uint32 Cnvt2Float(Float32 f) { return *(Uint32*)&f; }
#endif

The other alternative I can think is an array of 32-bit values that derives
its type from something I explicitly set it to.


This statement doesn't make sense to me. What are you *really* trying
to do, and why? Certainly there's no practical reason to use 'Uint32'
instead of 'Float32' in your code; you can even see already that trying
to use the wrong type makes the rest of your code a pain to write.
This is C's way of telling you you're headed in the wrong direction.

-Arthur

Nov 14 '05 #2

P: n/a
On 2004-07-08, Arthur J. O'Dwyer <aj*@nospam.andrew.cmu.edu> wrote:
On Thu, 8 Jul 2004, Jason Curl wrote:

typedef unsigned long int Uint32;
typedef float Float32;
Uint32 myArray[100];

u32 = ConvertToFloat(3.14159);


*(Float32*)u32 = 3.14159;


Nit:
*(Float32*)&u32 = 3.14159;

-- James
Nov 14 '05 #3

P: n/a

"Jason Curl" <j.****@motorola.com> wrote in message
news:cc**********@newshost.mot.com...
Greetings,

I have an array of 32 values. This makes it extremely fast to access
elements in this array based on an index provided by a separate enum. This
array is defined of type "unsigned long int". I have a typedef for this:

typedef unsigned long int Uint32;
typedef float Float32;
Uint32 myArray[100];

In C++ there are casting operators, however I'm writing my software in C.
I'm trying to tell the compiler to interpret a value as a float (32-bit
entity on this platform), but store it into the Uint32 array, which I later take and convert back to float. (I don't want to have type promotion or
demotion, just have the compiler change its interpretation of the type).

This can be easily done by

Uint32 u32;
Float32 f32;

f32=3.1415;
u32 = *(Uint32 *)(&f32);

So now, if you print u32 to the console it will print what looks like
garbage (definitely not the number 3), but the binary representation remains the same.

The same could be done also with Union structs (but the above is nicer I
think).

But for readability I would like to combine all this into something that
appears on one line without having to first put the number into a variable
or register, so that:

u32 = ConvertToFloat(3.14159);

I don't want to write a function - the overhead is high and I now need to
put this function in a library that will need to be linked (this is being
used by multiple binaries, somewhat like a "plugin" architecture). Also,
it's dependent on the compiler if such a function would be inline'd or not
(C doesn't provide inline as far as I know, and I still want everything in a header file if possible). It would be convenient to have a macro in a header file that could do this.

Does anyone know how to write such a macro?

Is there something that can be written in assembly for Microsoft Visual C++? I don't know anything about Intel Assembly.

The other alternative I can think is an array of 32-bit values that derives its type from something I explicitly set it to.


What in the world does this have to do with polymorphism?
Nov 14 '05 #4

P: n/a

On Thu, 8 Jul 2004, James Hu wrote:

On 2004-07-08, Arthur J. O'Dwyer <aj*@nospam.andrew.cmu.edu> wrote:

*(Float32*)u32 = 3.14159;


Nit:
*(Float32*)&u32 = 3.14159;


Whoops... Good catch! Especially considering the context... if the
OP thought it was a good idea to coerce floats to ints, he might not
have thought anything unusual about converting an int to a pointer!

Thanks,
-Arthur

Nov 14 '05 #5

P: n/a
On Thu, 8 Jul 2004 15:26:12 +0200, "Jason Curl" <j.****@motorola.com>
wrote:
Greetings,

I have an array of 32 values. This makes it extremely fast to access
elements in this array based on an index provided by a separate enum. This
array is defined of type "unsigned long int". I have a typedef for this:

typedef unsigned long int Uint32;
typedef float Float32;
Uint32 myArray[100];

In C++ there are casting operators, however I'm writing my software in C.
I'm trying to tell the compiler to interpret a value as a float (32-bit
entity on this platform), but store it into the Uint32 array, which I later
take and convert back to float. (I don't want to have type promotion or
demotion, just have the compiler change its interpretation of the type).

This can be easily done by

Uint32 u32;
Float32 f32;

f32=3.1415;
u32 = *(Uint32 *)(&f32);

So now, if you print u32 to the console it will print what looks like
garbage (definitely not the number 3), but the binary representation remains
the same.

The same could be done also with Union structs (but the above is nicer I
think).

But for readability I would like to combine all this into something that
appears on one line without having to first put the number into a variable
or register, so that:

u32 = ConvertToFloat(3.14159);

I don't want to write a function - the overhead is high and I now need to
put this function in a library that will need to be linked (this is being
used by multiple binaries, somewhat like a "plugin" architecture). Also,
it's dependent on the compiler if such a function would be inline'd or not
(C doesn't provide inline as far as I know, and I still want everything in a
header file if possible). It would be convenient to have a macro in a header
file that could do this.

Does anyone know how to write such a macro?

Is there something that can be written in assembly for Microsoft Visual C++?
I don't know anything about Intel Assembly.

The other alternative I can think is an array of 32-bit values that derives
its type from something I explicitly set it to.


Is there some reason memcpy won't do what you want?

<<Remove the del for email>>
Nov 14 '05 #6

P: n/a
Jason Curl wrote:
Greetings,

I have an array of 32 values. This makes it extremely fast to access
elements in this array based on an index provided by a separate enum. This
array is defined of type "unsigned long int". I have a typedef for this:

typedef unsigned long int Uint32;
typedef float Float32;
Uint32 myArray[100];

In C++ there are casting operators, however I'm writing my software in C.
I'm trying to tell the compiler to interpret a value as a float (32-bit
entity on this platform), but store it into the Uint32 array, which I later
take and convert back to float. (I don't want to have type promotion or
demotion, just have the compiler change its interpretation of the type).


Why not :

union {
float float32;
unsigned long int array[100];
} x;

In this case, there is no need for typecast, hacks or other nasty things.

Igmar
Nov 14 '05 #7

P: n/a
Thanks everybody.

The form used here [*(Float32*)&u32 = 3.14159;] is what I use now.

But for all your curiosity, why am I doing this? I've used C for quite some
time and mostly on embedded systems. This is a kind of flight recorder,
where the data being recorded may change, but the number of data elements to
record is fixed.

The array of Uint32's allows me to define a block of memory that is
allocated at compile time. The index to the array provides a very fast way
to access that index. The datatype isn't important, except for how much
space it takes up, and all of my data is 32-bits or less. Where I need a
string, it's a pointer to another general memory space that contains the
string. However, the most common datatype being used is a Uint32.

So it means I don't use "malloc" on initialisation. It also means in 80% of
the cases I don't need to do type conversions of this sort because the
datatypes are already in some integer form. It also means that components
can access the number of elements, perform a run-time function call to know
how to interpret the data. I can add to the number of elements in one small
area that collects it. Other components can use a small portion that they
need, or they can use everything. This is useful for realtime analysis of
incoming data, as well as storage (where the storage mechanism doesn't need
to know what the datatypes are). Hence, the point of the title, some basic
form of polymorphism in C.

I have a separate array that defines the datatype and it is used to
interpret the datatype at runtime for third party components.

I didn't want to have a solution using a Union construct, as when
initialising this array it means I first need to write to a temporary
variable and then copy that either using memcpy, union structs, or
typecasts. I simply wanted the compiler to take a float, without type
promotion or demotion and store it. Why not have one ASM instruction, than
have three?

The other solution I did think about was to have three arrays of a union
construct, one array of 100 Uint32's, another of 100 Float32's and the third
of 100 char ptrs. From there I could simply access the one I wanted.

Based on the comments it might be the better way to go. But type conversions
would still need to be made for assigning variables of different sizes (e.g.
Int16), especially when extracting the information from the array.

And the comment about the last part? Well..... Now you might know how I
intend to use the data and what it's for.

Cheers,

Jason.

"Arthur J. O'Dwyer" <aj*@nospam.andrew.cmu.edu> wrote in message
news:Pi**********************************@unix44.a ndrew.cmu.edu...

On Thu, 8 Jul 2004, James Hu wrote:

On 2004-07-08, Arthur J. O'Dwyer <aj*@nospam.andrew.cmu.edu> wrote:

*(Float32*)u32 = 3.14159;


Nit:
*(Float32*)&u32 = 3.14159;


Whoops... Good catch! Especially considering the context... if the
OP thought it was a good idea to coerce floats to ints, he might not
have thought anything unusual about converting an int to a pointer!

Thanks,
-Arthur

Nov 14 '05 #8

P: n/a

On Fri, 9 Jul 2004, Jason Curl wrote:

But for all your curiosity, why am I doing this? I've used C for quite some
time and mostly on embedded systems. This is a kind of flight recorder,
where the data being recorded may change, but the number of data elements to
record is fixed.
And by "data elements" you mean... objects (i.e., more or fewer bytes
of data depending on object size)? Bytes of data (i.e., more or fewer
chunks of data depending on chunk size)? Something else?
The array of Uint32's allows me to define a block of memory that is
allocated at compile time. The index to the array provides a very fast way
to access that index.
Oh, stop saying that already! Usenet posts aren't funding proposals;
there's no need to pretend that Obvious Method #1 is a "very fast way"
to do Trivial Thing #7. Besides, from the clc standpoint, nothing is
necessarily "very fast" --- how do *we* know what kind of code your
compiler generates? (And more to the point, how do *you* know what kind
of code *our* compilers generate?)

More usefully, I would strongly recommend the use of an array of
'unsigned char' rather than 'unsigned int'. It's a more direct tip-off
to the maintainer that you're doing evil things with bits and bytes.
Also, 'sizeof (unsigned char)' is always exactly 1, which will help you
immensely in getting an accurate size for your buffer.
So it means I don't use "malloc" on initialisation. It also means in 80% of
the cases I don't need to do type conversions of this sort because the
datatypes are already in some integer form.
Type conversions are source-level constructs, generally speaking.
In your case, they certainly don't add any code to the executable. So
it's just a readability concern --- and IMHO you ought to be using a
few cleverly-designed macros for readability and consistency anyway.
Hence, the point of the title, some basic
form of polymorphism in C.
Nothing to do with polymorphism. Trust me. :) But it sounds an
awful lot like "serialization"; you might Google up some references
on that topic, if you have the time to spare. (Probably won't help
you code it, but probably will give you a better idea of what you're
probably *trying* to code.)
I didn't want to have a solution using a Union construct, as when
initialising this array it means I first need to write to a temporary
variable and then copy that either using memcpy, union structs, or
typecasts. I simply wanted the compiler to take a float, without type
promotion or demotion and store it. Why not have one ASM instruction, than
have three?
Use gcc, which is very smart about memcpy and friends. (Possibly
other common compilers are smart too, but I recently had cause to
play with gcc's memcpy-vs-for-loop optimization in this newsgroup. ;)
IOW, don't worry about efficiency. Cf. "First Rule of Optimization."
And the comment about the last part? Well..... Now you might know how I
intend to use the data and what it's for.


If it's not too long, try posting an example of how you intend to
*use* the subroutines you're writing. For example:

BlackBox_clear();
BlackBox_addF(3.14159);
BlackBox_addI(6);
BlackBox_addS("times");
BlackBox_addI(9);
BlackBox_addI(42);
BlackBox_dump();

If this is what you're looking at, then you might write the functions
as follows [COMPLETELY UNTESTED CODE]:

static unsigned char BB_buffer[1000];
static size_t BB_idx = 0;
static char BB_types[1000];
static size_t BB_tdx = 0;

void BlackBox_clear(void)
{ BB_idx = BB_tdx = 0; }

#define BlackBox_add(c, t) \
void BlackBox_add##c(t value) { \
memcpy(BB_buffer+BB_idx, &value, sizeof value); \
BB_idx += sizeof value; \
BB_types[BB_tdx++] = #c [0]; \
}

BlackBox_add(I, int)
BlackBox_add(F, float)
#undef BlackBox_add

void BlackBox_addS(const char *value) {
size_t n = strlen(value)+1;
memcpy(BB_buffer+BB_idx, value, n);
BB_idx += n;
BB_types[BB_tdx++] = 'S';
}

void BlackBox_dump(void)
{
int i, j=0;
for (i=0; i < BB_tdx; ++i) {
switch(BB_types[i]) {
case 'I': {
int value; memcpy(&value, BB_buffer+j, sizeof value);
printf("int, value %d\n", value);
j += sizeof value;
}
case 'F': {
float value; memcpy(&value, BB_buffer+j, sizeof value);
printf("int, value %g\n", value);
j += sizeof value;
}
case 'S': {
printf("string, value '%s'\n", BB_buffer+j);
j = strchr(BB_buffer+j, '\0')-BB_buffer + 1;
}
}
}
}
.... A long example, but I think you get the idea.

HTH,
-Arthur
Nov 14 '05 #9

P: n/a
Thanks Arthur,

When I mentioned "Black Box", it wasn't quite exactly. Rephrasing, I think
logger might be better.

GPS data comes in once per second. In the background are various
measurements. There are about 60 measurements in total. An enum defines the
different measurements. In an OO implementation it might be an object that
has 60 properties, accessed by index. There are another 60 properties
associated with the measurements to indicated "Aged" or not.

Every time a GPS update arrives, an event is fired. Other processes get
notified. They can access one of the properties.

So,

#define CP_FLOAT32_UINT32(f32) (*((Uint32 *)(&(f32))))
#define CP_UINT32_FLOAT32(u32) (*((Float32 *)(&(u32))))

typedef enum {
PROPERTY1,
PROPERTY2,
....
PROPERTY_GPSALT,
PROPERTY_GPSSPEED,
NUM_PROPERTIES
} Properties;

typedef struct {
Uint32 Data[NUM_PROPERTIES];
Bool Aged[NUM_PROPERTIES];
} Block;

Block foo;

->Initialisation: (this is why I asked the question).
CP_UINT32_FLOAT32(foo.Data[PROPERTY_GPSALT]) = 0.0;

-> In the background data arrives from another thread (all the mutex's are
not here). Maybe from multiple threads.
foo.Data[PROPERTYn] = value1;
foo.Aged[PROPERTYn] = FALSE;

->When GPS data arrives (I'm using regular expressions to parse the data)
float altitude;
altitude = (float)atof(matchv[1]);
foo.Data[PROPERTY_GPSALT] = CP_FLOAT32_UINT32(altitude);
(void)NotifyGpsEvent();

-> Then other modules (configured at compile time, to turn on or off
features) would get the event. One of these modules would write it to Flash
memory.

At the moment it's a concept, and I'm trying to figure out the best way. See
also my other comments embedded. I suspect that's pretty much it. Any more
would be deviating from C?
"Arthur J. O'Dwyer" <aj*@nospam.andrew.cmu.edu> wrote in message
news:Pi**********************************@unix45.a ndrew.cmu.edu...

On Fri, 9 Jul 2004, Jason Curl wrote:

But for all your curiosity, why am I doing this? I've used C for quite some time and mostly on embedded systems. This is a kind of flight recorder,
where the data being recorded may change, but the number of data elements to record is fixed.
And by "data elements" you mean... objects (i.e., more or fewer bytes
of data depending on object size)? Bytes of data (i.e., more or fewer
chunks of data depending on chunk size)? Something else?


Yes, objects that may be of variable sizes, but generally simple objects
(except the string). Each object is not more than 32-bits.
The array of Uint32's allows me to define a block of memory that is
allocated at compile time. The index to the array provides a very fast way to access that index.
Oh, stop saying that already! Usenet posts aren't funding proposals;
there's no need to pretend that Obvious Method #1 is a "very fast way"
to do Trivial Thing #7. Besides, from the clc standpoint, nothing is
necessarily "very fast" --- how do *we* know what kind of code your
compiler generates? (And more to the point, how do *you* know what kind
of code *our* compilers generate?)


Thanks for the input. Would it be wrong to assume how compilers access
elements in an array? Maybe I wasn't clear in how that array is being used.
I align the datatypes on 32-bit boundaries so that it is simple and fast to
access the elements. But enough of that topic. I understand there are other
ways I haven't thought of that might be as efficient, simpler and quicker.

More usefully, I would strongly recommend the use of an array of
'unsigned char' rather than 'unsigned int'. It's a more direct tip-off
to the maintainer that you're doing evil things with bits and bytes.
Also, 'sizeof (unsigned char)' is always exactly 1, which will help you
immensely in getting an accurate size for your buffer.
So it means I don't use "malloc" on initialisation. It also means in 80% of the cases I don't need to do type conversions of this sort because the
datatypes are already in some integer form.
Type conversions are source-level constructs, generally speaking.
In your case, they certainly don't add any code to the executable. So
it's just a readability concern --- and IMHO you ought to be using a
few cleverly-designed macros for readability and consistency anyway.
Hence, the point of the title, some basic
form of polymorphism in C.


Nothing to do with polymorphism. Trust me. :) But it sounds an
awful lot like "serialization"; you might Google up some references
on that topic, if you have the time to spare. (Probably won't help
you code it, but probably will give you a better idea of what you're
probably *trying* to code.)


You're right. I just wanted an array where the datatypes are not all the
same. It's serialization.
I didn't want to have a solution using a Union construct, as when
initialising this array it means I first need to write to a temporary
variable and then copy that either using memcpy, union structs, or
typecasts. I simply wanted the compiler to take a float, without type
promotion or demotion and store it. Why not have one ASM instruction, than have three?
Use gcc, which is very smart about memcpy and friends. (Possibly
other common compilers are smart too, but I recently had cause to
play with gcc's memcpy-vs-for-loop optimization in this newsgroup. ;)
IOW, don't worry about efficiency. Cf. "First Rule of Optimization."
And the comment about the last part? Well..... Now you might know how I
intend to use the data and what it's for.


If it's not too long, try posting an example of how you intend to
*use* the subroutines you're writing. For example:

BlackBox_clear();
BlackBox_addF(3.14159);
BlackBox_addI(6);
BlackBox_addS("times");
BlackBox_addI(9);
BlackBox_addI(42);
BlackBox_dump();

If this is what you're looking at, then you might write the functions
as follows [COMPLETELY UNTESTED CODE]:

static unsigned char BB_buffer[1000];
static size_t BB_idx = 0;
static char BB_types[1000];
static size_t BB_tdx = 0;

void BlackBox_clear(void)
{ BB_idx = BB_tdx = 0; }

#define BlackBox_add(c, t) \
void BlackBox_add##c(t value) { \
memcpy(BB_buffer+BB_idx, &value, sizeof value); \
BB_idx += sizeof value; \
BB_types[BB_tdx++] = #c [0]; \
}

BlackBox_add(I, int)
BlackBox_add(F, float)
#undef BlackBox_add

void BlackBox_addS(const char *value) {
size_t n = strlen(value)+1;
memcpy(BB_buffer+BB_idx, value, n);
BB_idx += n;
BB_types[BB_tdx++] = 'S';
}

void BlackBox_dump(void)
{
int i, j=0;
for (i=0; i < BB_tdx; ++i) {
switch(BB_types[i]) {
case 'I': {
int value; memcpy(&value, BB_buffer+j, sizeof value);
printf("int, value %d\n", value);
j += sizeof value;
}
case 'F': {
float value; memcpy(&value, BB_buffer+j, sizeof

value); printf("int, value %g\n", value);
j += sizeof value;
}
case 'S': {
printf("string, value '%s'\n", BB_buffer+j);
j = strchr(BB_buffer+j, '\0')-BB_buffer + 1;
}
}
}
}
... A long example, but I think you get the idea.

HTH,
-Arthur

Nov 14 '05 #10

P: n/a
>Jason Curl wrote:
I have an array of 32[-bit] values. This makes it extremely fast to access
elements in this array based on an index provided by a separate enum. ...

(into which he wants to store data of various types, none of which
will be longer than 32 bits, or so he believes :-) ).

In article <40***********************@news.xs4all.nl>
Igmar Palsenberg <ig***@non-existant.local> writes:Why not :

union {
float float32;
unsigned long int array[100];
} x;

In this case, there is no need for typecast, hacks or other nasty things.


While a union *is* clearly the correct approach -- given my assumptions
about the technique he is using -- this is not quite the right one.
The "right one" is this:

union array_element {
float f;
unsigned long ul;
unsigned short us;
char c;
int i;
/* add more as needed */
};

union array_element array[SIZE];
...
array[i].f = floatval;
... "i" gets incremented mod SIZE but call this j: ...
array[j].us = ushortval;
...

and there is some kind of magic (most likely, a second, parallel array)
by which the system "remembers" that array[i] holds a "float" while
array[j] holds an "unsigned short".

Not only does this remove all the dodgy cast code, it even works
if for some strange reason an "unsigned short" happens to be *8*
8-bit bytes long, instead of the "expected" 2. The array simply
takes up twice as much memory, of which only 32 bits are used when
storing (32-bit) floats, and so on. The array is always sized
to be "big enough" to store the maximally-sized element.
--
In-Real-Life: Chris Torek, Wind River Systems
Salt Lake City, UT, USA (4039.22'N, 11150.29'W) +1 801 277 2603
email: forget about it http://web.torek.net/torek/index.html
Reading email is like searching for food in the garbage, thanks to spammers.
Nov 14 '05 #11

This discussion thread is closed

Replies have been disabled for this discussion.