Page 1 of 1
C Types and void *'s
Posted: Tue Jun 05, 2007 8:05 pm
by Alboin
A somewhat quick question:
A void * has no type. So, if I have two functions that do the same thing, but with an 8 bit character, and an 16 bit short, couldn't I just combine the two and do something like:
And then just cast to the correct type when it would be needed according to bits? Like:
Would this cause any difficulties? I just want to make sure before convert several hundred lines of code to a system like this.
Thanks.
Posted: Tue Jun 05, 2007 8:09 pm
by earlz
yea, though in most cases, you can use the largest used type and then just cast your small char to the short(or int)
course, this won't work in some cases though...
but yea, that is how I did some code for some project(might've been Open86) it was a little bit annoying though..
Posted: Tue Jun 05, 2007 8:16 pm
by Alboin
hckr83 wrote:might've been Open86
That's actually what I'm working on.
I'm kind of reorganizing some things...
Converting to the larger type seems even simpler. What problems are there?
Posted: Tue Jun 05, 2007 8:28 pm
by earlz
none _usually_ but for umm...well, it just keeps the function from knowing how many actual bits were sent..
like for the ports thing, if you just use a larger type, then some ports act differently depending on whether they get a byte or word, and that could keep the port from knowing which thing to use..
Posted: Tue Jun 05, 2007 8:38 pm
by Alboin
Oh....Well that's why I have the 'int bits' argument.
All is well,
Thanks!
Posted: Tue Jun 05, 2007 8:43 pm
by earlz
wow! you've been busy...lol 5 more commits..(I think today only) anyway..
Posted: Tue Jun 05, 2007 8:59 pm
by Alboin
hckr83 wrote:wow! you've been busy...lol 5 more commits..(I think today only) anyway..
Ahem...I would rather not talk about some of those commits.
SVN was acting up on me...Eventually I got it, but nonetheless...
I basically just rearranged some things. Switched the build system from GNU build tools to Scon, etc. I haven't committed my current SConstruct file. It's completely cross platform. (At least, as far as I know.)
That's about it. Now I'm organizing the code and making it a bit more clean, before I actually do anything major.
Posted: Tue Jun 05, 2007 10:51 pm
by Colonel Kernel
Doing what you describe is generally considered to be a Bad Idea. The more the compiler can help you by type-checking, the fewer bugs you'll have to find yourself, the hard way.
That said, it isn't really easy to write polymorphic functions in C, so I can sympathize. However, there are ways around it.
If your function always takes some kind of integer, one thing you can do is type the argument as uintptr_t (defined in C99... you might have to include stdint.h, or write your own -- I forget). It is the same size as a pointer on any architecture (e.g. -- it is 32-bits on x86 and 64-bits on x64). If you need signed integers, use intptr_t. If you don't want to cast all the time when calling the function, you can write a bunch of "front-ends" to it that each take the appropriate type and do the cast for you (this is what I do in my kernel).
You could also use macros, but you could also always gouge out your eyes with a butter knife. I'm not sure why you'd want to.
You could switch to C++ and use templates -- that's what they were invented for.
If your function is supposed to take a lot of different types that are a lot different from each other, you could always use a "discriminated union" -- that's a struct with two fields -- a union, and a type indicator that tells you what field of the union is valid.
There is actually a C API in common use today that does what you describe --
ODBC. Those of us who live and breathe it every day wish that it didn't abuse void* the way it does.
Posted: Thu Jun 07, 2007 5:18 pm
by Alboin
Okay. I just went with a few void *'s, which I then quickly abstracted. Thanks.
Somewhat related is this:
Code: Select all
typedef struct {
unsigned char high;
unsigned char low;
}bits8;
typedef union {
unsigned short bit16;
bits8 bit8;
}reg;
This emulates the 16 bit registers of x86. I was pretty excited about it. It's so elegant and peaceful. Just another solution instead of using pointers everywhere.
Toodles.
Posted: Thu Jun 07, 2007 5:30 pm
by earlz
lol..good luck changing all of those *gregs8[AL] to that....lol..find and replace is your friend!
Posted: Thu Jun 07, 2007 6:40 pm
by Alboin
Just had another idea for the void * issue.
You could use stdarg and just create a function something like:
Then, if bits is 8 you get 2 chars, and if it's 16 you get 2 shorts.
You know, there's a lot of ways to go about things in C...
Who needs templates?
Posted: Thu Jun 07, 2007 7:53 pm
by B.E
Alboin wrote:Just had another idea for the void * issue.
You could use stdarg and just create a function something like:
Then, if bits is 8 you get 2 chars, and if it's 16 you get 2 shorts.
You know, there's a lot of ways to go about things in C...
Who needs templates?
C will convert small types to bigger types for you (don't exacly know what you are tring to do thorugh). Also C will sign extend the type for you too.
so you would do something like this if signed:
Code: Select all
short add_signed(short a, short b){
return a+b;
}
the unsigned version would look like this:
Code: Select all
unsigned short add_unsigned(unsigned short a, unsigned short b){
return a+b;
}
and to use it in your code you would do the following
Code: Select all
char a,b;
char c;
short d;
short e,f;
a=b=3;
e=f=3;
// Add two bytes
c = (char)add(a,b);
// Add two 16-bit integers
d = add(e,f);
EDIT: This whole function code be a #define, i.e
Posted: Thu Jun 07, 2007 11:33 pm
by Colonel Kernel
Alboin wrote:Who needs templates?
People who appreciate the benefits of type safety.
Posted: Fri Jun 08, 2007 12:47 am
by Candy
Alboin wrote:Just had another idea for the void * issue.
You could use stdarg and just create a function something like:
Then, if bits is 8 you get 2 chars, and if it's 16 you get 2 shorts.
You know, there's a lot of ways to go about things in C...
Who needs templates?
add(10, stdout, 42); -> why this is wrong should be a compile-time error. In your case, it would very likely not even be a runtime error.