This question already has answers here:
Is `memcpy((void *)dest, src, n)` with a `volatile` array safe?
(3 answers)
Closed 2 years ago.
I'm getting warning like this on xc32 compiler (gcc based microcontroller compiler, not open-source).
modem_uart.c:66:5: warning: passing argument 1 of 'memset' discards
'volatile' qualifier from pointer target type [enabled by default]
Here is the code:
#include <string.h>
// (...)
volatile char rxbuf[MODEM_UART_RXBUF_SIZE];
// (...)
void some_function(void)
{
// (...)
memset(rxbuf, 0, MODEM_UART_RXBUF_SIZE); // <- warning here
// (...)
}
Can someone explain why compiler is discarding volatile?
The specification in the standard of memset has the following declaration:
void *memset(void *s, int c, size_t n);
The first argument is not declared volatile void *s. So it doesn't guarantee to obey the extra restrictions on accessing volatile data. Making every call to memset() treat the destination as if were volatile would impose an unnecessary performance impact.
If you need those assurances, you should replace the memset() call with an explicit loop.
for (int i = 0; i < MODEM_UART_RXBUF_SIZE; i++) {
rxbuf[i] = 0;
}
If you need this from multiple places in your code, you could put it into a volatile_memset() function.
Your platform doesn't provide a memset function that is guaranteed to respect whatever guarantees it provides for volatile. So, in order to call memset, the compiler must discard the volatile qualifier on rxbuf.
You should probably write your own implementation of memset that respects whatever guarantees you expect volatile to provide for you. This answer includes one for memcpy to solve a similar problem. If there are no such guarantees, then get rid of volatile.
Related
This question already has answers here:
What does casting to `void` really do? [duplicate]
(4 answers)
Closed 1 year ago.
I'm maintaining an application that incorporates C++, C and a few python files; and all executables are build using CMake.
I noticed a few functions that are using the (void) cast.
Example:
main.c:
typedef void CxType;
int foo(CxType *, const char *, const char *, int , int *);
// c is a template
// QString &s;
// QMapData::Node *e;
// QScopedPointer<QDataStreamPrivate> d;
// v is another template
#define foo2(c,s,e,d,v) foo(c,s,e,d,v)
static void some_function( void )
{
(void) foo(param1,param2,...);
}
According to the O'Reilly "C Pocket reference"; (void) can be used to explicitly discard the value of an expression in C; For example: (void)printf("An example.")
Why use (void) foo(param1,param2,...); instead of simply foo(param1,param2,...);?
The cast to void is there to suppress a compiler warning about unused return value.
// at least that was most probably the intention of the genius that came up with the cast.
Typically you would only cast an expression to void in one of two cases.
First, if a function takes a parameter that you know isn't being used but the parameter can't be removed because the function in question is being used as a callback.
Second, if you're calling a function that has an compiler-specific attribute that causes it to warn if the function's return value isn't used, but you know you don't need to read it.
Neither of these cases apply to the above code, so the cast isn't needed.
I admit to using the (void) foo() cast style myself; the rationale is to indicate that I know the function returns a value, which I'm deliberately ignoring. That is, it is for the reader (e.g., my future self) rather than to suppress compiler warnings, since popular C compilers do not warn about this (except perhaps with non-standard annotations on specific functions).
This question already has answers here:
C function syntax, parameter types declared after parameter list
(7 answers)
Should I place the parameter storage class specifier in the function definition or in both the declaration and definition?
(5 answers)
"register" keyword in C?
(19 answers)
Closed 2 years ago.
void
usage (cpp)
register const char *const *cpp;
{
(void) fprintf (stderr, *cpp++, program_name, cvs_cmd_name);
for (; *cpp; cpp++)
(void) fprintf (stderr, *cpp);
error_exit ();
}
I don't get why register variable is not inside the curly brackets and what is this (void) in front of fprintf? Also register const char *const *cpp, i've never seen anything like this before
The reason you've "never seen this before" is because this is using the syntax of the original, historical, K&R C version. That must be some real, old C code you're looking at. I just looked up, and ANSI C (C90) came out in 1990, so this code must be at least 30 years, or so, old.
I suppose this is something that needs to be known if one needs to deal with historic C code, but otherwise you can simply forget it.
The (void) cast means the same thing it means today.
The register keyword is a hint to the compiler that you'd like that value to be kept in a dedicated register on the processor. This can speed up reads and writes. With modern compilers, however, this sort of optimization is not only unnecessary but often counterproductive.
The reason it is between the function declaration and the block is that in old c (pre C90) you wouldn't declare parameter type next to the parameter but between the declaration of the function and the block.
For example:
int main(argc, argv)
char ** argv;
{
...
}
Notice I didn't do anything for argc because if you don't explicitly define a type it defaults to int.
You'll see this more often than you'd think. I ran into this a bunch when I did work on FFMPEG.
The (void) cast thing prevents unused parameter warnings/errors. I've run into this when working on PortAudio with a low-level callback function.
This question already has answers here:
Why cast an unused function parameter value to void?
(2 answers)
Closed 6 years ago.
I am trying to make sense of the following bit of C code.
static unsigned
parent(const struct binheap *bh, unsigned u)
{
(void)bh;
return (u / 2);
}
What could the purpose of (void)bh; be? It is not assigned to anything and should not have an effect on the output. The only purpose I can think of might be as a kind of an assert against a null pointer perhaps.
For context, that snippet is from the original implementation of a B-heap. That code tends to be rather too clever in other places as well, e.g. doing for (unsigned n = 2; n; n += n) { to break at n = 65536.
(void)bh; has no effect in the generated code. However, with many compilers it will prevent the compiler from issuing a warning about the parameter bh not being otherwise used in the function, and that was almost certainly the intent of the programmer. bh being a struct pointer is irrelevant; if this technique works at all, it will work regardless of the type of the unused parameter.
C++ has a more elegant way to accomplish this, allowing you to omit the variable name for any argument you don't need --
static unsigned
parent(const struct binheap *, unsigned u)
{
return (u / 2);
}
-- but C doesn't support this. Some compilers have extensions for the same purpose that are, if not so elegant, at least more self-describing, e.g. GCC's
static unsigned
parent(const struct binheap *bh __attribute__((unused)), unsigned u)
{
return (u / 2);
}
The (void)bh; trick is the only technique for suppressing unused-parameter warnings that uses only the facilities of ISO C; on the other hand, it's not guaranteed to work, the warnings a compiler emits are entirely up to that compiler, so you're already in implementation-defined territory no matter what you do.
This is simply to avoid the compiler warning against an unused variable. Without the cast there in place, you compiler will (try to) warn you that you have an unused variable in your code.
This is typically done to avoid compiler warnings. For example, if compiling with -Wall -Wextra in gcc, it will warn you that you're not using bh IF you do not make the cast to void.
Because compiler warning
Some compilers throw warning when a variable is unused within the function. See below
#include <stdio.h>
void hello(int a, int b)
{
int i = b + 1;
printf("hello %d\n", i);
return;
}
int main(void)
{
hello(10, 20);
return 0;
}
Compiling it as below to see the warning
$ gcc -Wunused-parameter a.c
a.c:3:16: warning: unused parameter 'a' [-Wunused-parameter]
void hello(int a, int b)
^
1 warning generated.
I want a macro to free multiple (variadic number) pointers of different type. Based on similar questions in SO I made this code which seems to work
#include <stdio.h>
#include <stdarg.h>
#include <stdlib.h>
/* your compiler may need to define i outside the loop */
#define FREE(ptr1, ...) do{\
void *elems[] = {ptr1, __VA_ARGS__};\
unsigned num = sizeof(elems) / sizeof(elems[0]);\
for (unsigned i=0; i < num; ++i) free(elems[i]);\
} while(0)
int main(void)
{
double *x = malloc(sizeof(double)); /* your compiler may need a cast */
int *y = malloc( sizeof(int)); /* ditto */
FREE(x, y);
}
My question is
Is the creation of a void* array correct in this context? (I saw the same trick with *int[], so the question is will a *void[] do what I expect)
Is the code C99 compliant, are there any compilers that would have problems with this?
One potential usability problem with this is that it doesn't scale to freeing only a single pointer, similar to the regular free. While this isn't necessary (since you could require the user to spot this and use free), it's usually elegant for things to be as generic as possible and automatically scale themselves to fit such use cases.
C99 (also C11) standard section 6.10.3 paragraph 4:
If the identifier-list in the macro definition does not end with an ellipsis ... Otherwise, there shall be more arguments in the invocation than there are parameters in the macro definition (excluding the ...).
i.e. in strictly conforming C, the __VA_ARGS__ must be used. GCC will even highlight this for you (a compiler can't prove something is compliant, but it can warn you when it isn't) when using -std=c99 -Wall -pedantic:
test.c: In function 'main':
test.c:18:11: warning: ISO C99 requires rest arguments to be used [enabled by default]
FREE(x);
^
Technically you don't need the actual value, just the trailing comma (FREE(x,); - an empty macro argument is still an argument, and the array initializer it populates also allows trailing commas), but that's not very... integrated with the language.
In practice real compilers won't directly object to missing rest-args, but they might warn about it (as shown above), because a non-fatal error is often reasonable to interpret as a sign that something is wrong elsewhere.
That's pretty cool, and yes it's correct to use void *.
You could improve it somewhat (more const, and of course use size_t instead of unsigned) but in general it seems alright.
Also, drop the casts in main(), there's no need to cast the return value of malloc() in C and doing so can mask actual errors so it's just bad.
To address #Leushenko's answer, you might be able to glue something together by adding an extra macro expansion step that always adds a NULL in the varargs macro call. That way, you're never going to call the actual varargs macro with just a single argument, even if the toplevel macro is called with only one. Of course, calling free(NULL) is always safe and well-defined, so that should work.
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.