C Beginner Question

C

Cao Tran

How do I pass different types of argument such as short, int, long,
etc.. to a function that does routine stuff?

Example:

int main()
{
short x=1;
int y =1;
long z=1

bit_count(x);
bit_count(y);
bit_coutn(z);

return 0;
}

/* how to declare a function to accept different types of argument */

int bit_count()
{
int count=0;

while (x!=0)
{
printf("count = %d and value of x = %d\n", count++, x);
x<<=1;
}
return 0;
}

thanks
 
M

Mark A. Odell

(e-mail address removed) (Cao Tran) wrote in
How do I pass different types of argument such as short, int, long,
etc.. to a function that does routine stuff?

Pass in a type argument or in this simple case define bit_count() to take a
long as its argument. Then C will promote short and int types to long in
the call to bit_count(). This won't work if you have complex types like
structs or unions.
Example:

int main() int main(void)
{
short x=1;
int y =1;
long z=1

bit_count(x);
bit_count(y);
bit_coutn(z);

return 0;
}

/* how to declare a function to accept different types of argument */

See above.
 
D

Default User

Cao said:
How do I pass different types of argument such as short, int, long,
etc.. to a function that does routine stuff?

Example:

int main()
{
short x=1;
int y =1;
long z=1

bit_count(x);
bit_count(y);
bit_coutn(z);

return 0;
}

There's no way to achieve this exactly. Solutions to generic functions
require either use of void*, union, or a variadic function. In any of
those cases, you'll have to tell the receiving function what kind of
variable you are passing.

An example is printf(). The first argument flags the expected types of
the following arguments.



Brian
 
D

Derrick Coetzee

Cao said:
How do I pass different types of argument such as short, int, long,
etc.. to a function that does routine stuff?

In this case you can take advantage of promotions by making the argument
a long int, so that any integral type will be accepted. Similarly, you
can use doubles for arguments that should accept any floating-point type.

In general though, the ability to write one piece of code and then use
it for many different types is a feature called *generics* that C does
not support. C++ supports these in the form of templates, and upcoming
versions of Java and C# support them. It is often possible, however, to
do one of the following:

1. Write C code that works on several types by passing a void pointer to
the object along with a type identifier:

void DoGenericThing(void* object, enum typeID) {
switch(typeID) {
case TypeShape: { Shape* shape = object; /* ... */ }
case TypeCar: {Car* car = object; /* ... */ }
case TypePresident: {President* pres = object; /* ... */ }
}
}

Once you've done this, you can enhance type safety in C99, gcc, and
other environments supporting inline functions by creating inline wrappers:
inline void DoGenericThingShape(Shape* shape) {
DoGenericThing(shape, TypeShape);
}
etc.

2. If you're simply storing the types, not executing operations on them,
as in a container of some sort, then it suffices to pass a void pointer
to the object with the size and then use memmove to move the data around.

3. Use macros with token-pasting to generate a different version of the
function for each type you wish to use it with:

#define DECLARE_DOGENERICTHING(type) \
void do_generic_thing_##type(type t);

#define DEFINE_DOGENERICTHING(type) \
void do_generic_thing_##type(type t) { \
/* Implementation */ \
}

Then use both macros in any module you want to have access to a
particular instantiation. Put the DECLARE macro in a header to export an
instantiation, so it can be reused.
 
J

Jonathan Adams

"Mark A. Odell said:
(e-mail address removed) (Cao Tran) wrote in


Pass in a type argument or in this simple case define bit_count() to take a
long as its argument. Then C will promote short and int types to long in
the call to bit_count().

.... which may (or may not) give the wrong results. In this example, it
depends on what the results of:

bit_count((short)-1);
bit_count((int)-1);

should be, since sign extension is part of promotion.

- jonathan
 
P

pete

I think we're talking about conversions and not promotions.
... which may (or may not) give the wrong results.
In this example,

This is the example:
int main()
{
short x=1;
int y =1;
long z=1

bit_count(x);
bit_count(y);
bit_coutn(z);

return 0;
}
it depends on what the results of:

bit_count((short)-1);
bit_count((int)-1);

