4

I am calling the following library function in two ways:

unsigned int
LsSendToQ(unsigned int p4Node, const char queueName[4], lsMsg *pMsg,
          unsigned int prio) {

}

The first way :

LsSendToQ((unsigned int)0, (const char *)Q_NAME, (lsMsg *)(void *)pMsg, 0) 

and the second way :

LsSendToQ((unsigned int)0, (const char *)Q_NAME, (lsMsg *)pMsg, 0) 

Both calls compile fine, but which one is the right way ? And why is (void *) used in the first call, which looks like a function pointer to me ?

David
  • 14,047
  • 24
  • 80
  • 101
dexterous
  • 6,422
  • 12
  • 51
  • 99
  • http://stackoverflow.com/questions/11626786/what-does-void-mean-and-how-to-use-it – Tharif Jan 19 '16 at 05:04
  • 2
    How is `Q_NAME` defined? how is `pMsg` defined? The first cast is useless, `(lsMsg *)(void *)pMsg` is redundant, but might be needed to silence a compiler warning. – chqrlie Jan 19 '16 at 05:38
  • 2
    You should avoid redundant casts; try `LsSendToQ(0, Q_NAME, pMsg, prio);` . The cast of `pMsg` may be required but we can't tell just based on what you posted. – M.M Jan 19 '16 at 05:56
  • As an aside, while the first one is just noise in C I can imagine that it makes a difference in certain inheritance situations in C++, with multiple inheritance. (The cast from and to `void*` would always be a reinterpret_cast while a direct cast may be translated to a static_cast to the address of a sub object). – Peter - Reinstate Monica Jan 19 '16 at 10:28

3 Answers3

3

A pointer to void is a "generic" pointer type. A void * can be converted to any other pointer type without an explicit cast. You cannot dereference a void * or do pointer arithmetic with it; you must convert it to a pointer to an complete data type first. See this answer.

So the parameter pMsgis not directly compitable to lsMsg * then the 2nd calling is a possible way to use this in the function calling[ I didn't tested it].

By the way, as long as type of pMsg is lsMsg * the 1st one is enough.

Edit:

The 2nd one is enough as it covers the 1st one.

Community
  • 1
  • 1
Shafi
  • 1,850
  • 3
  • 22
  • 44
  • Do not copy content from other answers without giving source: http://stackoverflow.com/a/11629682/694733 – user694733 Jan 19 '16 at 08:34
  • Thanks for the info. – Shafi Jan 19 '16 at 08:39
  • Hm. "A `void *` can be converted to any other pointer type without an explicit cast.": Wouldn't that imply that the OP could omit the final cast to `lsMsg *` in `(lsMsg *)(void *)pMsg` (because parameter passing is a form of initialization)? "You cannot dereference a `void *`": Unrelated to the OP's question. "So the parameter pMsg is not directly compitable to `lsMsg *` then the 2nd calling is a possible way to use this in the function calling": true, but the first one as well. So what? "By the way, as long as type of `pMsg` is `lsMsg *` the 1st one is enough." Of course; *no cast* suffices. – Peter - Reinstate Monica Jan 19 '16 at 10:23
3

The second version is the correct one.

The first call looks like an attempt to dodge incompatible type warnings. If pMsg is not compatible with lsMsg * you could kill the compiler warning by casting to void* in between.

You shouldn't do this though, because it almost certainly hides a bug in your program! Either the two pointer types are completely incompatible, in which case the program may instantly crash & burn upon accessing the pointer. Or they are in theory compatible, but the compiler implements type aliasing and the (void*) cast would then hide a violation of the "strict aliasing rule". In either case you have undefined behavior and a severe bug.

Lundin
  • 195,001
  • 40
  • 254
  • 396
2

I see no reason for the first way of converting the pointer type twice. Just use the second way is enough.

Sam Liao
  • 43,637
  • 15
  • 53
  • 61