it's common for generic function argument to be defined as void* because they allow the largest size variable. presumably the function referenced by the generic function pointer knows how to handle the argment
looks like these are constants, not ptrs. presumably you defined them as ptrs because they need to be cast as (void*) arguments, but they don't need to be ptrs to be cast as void *
when i tried recasting the void* argument to int, i get a loss of precision error. but it works when casting it to long. once cast as long it can be cast to smaller types
#include <stdio.h>
enum { Red, Green, Blue };
const char color1 = Green;
void
func (
void *arg)
{
long col = (long) arg;
char c = col;
printf ("%s: %ld %d\n", __func__, col, c);
}
int
main ()
{
func ((void*) color1);
func ((void*) Blue);
return 0;
}
An int (default for your enum) is 2 bytes on a UNO and so is a pointer so that works and the actual two bytes were passed but if you wanted to pass a real value like a long then if would fail on architectures where pointers are only two bytes. ➜ bad idea and not commonly done for value.
It’s really used for pointers like you find in memcpy() or memcmp()
i believe i understand what you're trying to say -- you can pass any type of value as long as you pass a ptr to it. And yes, the C++ compiler generated an error when i tried casting a void* to a char, but the C compiler only generated a warning.
what i've seen is defining a type of largest possible size to accommodate any type of argument, ptr or not. i've posted code showing how a char can be passed
void* is an idiom, how can you have a ptr to a void. it means a value with unspecified type (not just void). i know you're going to say "but it's still a ptr".
A pointer can be converted to any integral type large enough to hold all values of its type (e.g. to std::uintptr_t)
A value of any integral or enumeration type can be converted to a pointer type. A pointer converted to an integer of sufficient size and back to the same pointer type is guaranteed to have its original value, otherwise the resulting pointer cannot be dereferenced safely (the round-trip conversion in the opposite direction is not guaranteed; the same pointer may have multiple integer representations) The null pointer constant NULL or integer zero is not guaranteed to yield the null pointer value of the target type; static_cast or implicit conversion should be used for this purpose.
Indeed - it is…. Really not a good option.
If you want to accept various types of data and want to deal with them as a byte array for example then use void* and pass the pointer.
Anything else is not common practice nor recommended
I think the more likely explanation is that they at some point they added a diagnostic for it, and to avoid breaking old code bases, they made it a warning instead of an error.
When casting a pointer to an integer, there are only two main scenarios:
The pointer is actually a pointer to something. Converting it to an integer is only meaningful if you either A. later convert it back to a pointer, or B. use it as a unique integer for printing the address, using it as an index in some associative data structure, etc.
In both cases, converting the pointer to an integer type that's too small to represent all pointer values is a bug.
The pointer doesn't actually point to anything, but it's the result of an earlier cast from an integer to a pointer (e.g. reinterpret_cast<void *>(42)). In this case, casting the pointer back to an integer is meaningless, because you're not guaranteed to get back the original integer.
Then you ─ very carefully ─ use a const_cast: casting a pointer-to-const to a pointer-to-nonconst is allowed, as long as you don't use the pointer-to-nonconst to actually write to a constant object.
In this case, you can probably use C++'s std::thread, which makes this a non-issue, because it passes any arguments to the function, in a type-safe way:
If you need a specific configuration (task name, stack size, pinning to a specific core, etc.), you can use the esp_pthread_set_cfg() function before creating your threads.
We use a C++ compiler here. C let you do lots of things but the number of bytes allocated for a pointer is known and won’t fit larger data types so even in C it’s not a good idea
i don't understand why when copying data, the assumption is to copy the larger into the smaller instead of copying what fits into the smaller (which appear to be what c++ does).
the following works in C++. the long is truncated the size of char
void
func (
void *arg)
{
long col = (long) arg;
char c = col;
printf ("%s: %ld %d\n", __func__, col, c);
}
func: 0x120a 10
i don't understand why the compiler reports a loss of precision when going from (void*) to char, but not when going from long to char.