If i declare any variable using void, it gives error but sizeof(void) is 1.
What is reason for this?
void var; // it gives error
printf("sizeof(void) = %d", sizeof(void)); //prints 1
sizeof (void) is not valid in C and is allowed in GNU C as an extension to allow pointer arithmetic with void *.
From gcc documentation:
In GNU C, addition and subtraction operations are supported on pointers to void and on pointers to functions. This is done by treating the size of a void or of a function as 1. [...] consequence of this is that sizeof is also allowed on void and on function types, and returns 1.
The void type, in several programming languages derived from C and Algol68, is the type for the result of a function that returns normally, but does not provide a result value to its caller. Usually such functions are called for their side effects, such as performing some task or writing to their output parameters.
Upto my knowledge, You cannot use void as datatype, as the value is true or false statement the Boolean value will be 1 by default, so, it prints 1.
c.f. Is there a specific reason why “void” was not simply defined as “typedef struct{} void” (i.e. an empty struct) with appropriate casting rules? ...
This was originally suggested by Steve Bourne in AB33/Mar 1972 for Algol68 ...
Note: Algol68 doesn't have pointer arithmetic... but array slicing is available.
Related
I have a function that returns a value. Is it safe to cast it to a function pointer type that returns nothing (void) and then call it? Does the C standard give enough guarantees to make this safe on any platform, and equivalent to calling the function normally while ignoring the return value?
Bonus question: Is there a standards compliant calling convention that is used in practice on some platform and with which this is not safe to do?
Example code:
#include <stdio.h>
// simple function with a a side-effect;
// it is useful to call even when ignoring the return value
int f(int x) {
return printf("%d\n", x);
}
typedef void (*fun_t)(int);
int main() {
fun_t g = &f; // cast to void return type, issues a warning
g(123); // <-- is this safe, and equivalent to calling f(123) instead?
return 0;
}
Notes:
This question is concerned only with changing the return type during the cast, not changing the types of any function parameters.
I know that this is safe on the x86 and x64 platforms I use, assuming the default calling convention, but I would like to know if it is safe in general.
I know that it is easy to work around this when necessary by writing a wrapper void fw(int x) { f(x); }. However, I would still like to know if doing this is safe so that I can better understand the fundamentals of the C language.
No. This call invokes Undefined Behavior. See https://port70.net/~nsz/c/c11/n1570.html#6.3.2.3p8
A pointer to a function of one type may be converted to a pointer to a function of another type and back again; the result shall compare equal to the original pointer. If a converted pointer is used to call a function whose type is not compatible with the referenced type, the behavior is undefined.
At link https://port70.net/~nsz/c/c11/n1570.html#6.7.6.3p15 one can find rules of compatibility of function types:
For two function types to be compatible, both shall specify compatible return types. Moreover, the parameter type lists, if both are present, shall agree in the number of parameters and in use of the ellipsis terminator; corresponding parameters shall have compatible types. ...
No.
In addition to tstanisl's answer:
Consider a big return value as for example this structure:
struct big_t {
long la[1000000];
};
It is allowed as a return type.
Some compilers, including GCC for x86/x64, provide the space for the return value at the caller's site and call the function with a pointer to this space. In your use case, this pointer is not set.
So it is not safe on x86 or x64, nor any other architecture.
Have a lot of fun debugging the crashes!
This question already has answers here:
What does (void)var actually do?
(4 answers)
Closed 3 years ago.
I am reading this book and I have come across this code:
static void
task1(void *args) {
int i;
(void)args;
for (;;) {
gpio_toggle(GPIOC,GPIO13);
for (i = 0; i < 1000000; i++)
__asm__("nop");
}
}
I understand all (relatively) except for line 5. What is (void)args; doing?
args is not used in the function body, and I know that if an argument is not used then one could write
static void
task2(void *args __attribute((unused))) {
// code here
}
which is not being done here. So what is (void) written like that doing?
In general when one does not use an function argument, the compiler is likely to warn you about it. After all if you aren't going to use it why put it there in the first place?
In effect it is an artificial use of the argument that does nothing useful other than telling the compiler you know what you are doing, so "Shatupalready with the warning!"
(void) args works on all of the platforms that I have seen. I believe the __attribute((unused)) is a gcc specific thing.
Every expression has a type. Any expression can be turned into a statement by adding a semicolon. If an expression-statement yields a non-void value, that value is discarded.
Compilers will often warn about a value being discarded. Even a simple case like
printf("hello world\n");
quietly discards the int value returned by printf; a compiler warning might remind the programmer to test that value and take some action if it indicates that the call failed. (Most compilers will not warn in this particular case, since printf calls are usually used in a statement context, with the result ignored.)
Casting an expression to type void discards the result, but it does so explicitly. This is likely to silence a compiler warning.
As far as the language is concerned, a (void) cast converts a result to type void, which is equivalent to discarding that result. From a programmer's point of view, a (void) cast can silence a warning that a value is not used, since you're explicitly ignoring it and asserting to the compiler that you know what you're doing (even if you don't).
Quoting the C standard (N1570 draft), 6.3.2.2:
The (nonexistent) value of a void expression (an expression that has
type void) shall not be used in any way, and implicit or
explicit conversions (except to void) shall not be applied to
such an expression. If an expression of any other type is evaluated as
a void expression, its value or designator is discarded. (A void
expression is evaluated for its side effects.)
and 6.2.5 paragraph 19:
The void type comprises an empty set of values; it is an
incomplete object type that cannot be completed.
It's a compiler warning (-W unused-variable or -W all) they're suppressing by using it. You are correct in that __attribute__((unused)) is a valid C macro to do what you're asking, but it's a matter of preference. It's also not supported by all C compilers.
Sources:
http://www.keil.com/support/man/docs/armcc/armcc_chr1359124983230.htm
https://en.cppreference.com/w/cpp/compiler_support
void is an empty data type, it can be used in a different number of situations.
A function that "returns" void doesn't return anything (and by definition is a procedure, not a function).
A void* (pointer of void) is often used as a generic pointer (a pointer to a memory address with no particular data type associated with it). The compiler will let you assign this pointer to any other pointer type without need of explicit conversion.
malloc() for example, returns void* so you can do things like int* v = malloc(sizeof(int)*10)); without need of explicitly recasting the return value of malloc() to int*.
The other way around is also true, a function that takes void* as parameter will take any pointer type without need of explicit conversion.
I'm thinking about the difference between:
void *signal(int, void (*)(int))(int)
and
void (*signal(int, void (*)(int)))(int)
I know the latter is from here - Example #3: The ``Ultimate'' (it's a hilarious learning experience when I was trying speak out loud to understand it):
signal is a function takes (int, void (*)(int)) as input and returns a pointer to another function that takes (int) and returns void.
For the former I'm thinking that since the last (int) will have higher precedence than * so it should be a syntax error, but from cdecl.org the result is:
["] declare signal as function (int, pointer to function (int) returning void) returning function (int) returning pointer to void [."]
So I need a check.
One has to differentiate between grammar and semantics. cdecl.org only gives you the grammatical meaning of whatever declarator you type into it. In your first example, you have indeed a grammatically correct declaration of signal as a function returning a function. However, C does not allow functions to return other functions:
N1570 6.7.6.3 §1:
A function declarator shall not specify a return type that is a function type or an array type.
So while this declaration is grammatically correct, it is semantically invalid. In other words: While the C syntax makes it possible to write "function returning a function", you're not allowed to actually have a function that returns a function in a program. Just like the English language (or any language for that matter) also allows you to express all sorts of thoughts that would physically be impossible to carry out…
The most important part here is... you don't need to learn this, it is a very poorly designed part of the language. You can scroll down to the bottom of the answer to find the sane, professional solution.
Otherwise, if you insist, it goes like this...
When trying to return a function pointer from a function, the type of the function pointer gets split up. If you want to return a function pointer void(*)(void), then this poor function pointer gets split up in 3 parts. Lets call them like this:
void is A, the return type of the pointed-at function.
(*) is B, marking this a pointer to function, rather than a function.
(void) is C, the parameters of the pointed-at function.
Then if we want to stick this as a return type into some other icky function declaration, they end up like this:
#define A void
#define B *
#define C (void)
// A (B) C equals void(*)(void)
A (B madness(int, void (*fp)(int))) C;
where A, B and C are the parts of our poor function pointer to be returned, madness is the name of the function, and the rest is some mess used as parameters by the function itself.
If we omit the B part, it will be interpreted like a function returning another function of type void f (void); which isn't valid. The syntax allows it but not the language specification.
Similarly, int foo (void) [3]; - a function returning an array, is not allowed either.
Pondering these things is the road to madness and it makes the code unreadable. Professional programmers use typedef.
Given
void (*madness(int, void (*f)(int)))(int);
replace it with:
typedef void func_t (int);
func_t* sanity (int, func_t* f);
Learning and messing up with function pointers, I noticed a way to initialize void function pointers and cast them. Yet, although I don‘t receive any warning or error, either with GCC or VS’s compiler, I wanted to know whether it was dangerous or a bad practice to do this as I don't see this way of initializing function pointers often on the Internet. Moreover, do we call this generic function pointer?
#include <stdio.h>
#include <stdint.h>
#include <conio.h>
#define PAUSE (_getch())
uint16_t add(const uint16_t x, const uint16_t y) {
return x + y;
}
char chr(uint8_t test) {
return (char)test;
}
int main(void) {
void(*test)() = (void*)add;
const uint16_t x = 1, y = 1;
uint16_t value = ((uint16_t(*)())test)(x, y);
test = (void*)chr;
printf("%d\n", add(x, y)); // 2
printf("%d\n", value); // 2
printf("%c\n", ((char(*)())test)(100)); // d
PAUSE;
return 0;
}
Is this a generic function pointer
No, if I'm not terribly mistaken, there's no such thing as a "generic function pointer" in C.
and is it dangerous?
Yes, it is. It is evil.
There are a couple of things you need to know. First, unless you are running a system that conforms to POSIX,
void(*test)() = (void*)add;
is wrong. void * is a pointer-to-object type, and as such, it is not compatible with function pointers. (At least not in standard C -- as I mentioned, POSIX requires it to be compatible with function pointers too.)
The second thing is that void (*fp)() and void (*fp)(void) are different. The former declaration permits fp to take any number of parameters of any type, and the number of arguments and their types will be inferred when the compiler sees the first call to the function (pointer).
Another important aspect is that function pointers are guaranteed to be convertible across each other (AFAIK this manifests in them having the same representation and alignment requirements). This means that any function pointer can be assigned to (the address of) any function (after an appropriate cast), so long as you do not call a function through a pointer to an incompatible type. The behavior is well-defined if and only if you cast the pointer back to the original type before calling it.
So, if you want a "generic" function pointer, you can just write something like
typedef void (*fn_ptr)(void);
and then you could assign any pointer to function to an object of type fn_ptr. What you have to pay attention to is, again, the conversion to the right type when invoking the function, as in:
int add(int a, int b);
fn_ptr fp = (fn_ptr)add; // legal
fp(); // WRONG!
int x = ((int (*)(int, int))fp)(1, 2); // good
There are two serious problems here:
A cast from a function pointer to an object pointer (such as void *) triggers undefined behavior: in principle, it could crash your system (though in practice there are many systems where it will work fine). Instead of void *, it's better to use a function-pointer type for this purpose.
You're tricking the compiler into unknowingly passing an int to a function expecting a uint8_t. That's also undefined behavior, and it's very dangerous. Since the compiler doesn't know that it's doing this, it can't even take the most basic necessary steps to avoid smashing the stack — you're really gambling here. Similarly, this is a bit more subtle, but you're also tricking the compiler into passing two int-s into a function expecting two uint16_t-s.
And two lesser problems:
The notation for function pointer types on their own — e.g., in a cast — is confusing. I think it's better to use a typedef: typedef void (*any_func_ptr)(); any_func_ptr foo = (any_func_ptr)(bar).
It's undefined behavior to call a function pointer with a different signature than the actual function has. You can avoid that with careful coding — more careful than your current code — but it's tricky and risky.
You may corrupt the call stack with this, depending on the calling convention, specifically who's doing the cleanup: http://en.wikipedia.org/wiki/X86_calling_conventions With the callee cleanup, the compiler has no way of knowing how many variables you have passed on the stack at the point of cleanup, so passing the wrong number of parameters or parameters of the wrong size will end corrupting the call stack.
On x64, everyone uses the caller cleanup, so you're safe in this regard. The parameter values, however, will in general be a mess. In your example, on x64, they will be whatever was in the corresponding registers at the time.
C11 §6.3.2.3 (8) says:
A pointer to a function of one type may be converted to a pointer to a function of another type and back again; the result shall compare equal to the original pointer. If a converted pointer is used to call a function whose type is not compatible with the referenced type, the behavior is undefined.
And §6.7.6.3 (15) says about compatible types of functions:
[…] If one type has a parameter type list and the other type is specified by a function declarator that is not part of a function definition and that contains an empty identifier list, the parameter list shall not have an ellipsis terminator and the type of each parameter shall be compatible with the type that results from the application of the default argument promotions. […]
So, if you had add and chr to take int arguments (an int has at least a width of 16 bit) that would be OK (if you didn't cast the function pointer to void *), but, as it is, it is UB.
Let's say I have a function that accepts a void (*)(void*) function pointer for use as a callback:
void do_stuff(void (*callback_fp)(void*), void* callback_arg);
Now, if I have a function like this:
void my_callback_function(struct my_struct* arg);
Can I do this safely?
do_stuff((void (*)(void*)) &my_callback_function, NULL);
I've looked at this question and I've looked at some C standards which say you can cast to 'compatible function pointers', but I cannot find a definition of what 'compatible function pointer' means.
As far as the C standard is concerned, if you cast a function pointer to a function pointer of a different type and then call that, it is undefined behavior. See Annex J.2 (informative):
The behavior is undefined in the following circumstances:
A pointer is used to call a function whose type is not compatible with the pointed-to
type (6.3.2.3).
Section 6.3.2.3, paragraph 8 reads:
A pointer to a function of one type may be converted to a pointer to a function of another
type and back again; the result shall compare equal to the original pointer. If a converted
pointer is used to call a function whose type is not compatible with the pointed-to type,
the behavior is undefined.
So in other words, you can cast a function pointer to a different function pointer type, cast it back again, and call it, and things will work.
The definition of compatible is somewhat complicated. It can be found in section 6.7.5.3, paragraph 15:
For two function types to be compatible, both shall specify compatible return types127.
Moreover, the parameter type lists, if both are present, shall agree in the number of
parameters and in use of the ellipsis terminator; corresponding parameters shall have
compatible types. If one type has a parameter type list and the other type is specified by a
function declarator that is not part of a function definition and that contains an empty
identifier list, the parameter list shall not have an ellipsis terminator and the type of each
parameter shall be compatible with the type that results from the application of the
default argument promotions. If one type has a parameter type list and the other type is
specified by a function definition that contains a (possibly empty) identifier list, both shall
agree in the number of parameters, and the type of each prototype parameter shall be
compatible with the type that results from the application of the default argument
promotions to the type of the corresponding identifier. (In the determination of type
compatibility and of a composite type, each parameter declared with function or array
type is taken as having the adjusted type and each parameter declared with qualified type
is taken as having the unqualified version of its declared type.)
127) If both function types are ‘‘old style’’, parameter types are not compared.
The rules for determining whether two types are compatible are described in section 6.2.7, and I won't quote them here since they're rather lengthy, but you can read them on the draft of the C99 standard (PDF).
The relevant rule here is in section 6.7.5.1, paragraph 2:
For two pointer types to be compatible, both shall be identically qualified and both shall be pointers to compatible types.
Hence, since a void* is not compatible with a struct my_struct*, a function pointer of type void (*)(void*) is not compatible with a function pointer of type void (*)(struct my_struct*), so this casting of function pointers is technically undefined behavior.
In practice, though, you can safely get away with casting function pointers in some cases. In the x86 calling convention, arguments are pushed on the stack, and all pointers are the same size (4 bytes in x86 or 8 bytes in x86_64). Calling a function pointer boils down to pushing the arguments on the stack and doing an indirect jump to the function pointer target, and there's obviously no notion of types at the machine code level.
Things you definitely can't do:
Cast between function pointers of different calling conventions. You will mess up the stack and at best, crash, at worst, succeed silently with a huge gaping security hole. In Windows programming, you often pass function pointers around. Win32 expects all callback functions to use the stdcall calling convention (which the macros CALLBACK, PASCAL, and WINAPI all expand to). If you pass a function pointer that uses the standard C calling convention (cdecl), badness will result.
In C++, cast between class member function pointers and regular function pointers. This often trips up C++ newbies. Class member functions have a hidden this parameter, and if you cast a member function to a regular function, there's no this object to use, and again, much badness will result.
Another bad idea that might sometimes work but is also undefined behavior:
Casting between function pointers and regular pointers (e.g. casting a void (*)(void) to a void*). Function pointers aren't necessarily the same size as regular pointers, since on some architectures they might contain extra contextual information. This will probably work ok on x86, but remember that it's undefined behavior.
I asked about this exact same issue regarding some code in GLib recently. (GLib is a core library for the GNOME project and written in C.) I was told the entire slots'n'signals framework depends upon it.
Throughout the code, there are numerous instances of casting from type (1) to (2):
typedef int (*CompareFunc) (const void *a,
const void *b)
typedef int (*CompareDataFunc) (const void *b,
const void *b,
void *user_data)
It is common to chain-thru with calls like this:
int stuff_equal (GStuff *a,
GStuff *b,
CompareFunc compare_func)
{
return stuff_equal_with_data(a, b, (CompareDataFunc) compare_func, NULL);
}
int stuff_equal_with_data (GStuff *a,
GStuff *b,
CompareDataFunc compare_func,
void *user_data)
{
int result;
/* do some work here */
result = compare_func (data1, data2, user_data);
return result;
}
See for yourself here in g_array_sort(): http://git.gnome.org/browse/glib/tree/glib/garray.c
The answers above are detailed and likely correct -- if you sit on the standards committee. Adam and Johannes deserve credit for their well-researched responses. However, out in the wild, you will find this code works just fine. Controversial? Yes. Consider this: GLib compiles/works/tests on a large number of platforms (Linux/Solaris/Windows/OS X) with a wide variety of compilers/linkers/kernel loaders (GCC/CLang/MSVC). Standards be damned, I guess.
I spent some time thinking about these answers. Here is my conclusion:
If you are writing a callback library, this might be OK. Caveat emptor -- use at your own risk.
Else, don't do it.
Thinking deeper after writing this response, I would not be surprised if the code for C compilers uses this same trick. And since (most/all?) modern C compilers are bootstrapped, this would imply the trick is safe.
A more important question to research: Can someone find a platform/compiler/linker/loader where this trick does not work? Major brownie points for that one. I bet there are some embedded processors/systems that don't like it. However, for desktop computing (and probably mobile/tablet), this trick probably still works.
The point really isn't whether you can. The trivial solution is
void my_callback_function(struct my_struct* arg);
void my_callback_helper(void* pv)
{
my_callback_function((struct my_struct*)pv);
}
do_stuff(&my_callback_helper);
A good compiler will only generate code for my_callback_helper if it's really needed, in which case you'd be glad it did.
You have a compatible function type if the return type and parameter types are compatible - basically (it's more complicated in reality :)). Compatibility is the same as "same type" just more lax to allow to have different types but still have some form of saying "these types are almost the same". In C89, for example, two structs were compatible if they were otherwise identical but just their name was different. C99 seem to have changed that. Quoting from the c rationale document (highly recommended reading, btw!):
Structure, union, or enumeration type declarations in two different translation units do not formally declare the same type, even if the text of these declarations come from the same include file, since the translation units are themselves disjoint. The Standard thus specifies additional compatibility rules for such types, so that if two such declarations are sufficiently similar they are compatible.
That said - yeah strictly this is undefined behavior, because your do_stuff function or someone else will call your function with a function pointer having void* as parameter, but your function has an incompatible parameter. But nevertheless, i expect all compilers to compile and run it without moaning. But you can do cleaner by having another function taking a void* (and registering that as callback function) which will just call your actual function then.
As C code compiles to instruction which do not care at all about pointer types, it's quite fine to use the code you mention. You'd run into problems when you'd run do_stuff with your callback function and pointer to something else then my_struct structure as argument.
I hope I can make it clearer by showing what would not work:
int my_number = 14;
do_stuff((void (*)(void*)) &my_callback_function, &my_number);
// my_callback_function will try to access int as struct my_struct
// and go nuts
or...
void another_callback_function(struct my_struct* arg, int arg2) { something }
do_stuff((void (*)(void*)) &another_callback_function, NULL);
// another_callback_function will look for non-existing second argument
// on the stack and go nuts
Basically, you can cast pointers to whatever you like, as long as the data continue to make sense at run-time.
Well, unless I understood the question wrong, you can just cast a function pointer this way.
void print_data(void *data)
{
// ...
}
((void (*)(char *)) &print_data)("hello");
A cleaner way would be to create a function typedef.
typedef void(*t_print_str)(char *);
((t_print_str) &print_data)("hello");
If you think about the way function calls work in C/C++, they push certain items on the stack, jump to the new code location, execute, then pop the stack on return. If your function pointers describe functions with the same return type and the same number/size of arguments, you should be okay.
Thus, I think you should be able to do so safely.
Void pointers are compatible with other types of pointer. It's the backbone of how malloc and the mem functions (memcpy, memcmp) work. Typically, in C (Rather than C++) NULL is a macro defined as ((void *)0).
Look at 6.3.2.3 (Item 1) in C99:
A pointer to void may be converted to or from a pointer to any incomplete or object type