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.
Related
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 the following function:
void foo(char *ptr_1)
{
char *ptr_2;
bar(ptr_2);
ptr_1 = ptr_2;
}
And get this warning:
parameter "ptr_1" was set but never used
I understand that the warning is technically true, but is irrelevant at the same time. I could suppress it with:
(void)(ptr_1)
But is there a better way?
It is not an irrelevant warning because the assignment has no effect. You could completely remove ptr_1 from the code without changing its behaviour. Your code is equivalent to this:
void foo(char *)
{
char *ptr_2;
bar(ptr_2);
}
In other words, the function parameter isn't used for anything. If your intention was to change the pointer at the caller side, you need to either pass a pointer to a pointer and de-reference it, or return the new value and let the caller use its value:
void foo(char **ptr_1)
{
char *ptr_2;
bar(ptr_2);
*ptr_1 = ptr_2;
}
or
char* foo()
{
char *ptr_2;
bar(ptr_2);
return ptr_2;
}
I understand that the warning is technically true, but is irrelevant at the same time.
Well, so is the code here. From this point of view of your code, you can get rid of the offending instruction itself.
Also (my personal opinion), it is almost always better to deal with the warnings rather that suppressing them. They are there for a reason ,after all.
Simple way is....
int dClock;//variable initiated without used anywhere.
dClock = dClock;//assign variable to itself to suppress not used warning.
worked in keil!
I was reading some source code, and this came up;
struct Cookie *
Curl_cookie_add(struct SessionHandle *data, /* rest of params were here */)
{
/* unrelated things were here */
#ifdef CURL_DISABLE_VERBOSE_STRINGS
(void)data;
#endif
/* rest of function goes here */
}
As you can see, void casted pointer, isn't even assigned to a variable. I was wondering what is the purpose of this.
This cast suppresses a compiler warning that would arise if data is not used.
GCC produces this warning if the -Wunused-parameter flag (implied by -Wextra) is enabled.
Fair point Joey - but suppressing that warning also suppresses it for all the cases where the programmer has accidentally not used a parameter...
I'm trying to check a C program with Splint (in strict mode). I annotated the source code with semantic comments to help Splint understand my program. Everything was fine, but I just can't get rid of a warning:
Statement has no effect (possible undected modification through call to unconstrained function my_function_pointer).
Statement has no visible effect --- no values are modified. It may modify something through a call to an unconstrained function. (Use -noeffectuncon to inhibit warning)
This is caused by a function call through a function pointer. I prefer not to use the no-effect-uncon flag, but rather write some more annotations to fix it up. So I decorated my typedef with the appropriate #modifies clause, but Splint seems to be completely ignoring it. The problem can be reduced to:
#include <stdio.h>
static void foo(int foobar)
/*#globals fileSystem#*/
/*#modifies fileSystem#*/
{
printf("foo: %d\n", foobar);
}
typedef void (*my_function_pointer_type)(int)
/*#globals fileSystem#*/
/*#modifies fileSystem#*/;
int main(/*#unused#*/ int argc, /*#unused#*/ char * argv[])
/*#globals fileSystem#*/
/*#modifies fileSystem#*/
{
my_function_pointer_type my_function_pointer = foo;
int foobar = 123;
printf("main: %d\n", foobar);
/* No warning */
/* foo(foobar); */
/* Warning: Statement has no effect */
my_function_pointer(foobar);
return(EXIT_SUCCESS);
}
I've read the manual, but there's not much information regarding function pointers and their semantic annotations, so I don't know whether I'm doing something wrong or this is some kind of bug (by the way, it's not already listed here: http://www.splint.org/bugs.html).
Has anyone managed to successfully check a program like this with Splint in strict mode? Please help me find the way to make Splint happy :)
Thanks in advance.
Update #1: splint-3.1.2 (windows version) yields the warning, while splint-3.1.1 (Linux x86 version) does not complain about it.
Update #2: Splint doesn't care whether the assignment and the call are short or long way:
/* assignment (short way) */
my_function_pointer_type my_function_pointer = foo;
/* assignment (long way) */
my_function_pointer_type my_function_pointer = &foo;
...
/* call (short way) */
my_function_pointer(foobar);
/* call (long way) */
(*my_function_pointer)(foobar);
Update #3: I'm not interested in inhibiting the warning. That's easy:
/*#-noeffectuncon#*/
my_function_pointer(foobar);
/*#=noeffectuncon#*/
What I'm looking for is the right way to express:
"this function pointer points to a function which #modifies stuff, so it does have side-effects"
Maybe you are confusing splint by relying on the implicit conversion from "function name" to "pointer to function" in your assignment of my_function_pointer. Instead, try the following:
// notice the &-character in front of foo
my_function_pointer_type my_function_pointer = &foo;
Now you have an explicit conversion and splint doesn't need to guess.
This is just speculation, though. I haven't tested it.
I'm not familiar with splint, but it looks to me that it will check function calls to see if they produce an effect, but it doesn't do analysis to see what a function pointer points to. Therefore, as far as it's concerned, a function pointer could be anything, and "anything" includes functions with no effect, and so you'll continue to get that warning on any use of a function pointer to call a function, unless you so something with the return value. The fact that there's not much on function pointers in the manual may mean they don't handle them properly.
Is there some sort of "trust me" annotation for an entire statement that you can use with function calls through pointers? It wouldn't be ideal, but it would allow you to get a clean run.
I believe the warning is correct. You're casting a value as a pointer but doing nothing with it.
A cast merely makes the value visible in a different manner; it doesn't change the value in any way. In this case you've told the compiler to view "foobar" as a pointer but since you're not doing anything with that view, the statement isn't doing anything (has no effect).
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.