I have a question about void*. I have a function which captures blocks of 0.2 sec of audio by microphone. I have to process these blocks, in concrete a convolution.
This function returns these blocks of audio as a void * . To process this information I can't use void * because I can't access to them, so I have to convert in other kind of data, for example double but I don't know which length is assigned to this new pointer or how can I do it.
My code:
void Pre_proc_mono::PreProcess(void *data, int lenbytes, float t_max){
double * aux = (double*) data;
}
Now, aux's length is lenbytes too? Or I have to do something like:
int size = lenbytes/sizeof(double);
How can I make this work?
A pointer is an address in memory. This is the address of the first byte of data. The type of the pointer tells you how long is the data. So if we have
int *p
the value of p tells you where the data starts, and the type of the pointer, in this case int * tells you that from that address you need to take 4 bytes (on most architectures).
A void * pointer has only the starting address, but not the length of the data, so that's why you can't dereference a void * pointer.
sizeof(p) where p is a pointer (of any type) is the size of the pointer, and has nothing to do with the kind of data you find where the pointer points to
for instance:
sizeof(char) == 1
sizeof(char *) == 4
sizeof(void *) == 4
In your function:
void *data, int lenbytes, float t_max
data is a pointer to where the data starts, lenbytes is how many bytes the data has.
So you can have something like:
uint8_t *aux = (uint8_t*) data;
and you have a vector of lenbytes elements of type uint8_t (uint8_t is guaranteed to have 1 byte).
Or something like this:
double * aux = (double*) data;
and you have a vector of lenbutes/sizeof(double) elements of type double. But you need to be careful so that lenbytes is a multiple of sizeof(double).
Edit
And as regarding to what you should convert to, the answer depends on only the format of your blocks of data. Read the documentation, or search for an example.
Related
I am learning C++ using C++ Primer 5th edition. In particular, i read about void*. There it is written that:
We cannot use a void* to operate on the object it addresses—we don’t know that object’s type, and the type determines what operations we can perform on that object.
void*: Pointer type that can point to any nonconst type. Such pointers may not
be dereferenced.
My question is that if we're not allowed to use a void* to operate on the object it addressess then why do we need a void*. Also, i am not sure if the above quoted statement from C++ Primer is technically correct because i am not able to understand what it is conveying. Maybe some examples can help me understand what the author meant when he said that "we cannot use a void* to operate on the object it addresses". So can someone please provide some example to clarify what the author meant and whether he is correct or incorrect in saying the above statement.
My question is that if we're not allowed to use a void* to operate on the object it addressess then why do we need a void*
It's indeed quite rare to need void* in C++. It's more common in C.
But where it's useful is type-erasure. For example, try to store an object of any type in a variable, determining the type at runtime. You'll find that hiding the type becomes essential to achieve that task.
What you may be missing is that it is possible to convert the void* back to the typed pointer afterwards (or in special cases, you can reinterpret as another pointer type), which allows you to operate on the object.
Maybe some examples can help me understand what the author meant when he said that "we cannot use a void* to operate on the object it addresses"
Example:
int i;
int* int_ptr = &i;
void* void_ptr = &i;
*int_ptr = 42; // OK
*void_ptr = 42; // ill-formed
As the example demonstrates, we cannot modify the pointed int object through the pointer to void.
so since a void* has no size(as written in the answer by PMF)
Their answer is misleading or you've misunderstood. The pointer has a size. But since there is no information about the type of the pointed object, the size of the pointed object is unknown. In a way, that's part of why it can point to an object of any size.
so how can a int* on the right hand side be implicitly converted to a void*
All pointers to objects can implicitly be converted to void* because the language rules say so.
Yes, the author is right.
A pointer of type void* cannot be dereferenced, because it has no size1. The compiler would not know how much data he needs to get from that address if you try to access it:
void* myData = std::malloc(1000); // Allocate some memory (note that the return type of malloc() is void*)
int value = *myData; // Error, can't dereference
int field = myData->myField; // Error, a void pointer obviously has no fields
The first example fails because the compiler doesn't know how much data to get. We need to tell it the size of the data to get:
int value = *(int*)myData; // Now fine, we have casted the pointer to int*
int value = *(char*)myData; // Fine too, but NOT the same as above!
or, to be more in the C++-world:
int value = *static_cast<int*>(myData);
int value = *static_cast<char*>(myData);
The two examples return a different result, because the first gets an integer (32 bit on most systems) from the target address, while the second only gets a single byte and then moves that to a larger variable.
The reason why the use of void* is sometimes still useful is when the type of data doesn't matter much, like when just copying stuff around. Methods such as memset or memcpy take void* parameters, since they don't care about the actual structure of the data (but they need to be given the size explicitly). When working in C++ (as opposed to C) you'll not use these very often, though.
1 "No size" applies to the size of the destination object, not the size of the variable containing the pointer. sizeof(void*) is perfectly valid and returns, the size of a pointer variable. This is always equal to any other pointer size, so sizeof(void*)==sizeof(int*)==sizeof(MyClass*) is always true (for 99% of today's compilers at least). The type of the pointer however defines the size of the element it points to. And that is required for the compiler so he knows how much data he needs to get, or, when used with + or -, how much to add or subtract to get the address of the next or previous elements.
void * is basically a catch-all type. Any pointer type can be implicitly cast to void * without getting any errors. As such, it is mostly used in low level data manipulations, where all that matters is the data that some memory block contains, rather than what the data represents. On the flip side, when you have a void * pointer, it is impossible to determine directly which type it was originally. That's why you can't operate on the object it addresses.
if we try something like
typedef struct foo {
int key;
int value;
} t_foo;
void try_fill_with_zero(void *destination) {
destination->key = 0;
destination->value = 0;
}
int main() {
t_foo *foo_instance = malloc(sizeof(t_foo));
try_fill_with_zero(foo_instance, sizeof(t_foo));
}
we will get a compilation error because it is impossible to determine what type void *destination was, as soon as the address gets into try_fill_with_zero. That's an example of being unable to "use a void* to operate on the object it addresses"
Typically you will see something like this:
typedef struct foo {
int key;
int value;
} t_foo;
void init_with_zero(void *destination, size_t bytes) {
unsigned char *to_fill = (unsigned char *)destination;
for (int i = 0; i < bytes; i++) {
to_fill[i] = 0;
}
}
int main() {
t_foo *foo_instance = malloc(sizeof(t_foo));
int test_int;
init_with_zero(foo_instance, sizeof(t_foo));
init_with_zero(&test_int, sizeof(int));
}
Here we can operate on the memory that we pass to init_with_zero represented as bytes.
You can think of void * as representing missing knowledge about the associated type of the data at this address. You may still cast it to something else and then dereference it, if you know what is behind it. Example:
int n = 5;
void * p = (void *) &n;
At this point, p we have lost the type information for p and thus, the compiler does not know what to do with it. But if you know this p is an address to an integer, then you can use that information:
int * q = (int *) p;
int m = *q;
And m will be equal to n.
void is not a type like any other. There is no object of type void. Hence, there exists no way of operating on such pointers.
This is one of my favourite kind of questions because at first I was also so confused about void pointers.
Like the rest of the Answers above void * refers to a generic type of data.
Being a void pointer you must understand that it only holds the address of some kind of data or object.
No other information about the object itself, at first you are asking yourself why do you even need this if it's only able to hold an address. That's because you can still cast your pointer to a more specific kind of data, and that's the real power.
Making generic functions that works with all kind of data.
And to be more clear let's say you want to implement generic sorting algorithm.
The sorting algorithm has basically 2 steps:
The algorithm itself.
The comparation between the objects.
Here we will also talk about pointer functions.
Let's take for example qsort built in function
void qsort(void *base, size_t nitems, size_t size, int (*compar)(const void *, const void*))
We see that it takes the next parameters:
base − This is the pointer to the first element of the array to be sorted.
nitems − This is the number of elements in the array pointed by base.
size − This is the size in bytes of each element in the array.
compar − This is the function that compares two elements.
And based on the article that I referenced above we can do something like this:
int values[] = { 88, 56, 100, 2, 25 };
int cmpfunc (const void * a, const void * b) {
return ( *(int*)a - *(int*)b );
}
int main () {
int n;
printf("Before sorting the list is: \n");
for( n = 0 ; n < 5; n++ ) {
printf("%d ", values[n]);
}
qsort(values, 5, sizeof(int), cmpfunc);
printf("\nAfter sorting the list is: \n");
for( n = 0 ; n < 5; n++ ) {
printf("%d ", values[n]);
}
return(0);
}
Where you can define your own custom compare function that can match any kind of data, there can be even a more complex data structure like a class instance of some kind of object you just define. Let's say a Person class, that has a field age and you want to sort all Persons by age.
And that's one example where you can use void * , you can abstract this and create other use cases based on this example.
It is true that is a C example, but I think, being something that appeared in C can make more sense of the real usage of void *. If you can understand what you can do with void * you are good to go.
For C++ you can also check templates, templates can let you achieve a generic type for your functions / objects.
In C++ I had:
MallocMetadata *tmp = static_cast<MallocMetadata *> (p);
But now I want tmp to be 5 bytes before in memory so I tried:
MallocMetadata *tmp = static_cast<MallocMetadata *> (p-5);
But that didn't compile, I read some articles which suggested this (and didn't work too):
MallocMetadata *tmp = static_cast<MallocMetadata *> (static_cast<char *> (p) - 5);
How to fix this problem, please note: I am sure that place in memory is legal plus I want tmp to be of type MallocMetadata* to use it later.
You can use reinterpret_cast to convert pointers other than void* to another pointers.
MallocMetadata *tmp = reinterpret_cast<MallocMetadata *> (static_cast<char *> (p) - 5);
Another choice is casting the char* after subtracting something to void* again.
MallocMetadata *tmp = static_cast<MallocMetadata *> (static_cast<void *> (static_cast<char *> (p) - 5));
C++ How to Advance void * pointer?
It is not possible to advance a void*.
Advancing a pointer by one modifies the pointer to point to the next sibling of the previously pointed object within an array of objects. The distance between two elements of an array differs between objects of different types. The distance is exactly the same as the size of the object.
Thus to advance a pointer, it is necessary to know the size of the pointed object. void* can point to an object of any size, and there is no way to get information about that size from the pointer.
What you can do instead is static cast void* to the dynamic type of the pointed object. The size of the pointed object is then known by virtue of knowing the type of the pointer, as long as the type is complete. You can then use pointer arithmetic to advance the converted pointer to a sibling of the pointed object.
But now I want tmp to be 5 bytes before in memory
Before we proceed any further, I want to make it clear that this is an unsafe thing to attempt, and you must know the language rules in detail to have even a remote chance of doing this correctly. I urge you to consider whether doing this is necessary.
To get a pointer to the memory address 5 bytes before, you can static_cast void* to unsigned char* and do pointer arithmetic on the converted pointer:
static_cast<unsigned char*>(p) - 5
MallocMetadata *tmp = static_cast<MallocMetadata *> (static_cast<char *> (p) - 5);
char* isn't static-castable to arbitrary object pointer types. if the memory address is properly aligned and ((the address contains an object of similar type) or (MallocMetadata is a trivial type and the address doesn't contain an object of another type and you're going to write to the address and not read, thereby creating a new object)), then you can use reinterpret_cast instead:
MallocMetadata *tmp = reinterpret_cast<MallocMetadata*>(
static_cast<char*>(p) - 5
);
A full example:
// preparation
int offset = 5;
std::size_t padding = sizeof(MallocMetadata) >= offset
? 0
: sizeof(MallocMetadata) - offset;
auto align = static_cast<std::align_val_t>(alignof(MallocMetadata));
void* p_storage = ::operator new(sizeof(MallocMetadata) + padding, align);
MallocMetadata* p_mm = new (p_storage) MallocMetadata{};
void* p = reinterpret_cast<char*>(p_mm) + offset;
// same as above
MallocMetadata *tmp = reinterpret_cast<MallocMetadata*>(
static_cast<char*>(p) - offset
);
// cleanup
tmp->~MallocMetadata();
::operator delete(tmp);
I don't know what you'll make of this, but I'll try:
There's a requirement in the standard that void * and character pointers have the same representation and alignment that falls out of C and how historically you had character pointer types where you now have void *.
If you have a void *, actually a void * and not some other type of pointer, and you wanted to advance it a byte at a time, you should be able to create a reference-to-pointer-to-unsigned-character bound to the pointer-to-void, as in:
auto &ucp = reinterpret_cast<unsigned char *&>(void_pointer);
And now it should be possible to manipulate void_pointer through operations on ucp reference.
So ++ucp will advance it, and therefore void_pointer, by one.
void Manager::byteArrayToDoubleArray(byte ch[]) {
int counter = 0;
// temp array to break the byte array into size of 8 and read it
byte temp[64];
// double result values
double res[8];
int index = 0;
int size = (sizeof(ch) / sizeof(*ch));
for (int i = 0; i < size; i++) {
counter++;
temp[i] = ch[i];
if (counter % 8 == 0) {
res[index] = *reinterpret_cast<double * const>(temp);
index++;
counter = 0;
}
}
}
Here result would be a list of double values with count = 8.
Your problem is two things. You have some typos and misunderstanding. And the C++ standard is somewhat broken in this area.
I'll try to fix both.
First, a helper function called laundry_pods. It takes raw memory and "launders" it into an array of a type of your choice, so long as you pick a pod type:
template<class T, std::size_t N>
T* laundry_pods( void* ptr ) {
static_assert( std::is_pod<std::remove_cv_t<T>>{} );
char optimized_away[sizeof(T)*N];
std::memcpy( optimized_away, ptr , sizeof(T)*N );
T* r = ::new( ptr ) T[N];
assert( r == ptr );
std::memcpy( r, optimized_away, sizeof(T)*N );
return r;
}
now simply do
void Manager::byteArrayToDoubleArray(byte ch[]) {
double* pdouble = laundry_pods<double, 8>(ch);
}
and pdouble is a pointer to memory of ch interpreted as an array of 8 doubles. (It is not a copy of it, it interprets those bytes in-place).
While laundry_pods appears to copy the bytes around, both g++ and clang optimize it down into a binary noop. The seeming copying of bytes around is a way to get around aliasing restrictions and object lifetime rules in the C++ standard.
It relies on arrays of pod not having extra bookkeeping overhead (which C++ implementations are free to do; none do that I know of. That is what the non-static assert double-checks), but it returns a pointer to a real honest to goodness array of double. If you want to avoid that assumption, you could instead create each doulbe as a separate object. However, then they aren't an array, and pointer arithmetic over non-arrays is fraught as far as the standard is concerned.
The use of the term "launder" has to do with getting around aliasing and object lifetime requirements. The function does nothing at runtime, but in the C++ abstract machine it takes the memory and converts it into binary identical memory that is now a bunch of doubles.
The trick of doing this kind of "conversion" is to always cast the double* to a char* (or unsigned char or std::byte). Never the other way round.
You should be able to do something like this:
void byteArrayToDoubleArray(byte* in, std::size_t n, double* out)
{
for(auto out_bytes = (byte*) out; n--;)
*out_bytes++ = *in++;
}
// ...
byte ch[64];
// .. fill ch with double data somehow
double res[8];
byteArrayToDoubleArray(ch, 64, res);
Assuming that type byte is an alias of char or unsigned char or std::byte.
I am not completly sure what you are trying to achieve here because of the code (sizeof(ch) / sizeof(*ch)) which does not make sense for an array of undefined size.
If you have a byte-Array (POD data type; something like a typedef char byte;) then this most simple solution would be a reinterpret_cast:
double *result = reinterpret_cast<double*>(ch);
This allows you to use result[0]..result[7] as long as ch[] is valid and contains at least 64 bytes. Be aware that this construct does not generate code. It tells the compiler that result[0] corresponds to ch[0..7] and so on. An access to result[] will result in an access to ch[].
But you have to know the number of elements in ch[] to calculate the number of valid double elements in result.
If you need a copy (because - for example - the ch[] is a temporary array) you could use
std::vector<double> result(reinterpret_cast<double*>(ch), reinterpret_cast<double*>(ch) + itemsInCh * sizeof(*ch) / sizeof(double));
So if ch[] is an array with 64 items and a byte is really an 8-bit value, then
std::vector<double> result(reinterpret_cast<double*>(ch), reinterpet_cast<double*>(ch) + 8);
will provide a std::vector containing 8 double values.
There is another possible method using a union:
union ByteToDouble
{
byte b[64];
double d[8];
} byteToDouble;
the 8 double values will occupie the same memory as the 64 byte values. So you can write the byte values to byteToDouble.b[] and read the resultingdouble values from byteToDouble.d[].
using namespace std;
#include<iostream>
int main()
{
struct node
{
int data;
struct node *next;
};
struct node *node1;
node1 = (struct node*)malloc(sizeof(node));
node1->data = 5;
node1->next = NULL;
cout<<"node data value "<<node1->data<<endl;
int *vara;
cout<<"size of struct node pointer with * "<<sizeof(*node1)<<endl; // size is 8
cout<<"size of struct node pointer without * "<<sizeof(node1)<<endl; // size is 4
cout<<"size of integer pointer variable with * "<<sizeof(*vara)<<endl; // size is 4
cout<<"size of integer pointer variable with * "<<sizeof(*vara)<<endl; // size is 4 in this case as well
}
Why is there some difference in the size when used with * operator and without * operator for a pointer pointing to a struct variable ?
Executed the above code in CodeBlocks, Language C++.
Short answer: because node1 is a pointer and *node1 is a node, and these have different sizes.
Longer answer:
Let's examine the type of each of the expressions you are passing to the sizeof operator:
*node1 has type node, which consists of an int and a node*, both of which has size 4 bytes on your platform, hence making the total size 8 bytes.
node1 has type node*, which is a pointer. On your platform, pointers are 4 bytes long.
*vara has type int, which is an integer. On your platform, integers are 4 bytes long.
vara has type int*, which is a pointer. On your platform, pointers are 4 bytes long.
The first sizeof returns the size of the struct (the size of an int + the size of a pointer) , the second one the size of a pointer to a struct (4 bytes on your machine) the third one the size of an integer.
Why is there some difference in the size when used with "" operator and without "" operator for a pointer pointing to a struct variable ?
Because they are different types. In this declaration:
node *ptr;
ptr has type pointer to node, while *ptr has type node. In your third and forth example looks like you wanted to compare int vs int *. The fact that you get the same size for int * and int is just a coincidence and happened to be the same on your platform. You cannot either rely on that nor deduce any rules from that fact.
It is because a pointer, in this case, has the same size (4 bytes) than an integer, but your node structure's size is 8 bytes.
When you ask for sizeof(a) when a is a pointer, you ask for the size of the pointer. When you ask for sizeof(*a), you ask for the size of what is pointed by a.
In the following lines of code, I need to adjust the pointer pm by an offset in bytes in one of its fields. Is there an better/easier way to do this, than incessantly casting back and forth from char * and PartitionMap * such that the pointer arithmetic still works out?
PartitionMap *pm(reinterpret_cast<PartitionMap *>(partitionMaps));
for ( ; index > 0 ; --index)
{
pm = (PartitionMap *)(((char *)pm) + pm->partitionMapLength);
}
return pm;
For those that can't grok from the code, it's looping through variable length descriptors in a buffer that inherit from PartitionMap.
Also for those concerned, partitionMapLength always returns lengths that are supported by the system this runs on. The data I'm traversing conforms to the UDF specification.
I often use these templates for this:
template<typename T>
T *add_pointer(T *p, unsigned int n) {
return reinterpret_cast<T *>(reinterpret_cast<char *>(p) + n);
}
template<typename T>
const T *add_pointer(const T *p, unsigned int n) {
return reinterpret_cast<const T *>(reinterpret_cast<const char *>(p) + n);
}
They maintain the type, but add single bytes to them, for example:
T *x = add_pointer(x, 1); // increments x by one byte, regardless of the type of x
Casting is the only way, whether it's to a char* or intptr_t or other some such type, and then to your final type.
You can of course just keep two variables around: a char * to step through the buffer and a PartitionMap * to access it. Makes it a little clearer what's going on.
for (char *ptr = ??, pm = (PartitionMap *)ptr ; index > 0 ; --index)
{
ptr += pm->partitionMapLength;
pm = (PartitionMap *)ptr;
}
return pm;
As others have mentioned you need the casts, but you can hide the ugliness in a macro or function. However, one other thing to keep in mind is alignment requirements. On most processors you can't simply increment a pointer to a type by an arbitrary number of bytes and cast the result back into a pointer to the original type without problems accessing the struct through the new pointer due to misalignment.
One of the few architectures (even if it is about the most popular) that will let you get away with it is the x86 architecture. However, even if you're writing for Windows, you'll want to take this problem into account - Win64 does enforce alignment requirements.
So even accessing the partitionMapLength member through the pointer might crash your program.
You might be able to easily work around this problem using a compiler extension like __unaligned on Windows:
PartitionMap __unaliged *pm(reinterpret_cast<PartitionMap *>(partitionMaps));
for ( ; index > 0 ; --index)
{
pm = (PartitionMap __unaligned *)(((char *)pm) + pm->partitionMapLength);
}
return pm;
Or you can copy the potentially unaligned data into a properly aligned struct:
PartitionMap *pm(reinterpret_cast<PartitionMap *>(partitionMaps));
char* p = reinterpret_cast<char*>( pm);
ParititionMap tmpMap;
for ( ; index > 0 ; --index)
{
p += pm->partitionMapLength;
memcpy( &tmpMap, p, sizeof( newMap));
pm = &tmpMap;
}
// you may need a more spohisticated copy to return something useful
size_t siz = pm->partitionMapLength;
pm = reinterpret_cast<PartitionMap*>( malloc( siz));
if (pm) {
memcpy( pm, p, siz);
}
return pm;
The casting has to be done, but it makes the code nearly unreadable. For readability's sake, isolate it in a static inline function.
What is puzzling me is why you have 'partitionMapLength' in bytes?
Wouldn't it be better if it was in 'partitionMap' units since you anyway cast it?
PartitionMap *pmBase(reinterpret_cast<PartitionMap *>(partitionMaps));
PartitionMap *pm;
...
pm = pmBase + index; // just guessing about your 'index' variable here
Both C and C++ allow you to iterate through an array via pointers and ++:
#include <iostream>
int[] arry = { 0, 1, 2, 3 };
int* ptr = arry;
while (*ptr != 3) {
std::cout << *ptr << '\n';
++ptr;
}
For this to work, adding to pointers is defined to take the memory address stored in the pointer and then add the sizeof whatever the type is times the value being added. For instance, in our example ++ptr adds 1 * sizeof(int) to the memory address stored in ptr.
If you have a pointer to a type, and want to advance a particular number of bytes from that spot, the only way to do so is to cast to char* (because sizeof(char) is defined to be one).