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!
Related
I've got a problem when the function is called by other functions.
My functions are so:
void *table_lookup(const table *t) {
...
//Here I want to call my other function.
table_remove(t);
...
}
void table_remove(table *t) {
...
}
I got a warning when I compile it. The problem is that I cannot change the argument's type.
You must NOT cast away the const qualifier. Any attempt to thereafter modify the value that was qualified const invokes Undefined Behavior. See C11 Standard - 6.7.3 Type qualifiers(p6).
The table_lookup parameter is const qualified for a reason. It allows the compiler to optimize the use of t. If you cast away the const and attempt to modify t you are breaking your promise to the compiler that t won't be modified.
Instead, you should refactor your code so that the remove() function calls table_lookup inside it to obtain a pointer (presumably) to the node you wish to remove. Then remove the node. Don't try and add a remove() within table_lookup. Create a new function.
In C, you can directly cast it to remove the 'const' property.
void *table_lookup(const table *t)
//Here I want to call my other function.
table_remove((table*)t) // remove 'const' by directly casting.
...
return
void table_remove(table *t)
...
You can cast away the const qualifier: table_remove((table *)t); but you might run into problems if table_remove tries to modify the table structure, for example if it is stored in a read-only segment.
Therefore you should not do it. It is rather unexpected that a lookup function would modify the table anyway. If it does for good reasons, such as building a hash table or maintaining a cache, the argument should not be declared as const.
Yes That’s right. it was bad idea to cast away const qualifier. . I can’t add a new function either. ((table)*) gives problem.
You can try the code below:
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wcast-qual"
void *table_lookup(const table *t) {
table_remove((table *)t);
}
#pragma GCC diagnostic pop
From: https://stackoverflow.com/a/13253997/5093308
What are void type variable in C?
I have rough idea but not sure how i can use them for below scenario.
server/ client program
I have a struct array which contains hostname, address in server. I want to send it to the client over the socket. How i can achieve it?
struct ipinfo{
char hostname[64];
char address[64];
}
struct ipinfo allip[5];
I read some where that i can copy into specific memory location as void type variable and them send the variable? Can any one please explain this concept? I really appreciate it.
In C the only time void can be used as a variable type is if it's a pointer. They are handy for when you aren't sure what type of data you have coming.
void * somePointer;
This can be used for various things.
Referencing an object without knowing the type.
Handling plain memory without a type. Malloc (and I believe new in C++) returns a void pointer as at the moment the memory is without a type.
Try not to use void pointers though, they are generally a good idea to stay away from. Likely to cause errors and headaches. You can often times find a better solution.
The void keyword can also be used in front a function.
void printHello(void)
{
printf("Hello");
}
In this function we use void because it's not returning anything. Void functions can simply do whatever task we assign them without returning anything. We also don't need to pass any data into the function, so we specify void in the parameters.
Note: If you're ever learning C++, there's something you really need to keep in mind about function parameters.
void printHello() // <- This is bad in C, it will take any number of anything practically
{
printf("Hello");
}
Always put void in the parameters if you want no arguments passed in for C.
void printHello() // <- Good in C++, it won't allow any arguments on a call
{
std::cout << "Hello";
}
You cannot however use void as a variable type as in
void a = 0;
void b = 's';
void c = 5.5
// You can't use void to store anything
I don't think void means what you hope it means. void is used in C-like languages to indicate an unknown type, or no type. For example, void* is a void pointer. It's a memory address that has some data at it, but the format of the data (and even its size) is not specified. In order to use that data you need to assign some type to it, usually through an assignment or and explicit or implicit cast.
Here's an example:
void * memory = malloc(16);
memory[0] = 0; // this won't compile!
int * int_array = memory;
int_array[0] = 0; // this is ok because we know the type
void is also used to indicate that a function doesn't have a return value.
Here's an example:
void exit(int status);
void can also be used as an indication that you're intentionally discarding the return value of a function call. This can improve the readability of your program, or suppress some compiler diagnostics.
Here's an example:
(void)memset(memory, 0, 16); // why does memset have a return value??
Another use of void is to indicate an empty parameter list. In C, a function declared like main() has an unspecified parameter list, not an empty list.
Here's an example:
int main(void) {
...
}
I'm afraid that none of these application are likely to help you solve your socket problem.
void pointers are mainly used in function argument when you expect that argument to be of any type because you can cast any type to void then back to any type without loss of data , the only thing you can't do with a void pointer is to dereference it.
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).
Can anyone enlighten me as to why I should bother to specify the size of a C array argument in a function header? For example:
void foo (int iz[6]) { iz[42] = 43; }
With:
int is[2] = {1,2,3};
we get a useful error. Perhaps it helps with commenting/documentation?
Can anyone enlighten me as to why I should bother to specify the size of a C array argument in a function header? For example:
void foo (const char sz[6]) { sz[42] = 43; }
IMO, you shouldn't. When you try to pass an array to a function, what's really passed is a pointer to the beginning of the array. Since what the function receives will be a pointer, it's better to write it to make that explicit:
void foo(char const *sz)
Then, since it's now clear that the function has been given no clue of the size, add that as a separate parameter:
void foo(char const *sz, size_t size)
The only meaningful reason to do that is for documentation purposes - to tell the future users that functions expect to receive an array of at least that many elements. But even that is a matter of convention - something that you have to agree upon with other users in advance. The language (the compiler) ignores that size anyway. Your function declaration is equivalent to void foo(int iz[]) and to void foo(int *iz).
The only way to make it somewhat meaningful for the compiler is to declare it as
void foo (int iz[static 6])
which acts as a promise to the compiler that the array will have at least 6 elements, meaning that the compiler will be able to optimize that code using that assumption. Moreover, if you really want to adopt the convention mentioned above, it makes more sense to declare array parameter sizes with static specifically, since the language explicitly defines the semantics of this construct.
What you mean by "we get a useful error" is not clear to me. The code
int is[2] = {1,2,3};
is[42] = 42;
does not contain any constraint violations. It produces undefined behavior, but it is not required to produce a diagnostic message during compilation. In other words, no, we don't get any "useful error" from this.
It's a comment. Arrays are demoted to pointers in function parameters. Comments can still be useful however, even if the compiler doesn't read them.
It is a useful comment when you want to tell to client code that it must pass an array of defined size, i.e:
void foo(const char bar[5]);
/* It is expected that foo function receives an array of size 5 */
Yet, documentation doesn't replace in code checks:
void foo(const char bar[5])
{
if (!bar) error();
if (strlen(bar) != 4) error();
/* ... */
}
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.