typecast function pointer

M

Mark

Hello

typedef signed int s_int32_t;

typedef void (*del_cb_t) (void *val);
typedef s_int32_t (*cmp_cb_t) (void *val1, void *val2);

int obj_create (cmp_cb_t cmp, del_cb_t del);

int obj_create (cmp_cb_t cmp, del_cb_t del)
{
/* do the stuff */
}

....
int my_cmp (void * data1, void * data2)
{
}

ret = obj_create ((cmp_cb_t)my_cmp, (del_cb_t)NULL);

Does it have any useful effect to typecast 'my_cmp' given that return value
is different with what defines typedef ?


Mark
 
E

Eric Sosman

Hello

typedef signed int s_int32_t;

typedef void (*del_cb_t) (void *val);
typedef s_int32_t (*cmp_cb_t) (void *val1, void *val2);

int obj_create (cmp_cb_t cmp, del_cb_t del);

int obj_create (cmp_cb_t cmp, del_cb_t del)
{
/* do the stuff */
}

...
int my_cmp (void * data1, void * data2)
{
}

ret = obj_create ((cmp_cb_t)my_cmp, (del_cb_t)NULL);

Does it have any useful effect to typecast 'my_cmp' given that return value
is different with what defines typedef ?

No, because `int' and `s_int32_t' are *not* different types.
A typedef declaration does not create a new type; it just creates
an additional name for an existing type. Also, `signed int' and
`int' are not different types, but just two different ways to
name the same type. All of `s_int32_t', `signed int', and `int'
are different ways of naming one type, and all three aliases can
be used interchangeably.[*],[**]

If my_cmp() were in fact different -- if it returned a `float',
say, or an `unsigned long' -- then the cast would be both necessary
an *in*sufficient. "Necessary" in the sense that the compiler would
be required to issue a diagnostic if the cast were absent, but
"insufficient" in that even if it quieted the diagnostic the program
would still be wrong, with a wrongness that might not be detected
until run-time.

The other cast is also unnecessary. Because obj_create() is
declared with a prototype, the compiler "knows" the types of its
parameters and will convert the `NULL' argument to the proper
type.[***]

[*] Although `int' and `signed int' name the same type, note
that `char' and `signed char' do not. For historical reasons,
`char' is somewhat special, and is distinct from both `signed char'
and `unsigned char' even though it behaves just like one or the
other of them.

[**] In a bit-field declaration (like `int x : 4;' in a struct
or union), `int' and `signed int' may mean different things. Again
for historical reasons, a plain `int' bit-field may be either signed
or unsigned at the compiler's discretion, while `signed int x : 4;'
is definitely signed. It's helpful to adopt the viewpoint that
although `int' and `signed int' are the same, `int:N' and
`signed int:N' are distinct.

[***] Note that the compiler has no information about the types
of variadic parameters, those that match the `...' portion of a
variable-argument prototype. Casts are sometimes needed when
passing arguments to match those parameters; a cast is *always*
needed when passing `NULL' arguments to such parameters.
 
B

Ben Bacarisse

Mark said:
typedef signed int s_int32_t;

typedef void (*del_cb_t) (void *val);
typedef s_int32_t (*cmp_cb_t) (void *val1, void *val2);

It would be better is these could be const void * parameters.
int obj_create (cmp_cb_t cmp, del_cb_t del);

int obj_create (cmp_cb_t cmp, del_cb_t del)
{
/* do the stuff */
}

...
int my_cmp (void * data1, void * data2)
{
}

ret = obj_create ((cmp_cb_t)my_cmp, (del_cb_t)NULL);

Does it have any useful effect to typecast 'my_cmp' given that return value
is different with what defines typedef ?

Not really. I suppose it just possible that it might suppress a
warning. No diagnostic is required, but I can maybe an overly "helpful"
compiler might warn about the code without the cast.

However, you are setting yourself up for a maintenance problem later on.
If, in some future port of the software, s_int32_t ends not being
compatible with int, the code will be undefined and the cast might mask
all warnings about that. Is not possible to define my_cmp as returning
an s_int32_t?
 
M

Mark

Eric Sosman said:
No, because `int' and `s_int32_t' are *not* different types.
A typedef declaration does not create a new type; it just creates
an additional name for an existing type. Also, `signed int' and
`int' are not different types, but just two different ways to
name the same type. All of `s_int32_t', `signed int', and `int'
are different ways of naming one type, and all three aliases can
be used interchangeably.[*],[**]

