In some C project, I have seen this code:
static void *l_alloc (void *ud, void *ptr, size_t osize, size_t nsize) {
(void)ud;
(void)osize;
/* some code not using `ud` or `osize` */
return ptr;
}
Do the two casts to void serve any purpose?
It is there to avoid warnings from the compiler because some parameters are unused.
The reason for having unused parameters in the prototype is usually because the function needs to conform to some external API - perhaps it is a library function, or a pointer to that function is passed to another function that expects this calling convention. However not all arguments used by the calling convention are actually needed in the function itself.
The reason for mentioning the parameter name in the body is to avoid warnings like
unused.c: In function ‘l_alloc’:
unused.c:3:22: warning: unused parameter ‘ud’ [-Wunused-parameter]
void *l_alloc (void *ud, void *ptr, size_t osize, size_t nsize) {
^~
This warning can be suppressed with using the actual parameter in the function body. For example if you do have the following statement:
ud;
This warning is now suppressed. However now GCC will produce another warning:
unused.c:5:5: warning: statement with no effect [-Wunused-value]
ud;
^~
This warning tells that the statement ud;, while being syntactically valid C, does not affect anything at all, and is possibly a mistake, not unlike the statement
abort;
which should perhaps have been written as abort(); instead for it to do something.
And that's where the (void) cast comes in - it will tell the compiler unambiguously and explicitly that the statement is supposed to have absolutely no effect at all.
While perusing some STM32 middleware code, I came across this very odd line and can't parse it. It's basically,
(void)(foo);
It's not a void pointer cast - that would be straightforward. It's not calling a function and casting its return value as void - that would require a couple more parentheses. It looks like an rvalue without an lvalue. Is this just a no-op to prevent the function from being optimized away? Or does it actually do anything?
Here it is in context.
// SVCCTL_EvtAckStatus_t is just an enum typedef
typedef SVCCTL_EvtAckStatus_t (*SVC_CTL_p_EvtHandler_t)(void *p_evt);
void SVCCTL_RegisterCltHandler( SVC_CTL_p_EvtHandler_t pfBLE_SVC_Client_Event_Handler )
{
#if (BLE_CFG_CLT_MAX_NBR_CB > 0)
// Ignore all this
SVCCTL_CltHandler.SVCCTL_CltHandlerTable[SVCCTL_CltHandler.NbreOfRegisteredHandler] = pfBLE_SVC_Client_Event_Handler;
SVCCTL_CltHandler.NbreOfRegisteredHandler++;
#else
// This is the weird stuff
(void)(pfBLE_SVC_Client_Event_Handler);
#endif
return;
}
It doesn't do anything, except one thing. Stopping the compiler from complaining about unused variables. It is actually being recommended here, on SO, as a portable way of doing it: Portable UNUSED parameter macro used on function signature for C and C++
Example:
int somefunction(int a, int b, int c)
{
(void)(c); // c is reserved for future usage,
//stop the compiler from issuing "unused parameter" warning
return a+b;
}
What this does:
(void)(foo);
Is cast the expression foo to type void. It's a way of saying that an expression is explicitly not being used.
If you look at the definition of the function SVCCTL_RegisterCltHandler, you'll see that it takes a parameter named pfBLE_SVC_Client_Event_Handler. This parameter is used in the #if preprocessor block. If the #if condition is false, this parameter would otherwise be unused and the compiler would emit a warning that the parameter pfBLE_SVC_Client_Event_Handler is unused.
By casting this parameter to void in the #else block it uses the value and silences the compiler warning.
It's to prevent the compiler from complaining about foo being unused. That's literally it. It's like the maybe_unused attribute in C++.
I have following code in C:
pthread_cleanup_push(pthread_mutex_unlock, &mutex);
however when I compile it, I get the following warning:
warning: initialization from incompatible pointer type
What's wrong? It looks like the cleanup handler should return void*, not int. Is there any way to bypass this warning without writing additional wrapper?
The expression pthread_mutex_unlock does not have type void (*)(void *). You need to wrap it:
static void cleanup_unlock_mutex(void *p)
{
pthread_mutex_unlock(p);
}
and pass this function's address to pthread_cleanup_push.
Others may advise you to just cast pthread_mutex_unlock, but this is incorrect and unsafe. It will cause the function to be called via a pointer to the wrong function type, resulting in undefined behavior.
static void llist_dtor(void *user, void *element)
{
(void)user;
(void)element;
/* Do nothing */
}
Is it no-operation function? Then why is casting done? Is it ok to pass NULL as one of its parameters?
That's indeed a no-op. The casts to (void) are here to avoid getting "parameter never used" warnings with some compilers (the casts are optimized away, but the parameters are still considered as "used").
You can pass NULL since the parameters are ignored anyway.
Yes, this is a no-op function.
The casting is a common trick to prevent the compiler complaining about unused parameters.
Yes, this is a no-op function and void casted lines are placed to avoid the "unused parameter" warning. For gcc, search for "unused" in the page: http://gcc.gnu.org/onlinedocs/gcc/Warning-Options.html
However, if it were C++ instead of C, I would probably write it little differently as
static void llist_dtor( void * /* user */, void * /* element */ )
{
/* Do nothing */
}
Note that the variable names are commented out.
That is not no-op. Like that you tell the compiler to ignore those two arguments.
For the following C code (for swapping two numbers) I am getting the "conflicting types" error for swap function:
#include <stdio.h>
#include <stdlib.h>
int main()
{
int a,b;
printf("enter the numbers to be swapped");
scanf("%d%d",&a,&b);
printf("before swap");
printf("a=%d,b=%d",a,b);
swap(&a,&b,sizeof(int));
printf("after swap");
printf("a=%d,b=%d",a,b);
getch();
}
void swap(void *p1,void *p2,int size)
{
char buffer[size];
memcpy(buffer,p1,size);
memcpy(p1,p2,size);
memcpy(p2,buffer,size);
return(0);
}
Compiler diagnostics:
<source>:10:6: warning: implicit declaration of function 'swap' [-Wimplicit-function-declaration]
swap(&a,&b,sizeof(int));
^~~~
program:15:6: warning: conflicting types for 'swap'
void swap(void *p1,void *p2,int size)
^~~~
Can anybody tell why that error is coming?
What is the solution for that?
The problem is that swap was not declared before it is used. Thus it is assigned a "default signature", one which will in this case not match its actual signature. Quote Andrey T:
The arguments are passed through a set
of strictly defined conversions. int *
pointers will be passed as int *
pointers, for example. In other words,
the parameter types are temporarily
"deduced" from argument types. Only
the return type is assumed to be int.
Aside from that, your code produces a bunch of other warnings. If using gcc, compile with -Wall -pedantic (or even with -Wextra), and be sure to fix each warning before continuing to program additional functionality. Also, you may want to tell the compiler whether you are writing ANSI C (-ansi) or C99 (-std=c99).
Some remarks:
Put spaces after commas.
Make main return an int.
And make it return 0 or return EXIT_SUCCESS.
Import the definition of getch: #include <curses.h>.
Or just use getchar.
Import the definition of memcpy: #include <string.h>.
Don't return something in a void function.
You may want to use malloc to allocate a buffer of variable size. That will also work with older compilers:
void swap(void *p1, void *p2, int size) {
void *buffer = malloc(size);
memcpy(buffer, p1, size);
memcpy(p1, p2, size);
memcpy(p2, buffer, size);
free(buffer);
}
You need to declare swap before using it. For example, put swap above main, or add a prototype for swap like this:
void swap(void *,void *,int);
int main ()
Incidentally main should be int not void and usually it returns the value zero, unless there is an error.
First off, the actual error message wouldn't hurt.
Secondly, making buffer of [size] only works on some compilers (that's a new feature, not all compilers have it yet). Are you sure yours does?
Thirdly, you need to declare swap before calling it. Add a prototype at the top of the file:
void swap(void *p1,void *p2,int size);
You failed to declare your swap explicitly, forcing the compiler to make assumptions about the function at the point of the call. The compiler, in accordance with C rules, will assume that swap is
int swap(int *, int *, size_t)
Later you declare your swap as
void swap(void *, void *, int)
which is obviously different from what the compiler assumed. This is the conflict the compiler is telling you about.
Also, your void swap attempts to return 0. What were you trying to achieve by that?
P.S. It's int main, not void main.
P.P.S. The program is not guaranteed to produce any output if its output does not end in a new-line character.
You may wonder why the program compiles at all without a prototype for swap(), and that's because the compiler is more than a C99 tool. It also compiles C89 and K&R C programs.
C89 added the prototypes. Prior to C89, the compiler didn't need to see the declaration (the prototype) of a function unless it returned something other than int and the types of the formal parameters were not known to the compiler at all. The compiler just called every function with the types of the actual arguments, which received a set of default argument promotions to simplify things. The programmer would run the lint utility to cross-check actual and formal parameters. This program is still shipped with the BSD distributions.
K&R programs and their corresponding code styles are still accepted by your compiler, so when it sees a function for which no prototype is available it just goes ahead and calls it anyway.
In this case, you switch paradigms in between the call and the definition of the function. The K&R C assumptions the compiler made about the undeclared function when it had to generate a call turned out not to be valid. Even if you had written the whole program in the K&R style the compiler would have made the same complaints when it found out the real types of the function arguments.
With GCC, this is a warning,
when you dont declare a function before using it, the compiler tries to guess the declaration using the type of call made to that function.Hence the behavior.
Well, it compiles on http://codepad.org (after removing the getch(), which is irrelevant). Maybe your compiler complains about using memcpy on non-restricted pointers?
In swap() p1 and p2 are not guaranteed not to be aliases. This is an actual bug waiting to happen - calling swap on &a[i] and &a[j] might blow up memcpy when i==j. Either use memmove (which is guaranteed not to blow up on overlapped areas) or declare the pointers restricted.