should be, since sign extension is part of promotion.

No, it doesn't depend on that.
void bit_count(long);
takes care of int and short arguments.

(int)-1 means exactly the same thing as -1
Both ((short)-1) and (-1) will be converted to ((long)-1)
if used as arguments to a function with long parameters.
 
J

Jonathan Adams

pete said:
Jonathan Adams wrote:

This is the example:
int main()
{
short x=1;
int y =1;
long z=1

bit_count(x);
bit_count(y);
bit_coutn(z);

return 0;
}
Indeed.


No, it doesn't depend on that.
void bit_count(long);
takes care of int and short arguments.

(int)-1 means exactly the same thing as -1
Both ((short)-1) and (-1) will be converted to ((long)-1)
if used as arguments to a function with long parameters.

Take a simplified bit_count():

int
bit_count(long x)
{
int count = 0;
while (x != 0) {
count++;
x <<= 1;
}
return (count);
}

If I wrote bit_count_short(), which looks like the above bit_count(),
only substituting "short" for "long" every place it appears, then:

bit_count_short(-1) < bit_count((short)-1)

assuming sizeof (short) < sizeof (long). Which version of the function
is desired (bit_count_short(x) or bit_count(x)) in main() above depends
on what the bit_count*() family is supposed to be doing.


Cheers,
- jonathan
 
P

pete

Jonathan said:
Take a simplified bit_count():

int
bit_count(long x)
{
int count = 0;
while (x != 0) {
count++;
x <<= 1;
}
return (count);
}

If I wrote bit_count_short(), which looks like the above bit_count(),
only substituting "short" for "long" every place it appears, then:

bit_count_short(-1) < bit_count((short)-1)

assuming sizeof (short) < sizeof (long).
Which version of the function
is desired (bit_count_short(x) or bit_count(x)) in main()
above depends
on what the bit_count*() family is supposed to be doing.

I see.
Thank you.
 
C

CBFalconer

Jonathan said:
.... snip ...

Take a simplified bit_count():

int
bit_count(long x)
{
int count = 0;
while (x != 0) {
count++;
x <<= 1;
}
return (count);
}

I hope you don't write code like that. The << 1 operator is
defined to produce the same result as *2. The result of
overflowing a long (or any signed integer type) is either
implementation or undefined behavior, and is not portable.

Besides which the above doesn't even count bits set. You might
try:

int bit_count(unsigned long x)
{
int count;

for (count = 0; x != 0; x >>= 1)
if (x & 1) count++;
return count;
} /* bit_count untested */

although there are more efficient methods.
 
J

Jonathan Adams

CBFalconer said:
I hope you don't write code like that. The << 1 operator is
defined to produce the same result as *2. The result of
overflowing a long (or any signed integer type) is either
implementation or undefined behavior, and is not portable.

I was just repeating the original example from

--- cut here ---
/* how to declare a function to accept different types of argument */

int bit_count()
{
int count=0;

while (x!=0)
{
printf("count = %d and value of x = %d\n", count++, x);
x<<=1;
}
return 0;
}
--- cut here ---

sans printf(). No, I don't write code like that. Part of the reason I
was wondering about signed-unsigned issues was the unlikeliness of the
algorithm, especially given the *name*.
although there are more efficient methods.
Yup -- I've got a copy of _Hacker's Delight_ sitting on my shelf, in
fact.

- jonathan
 
C

CBFalconer

Jonathan said:
.... snip ...

/* how to declare a function to accept different types of argument */

int bit_count()
{

That doesn't accept different types of arguments. The first time
used a decent compiler resolves the arguments and their types.
Further use should match this, or there will be unannotated
conversions to the appropriate type. The practice can lead to
peculiar and obscure bugs. Use proper prototypes.

However "int bit_count(unsigned long x);" can be called with an
int or a short or even a char argument, signed or unsigned, and
the argument will be automatically converted at the calling
point. As long as the arguments are non-negative you will still
get the correct results.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
474,146
Messages
2,570,832
Members
47,374
Latest member
EmeliaBryc

Latest Threads

Top