Thanks for comprehensive answers!

What can be the reason to declare a function returning 'signed int' instead
of 'int' if those are all the same types? IMHO it only brings in confusion,
as in my case.

Mark.
 
I

Ian Collins

Eric Sosman said:
No, because `int' and `s_int32_t' are *not* different types.
A typedef declaration does not create a new type; it just creates
an additional name for an existing type. Also, `signed int' and
`int' are not different types, but just two different ways to
name the same type. All of `s_int32_t', `signed int', and `int'
are different ways of naming one type, and all three aliases can
be used interchangeably.[*],[**]

Thanks for comprehensive answers!

What can be the reason to declare a function returning 'signed int' instead
of 'int' if those are all the same types? IMHO it only brings in confusion,
as in my case.

There aren't any really. Maybe the original authour was trying to look
smart?
 
K

Keith Thompson

Mark said:
Eric Sosman said:
No, because `int' and `s_int32_t' are *not* different types.
A typedef declaration does not create a new type; it just creates
an additional name for an existing type. Also, `signed int' and
`int' are not different types, but just two different ways to
name the same type. All of `s_int32_t', `signed int', and `int'
are different ways of naming one type, and all three aliases can
be used interchangeably.[*],[**]

Thanks for comprehensive answers!

What can be the reason to declare a function returning 'signed int' instead
of 'int' if those are all the same types? IMHO it only brings in confusion,
as in my case.

The compiler doesn't care whether you write "int", or "signed int", or
"signed", or "int unsigned" for that matter.

You might write "signed int" for emphasis, to distinguish it from
"unsigned int":

unsigned int this_function(void);
signed int that_function(void);

(And "signed int" is not necessarily "int" when used to declare a bit
field, but the question was about function return types, so that doesn't
apply.)
 
E

Eric Sosman

Eric Sosman said:
No, because `int' and `s_int32_t' are *not* different types.
A typedef declaration does not create a new type; it just creates
an additional name for an existing type. Also, `signed int' and
`int' are not different types, but just two different ways to
name the same type. All of `s_int32_t', `signed int', and `int'
are different ways of naming one type, and all three aliases can
be used interchangeably.[*],[**]

Thanks for comprehensive answers!

What can be the reason to declare a function returning 'signed int' instead
of 'int' if those are all the same types? IMHO it only brings in confusion,
as in my case.

The `signed' keyword was absent from original prehistoric C,
and was added in the first ("C89", "ANSI") version of the Standard.
The intent was to allow the programmer to write `signed char' or
`unsigned char' when a tiny signed or unsigned integer was desired,
or to write plain `char' when the signedness was unimportant and
the choice could be left to the compiler.

When `signed char' became available, the committee decided that
`signed int' and `signed short' and `signed long' should also be
allowed, even though `signed' added no new meaning (these integer
flavors were and still are always signed). Perhaps the committee was
inspired by a desire for "regularity" in the language, or perhaps
they were thinking of declarations constructed by macro expansion.
Whatever their reason, `signed int' is now an alias for `int'.

To me, it seems pointless to write `signed int' instead of `int'.
Some might feel that `signed int' is more self-documenting in that
it emphasizes the fact that the type holds signed values, but it seems
to me that this is such a basic property of C that anyone who needs
the emphasis probably shouldn't be using the language. (I also find
`short int' similarly useless, and avoid `long int signed long' as
a threat to sanity.) Tastes vary, though, and a C programmer must be
prepared for the occasional "unusual" declaration.
 
I

Ike Naar

The compiler doesn't care whether you write "int", or "signed int", or
"signed", or "int unsigned" for that matter.

That sentence (or else the compiler) needs to be fixed.
 
K

Keith Thompson

Ike Naar said:
That sentence (or else the compiler) needs to be fixed.

Oops, the last should be "int signed".

To summarize, the following are all equivalent names for the same type:

int
signed int
int signed
signed

The "int signed" form is rarely used, but the standard permits type
specifiers to appear in any order.
 

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

Forum statistics

Threads
473,767
Messages
2,569,572
Members
45,045
Latest member
DRCM

Latest Threads

Top