Casting void pointers, depending on data (C++) - c++

Basically what I want to do is, depending on the some variable, to cast a void pointer into a different datatype. For example (the 'cast' variable is just something in order to get my point across):
void* ptr = some data;
int temp = some data;
int i = 0;
...
if(temp == 32) cast = (uint32*)
else if(temp == 16) cast = (uint16*)
else cast = (uint8*)
i = someArray[*((cast)ptr)];
Is there anything in C++ that can do something like this (since you can't actually assign a variable to be just (uint32*) or something similar)? I apologize if this isn't clear, any help would be greatly appreciated.

The "correct" way:
union MyUnion
{
uint32 asUint32;
uint16 asUint16;
uint8 asUint8;
}
uint32 to_index(int size, MyUnion* ptr)
{
if (size== 32) return ptr->asUint32;
if (size== 16) return ptr->asUint16;
if (size== 8) return ptr->asUint8;
}
i = someArray[to_index(temp,ptr)]
[update: fixed dumb typo]

Clearly, boost::variant is the way to go. It already stores a type-tag that makes it impossible for you to cast to the wrong type, ensuring this using the help of the compiler. Here is how it works
typedef boost::variant<uint32_t*, uint16_t*, uint8_t*> v_type;
// this will get a 32bit value, regardless of what is contained. Never overflows
struct PromotingVisitor : boost::static_visitor<uint32_t> {
template<typename T> uint32_t operator()(T* t) const { return *t; }
};
v_type v(some_ptr); // may be either of the three pointers
// automatically figures out what pointer is stored, calls operator() with
// the correct type, and returns the result as an uint32_t.
int i = someArray[boost::apply_visitor(PromotingVisitor(), v)];

A cleaner solution:
uint32 to_index(int temp, void* ptr) {
if (temp == 32) return *((uint32*)ptr);
if (temp == 16) return *((uint16*)ptr);
if (temp == 8) return *((uint8*)ptr);
assert(0);
}
i = someArray[to_index(temp,ptr)]

It sounds like maybe you're after a union, or if you're using Visual Studio a _variant_t. Or maybe typeinfo() would be helpful? (To be honest, I'm not quite sure exactly what you're trying to do).
As far as the casts, you can cast just about anything to anything -- that's what makes C++ dangerous (and powerful if you're really careful).
Also, note that pointer values are 32-bit or 64-bit in most platforms, so you couldn't store a uint64 in a void* on a 32-bit platform.
Finally, maybe this is what you want:
void* p = whatever;
uint32 x = (uint32)p;
or maybe
uint32 source = 6;
void* p = &source;
uint32 dest = *((uint32*)p);
void* p =

If you were locked into using a void ptr, and absolutely needed to call [] with different types:
template <typename cast_to>
inline
int get_int_helper(someArray_t someArray, void* ptr) {
return someArray[*static_cast<cast_to*>(ptr)];
}
int get_int(someArray_t someArray, void* ptr, int temp) {
switch ( temp ) {
case 32: return get_int_helper<uint32>(someArray,ptr);
case 16: return get_int_helper<uint16>(someArray,ptr);
default: return get_int_helper<uint8>(someArray,ptr);
}
}
However, as others have pointed out; there are probably better/other ways to do it. Most likely, whatever array you have doesn't have multiple operator[], so it doesn't need the different types. In addition, you could be using boost::variant to hold a discriminated union of the types so you wouldn't have to pass around temp

It seems you want to store the "cast" function that takes a void* and produces an unsigned integer. So, make it a function:
std::map<int, boost::function<unsigned(*)(void*)> casts;
template <typename T> unsigned cast(void* v) { return *(T*)v; }
casts[32] = cast<uint32>;
casts[16] = cast<uint16>;
casts[8] = cast<uint8>;
casts[128] = MySpecialCastFromDouble;
void* foo = getFoo();
unsigned bar = casts[16](foo);

Related

Casting a reference to a pointer to a reference to a void*

Is the following well defined behavior?
#include <cstdlib>
#include <iostream>
void reallocate_something(void *&source_and_result, size_t size) {
void *dest = malloc(size);
memcpy(dest, source_and_result, size);
free(source_and_result);
source_and_result = dest;
}
void reallocate_something(int *&source_and_result, size_t size) {
// I the cast safe in this use case?
reallocate_something(reinterpret_cast<void*&>(source_and_result), size);
}
int main() {
const size_t size = 4 * sizeof(int);
int *start = static_cast<int*>(malloc(size));
*start = 0;
std::cout << start << ' ' << *start << '\n';
reallocate_something(start, size);
std::cout << start << ' ' << *start << '\n';
return 0;
}
The code uses a reinterpret_cast to pass a reference to a pointer and re-allocate it, free it, and set it to the new area allocated. Is this well defined?
In particular A static_cast would work if I did not want to pass a reference, and that would be well defined.
The tag is C++, and I'm asking about this code as-is within the C++ standard.
Is the following well defined behavior?
No, it's not. You can't interpret int * pointer with void * handle, int and void are not similar types. You can convert an int * pointer to void * and back. If your function takes a reference, to do the conversion you need a new temporary variable of type void * to hold the result of the conversion, and then you have to assign it back, like in the other answer https://stackoverflow.com/a/69641609/9072753 .
Anyway, just make it a template, and write nice C++ code with placement new. Something along:
template<typename T>
void reallocate_something(T *&pnt, size_t cnt) {
T *dest = reinterpret_cast<T *>(malloc(cnt * sizeof(T)));
if (dest == NULL) throw ...;
for (size_t i = 0; i < cnt; ++i) {
new (dest[i]) T(pnt[i]);
}
free(static_cast<void*>(pnt));
pnt = dest;
}
Actually I'm not sure but I feel this is the correct way to do.
#include <iostream>
#include <cstring>
void reallocate_something(void *&source_and_result, size_t size) {
void *dest = malloc(size);
memcpy(dest, source_and_result, size);
free(source_and_result);
source_and_result = dest;
}
void reallocate_something(int *&source_and_result, size_t size) {
// Is the cast safe in this use case?
void *temp = static_cast<void*>(source_and_result);
reallocate_something(temp, size);
source_and_result = static_cast<int*>(temp);
}
int main() {
const size_t size = 4 * sizeof(int);
int *start = static_cast<int*>(malloc(size));
std::cout << start << ' ' << *start << '\n';
reallocate_something(start, size);
std::cout << start << ' ' << *start << '\n';
return 0;
}
This is not well defined for void* and int* are not similar. Refer to Type aliasing section here.
Note that pointer round trip via void* like below is well defined. Particularly, there is no type aliasing here.
T* pt = ...;
void* p = pt;
auto pt2 = static_cast<T*>(p);
assert(pt2 == pt);
This is different from following code with type aliasing which is not well defined.
T* pt = ...;
void* p = nullptr;
reinterpret_cast<T*&>(p) = pt; // or *reinterpret_cast<T**>(&p) = pt;
auto pt2 = static_cast<T*>(p);
assert(pt2 == pt);
It follows that your sample code can be revised as below.
void reallocate_something(int *&source_and_result, size_t size) {
void* p = source_and_result;
reallocate_something(p, size);
source_and_result = static_cast<int*>(p);
}
Or better yet
void* reallocate_something(void *source_and_result, size_t size) {
void *dest = malloc(size);
memcpy(dest, source_and_result, size);
free(source_and_result);
return dest;
}
void reallocate_something(int *&source_and_result, size_t size) {
source_and_result = static_cast<int*>(reallocate_something(source_and_result, size));
}
There exist platforms where the bitwise representations of int* and void* are incompatible. On such platforms, it would be often be impossible for a compiler to allow a reference of one type to meaningfully act upon an object of the other, and the Standard thus refrains from requiring that implementations do so.
Of course, the vast majority of platforms use the same representation for all PODS pointer types, and when the Standard was written it was obvious to pretty much everyone that (1) it allowed compilers for such platforms to process reference type casts usefully, and (2) compilers should process such casts usefully except when there was a compelling reason to do otherwise. It was expected that the only compiler writers who would care about whether such conversions had defined behavior would be those targeting platforms where such support would be expensive (e.g. requiring that any int* whose address is taken be stored using the same bit pattern as void*, even if that would require shuffling its bits around when using it to fetch an int), and compiler writers were expected know more about the costs and benefits of such support than the Committee ever could.
Most implementations can be configured to process such casts in the manner that would have been expected when the Standard was written, but the Standard does not mandate such support; when such configurations, the behavior of the construct should be regarded as defined by a popular language extension.

Storing an std::assume_aligned pointer C++ 20

In C++ 20 we're getting assume aligned, this would be very usefull for audio code where pointers to aligned blocks of floats are passed around all the time. Let's say we have the following span type:
template<typename T>
struct Signal
{
const T* data
size_t size;
};
How would one indicate that the data pointer in this struct is aligned by some constexpr integer? Is something like this already possible in C++ 20?
constexpr int SIMDAlignment = 16;
template<typename T>
struct Signal
{
aligned<SIMDAlignment> const T* data
size_t size;
};
It seems that the assume-aligned hint is a property of a particular pointer object, and it cannot be made a property of a pointer type. However, you might try to wrap that pointer by an (inline) getter function and use std::assume_aligned for its return value. For example, in my experiment, when I used the pointer returned by such a function, it was treated as "aligned" (pointing to aligned data) correctly by GCC:
double* f()
{
static double* data =
(double*)std::aligned_alloc(64, 1024 * sizeof(double));
return std::assume_aligned<64>(data);
}
void g()
{
double* a = f();
for (int i = 0; i < 1024; i++)
a[i] = 123.45;
}
In this case, the array was filled by vmovapd which requires aligned memory access.
On the contrary, when I changed:
return std::assume_aligned<64>(data);
to:
return data;
The generated assembly contained vmovupd which works with unaligned data.
Live demo: https://godbolt.org/z/d5aPPj — check the .L19 loop in both cases.

How to dereference a n-levels void pointer to an int pointer

I'm trying to implement the following function:
int foo(const void *p, unsigned int n);
Where p is actually a n-levels pointer to an int value and the function must return that value. So:
n = 0: value = (int)(p);
n = 1: value = *(int*)(p);
n = 2: p is a pointer to a pointer to an int value
And so on...
So, I think that the following implementation may be correct:
int foo(const void *p, unsigned int n) {
if (!n) {
return (int)p;
}
return foo((void*)*((int*)p), n - 1);
}
But, in this code, I assume that size of a pointer always equals a size of an int, and I know it is not true. However, since p is always a pointer to pointer to int (n times), I think that maybe I can always cast p to pointer to int as I do in the code.
Is my idea correct? I cannot found any problem similar to this on internet.
Thanks in advance!
Your bottom case of the recursion is not correct, since this supposes that void* and int have the same width.
if (n == 1) return *(int*)p;
Would be better.
this assumes that your int is no bigger than a void*:
int foo(const void *p, unsigned int n) {
if (!n) {
return reinterpret_cast<int>(p);
}
return foo(*static_cast<void**>(p), n - 1);
}
we can avoid that assumption for everything except the n=0 case:
int foo(const void *p, unsigned int n) {
if (!n) {
return reinterpret_cast<int>(p);
}
if (n==1) {
return *static_cast<int*>(p);
}
return foo(*static_cast<void**>(p), n - 1);
}
In C you can replace the static_cast<X> and reinterpret_cast<X> clauses with (X).
I'm not sure what you are trying to accomplish, but I suspect there is a better approach.
Anyway, a pointer to something is the same size as a pointer to a pointer to something, etc.
So you can cast a (void*) to a (void**).
But casting a pointer to an int may loose information, because sizeof(void*) may be > sizeof(int).
You should write:
int foo(const void *p, unsigned int n) {
//if n is 0, then p is already an int, but has been casted to a void*
//This should probably never happend, so you should assert that n > 0
//if n is 1, then p is actually a pointer to an int
if (n == 1) return *(int*)p;
//else dereference it (by casting it to a (void**) and *then* dereferencing it)
return foo(*(void**)p, n-1);
}
In general it's usually better to stick with iterative solution, rather than recursive, if it's possible.
int foo(void *p, unsigned int n) {
for (unsigned int i = 0; i < n; ++i) {
p = *((void**)p);
}
return (int)p;
}
IDEONE: demo
It lets you avoid problems with theoretiaclly possible stack overflow for large ns (I have no idea why would you need to dereference 1000+ levels deep pointer, but I have no idea why you need this function in the first place, so let's keep the function safe) and avoids unnecessary function call overhead (yes, it might get optimized by the compiler, but why not write it optimally in the first place?).

C++ variable length arrays in struct

I am writing a program for creating, sending, receiving and interpreting ARP packets. I have a structure representing the ARP header like this:
struct ArpHeader
{
unsigned short hardwareType;
unsigned short protocolType;
unsigned char hardwareAddressLength;
unsigned char protocolAddressLength;
unsigned short operationCode;
unsigned char senderHardwareAddress[6];
unsigned char senderProtocolAddress[4];
unsigned char targetHardwareAddress[6];
unsigned char targetProtocolAddress[4];
};
This only works for hardware addresses with length 6 and protocol addresses with length 4. The address lengths are given in the header as well, so to be correct the structure would have to look something like this:
struct ArpHeader
{
unsigned short hardwareType;
unsigned short protocolType;
unsigned char hardwareAddressLength;
unsigned char protocolAddressLength;
unsigned short operationCode;
unsigned char senderHardwareAddress[hardwareAddressLength];
unsigned char senderProtocolAddress[protocolAddressLength];
unsigned char targetHardwareAddress[hardwareAddressLength];
unsigned char targetProtocolAddress[protocolAddressLength];
};
This obviously won't work since the address lengths are not known at compile time. Template structures aren't an option either since I would like to fill in values for the structure and then just cast it from (ArpHeader*) to (char*) in order to get a byte array which can be sent on the network or cast a received byte array from (char*) to (ArpHeader*) in order to interpret it.
One solution would be to create a class with all header fields as member variables, a function to create a byte array representing the ARP header which can be sent on the network and a constructor which would take only a byte array (received on the network) and interpret it by reading all header fields and writing them to the member variables. This is not a nice solution though since it would require a LOT more code.
In contrary a similar structure for a UDP header for example is simple since all header fields are of known constant size. I use
#pragma pack(push, 1)
#pragma pack(pop)
around the structure declaration so that I can actually do a simple C-style cast to get a byte array to be sent on the network.
Is there any solution I could use here which would be close to a structure or at least not require a lot more code than a structure?
I know the last field in a structure (if it is an array) does not need a specific compile-time size, can I use something similar like that for my problem? Just leaving the sizes of those 4 arrays empty will compile, but I have no idea how that would actually function. Just logically speaking it cannot work since the compiler would have no idea where the second array starts if the size of the first array is unknown.
You want a fairly low level thing, an ARP packet, and you are trying to find a way to define a datastructure properly so you can cast the blob into that structure. Instead, you can use an interface over the blob.
struct ArpHeader {
mutable std::vector<uint8_t> buf_;
template <typename T>
struct ref {
uint8_t * const p_;
ref (uint8_t *p) : p_(p) {}
operator T () const { T t; memcpy(&t, p_, sizeof(t)); return t; }
T operator = (T t) const { memcpy(p_, &t, sizeof(t)); return t; }
};
template <typename T>
ref<T> get (size_t offset) const {
if (offset + sizeof(T) > buf_.size()) throw SOMETHING;
return ref<T>(&buf_[0] + offset);
}
ref<uint16_t> hwType() const { return get<uint16_t>(0); }
ref<uint16_t> protType () const { return get<uint16_t>(2); }
ref<uint8_t> hwAddrLen () const { return get<uint8_t>(4); }
ref<uint8_t> protAddrLen () const { return get<uint8_t>(5); }
ref<uint16_t> opCode () const { return get<uint16_t>(6); }
uint8_t *senderHwAddr () const { return &buf_[0] + 8; }
uint8_t *senderProtAddr () const { return senderHwAddr() + hwAddrLen(); }
uint8_t *targetHwAddr () const { return senderProtAddr() + protAddrLen(); }
uint8_t *targetProtAddr () const { return targetHwAddr() + hwAddrLen(); }
};
If you need const correctness, you remove mutable, create a const_ref, and duplicate the accessors into non-const versions, and make the const versions return const_ref and const uint8_t *.
Short answer: you just cannot have variable-sized types in C++.
Every type in C++ must have a known (and stable) size during compilation. IE operator sizeof() must give a consistent answer. Note, you can have types that hold variable amount of data (eg: std::vector<int>) by using the heap, yet the size of the actual object is always constant.
So, you can never produce a type declaration that you would cast and get the fields magically adjusted. This goes deeply into the fundamental object layout - every member (aka field) must have a known (and stable) offset.
Usually, the issue have is solved by writing (or generating) member functions that parse the input data and initialize the object's data. This is basically the age-old data serialization problem, which has been solved countless times in the last 30 or so years.
Here is a mockup of a basic solution:
class packet {
public:
// simple things
uint16_t hardware_type() const;
// variable-sized things
size_t sender_address_len() const;
bool copy_sender_address_out(char *dest, size_t dest_size) const;
// initialization
bool parse_in(const char *src, size_t len);
private:
uint16_t hardware_type_;
std::vector<char> sender_address_;
};
Notes:
the code above shows the very basic structure that would let you do the following:
packet p;
if (!p.parse_in(input, sz))
return false;
the modern way of doing the same thing via RAII would look like this:
if (!packet::validate(input, sz))
return false;
packet p = packet::parse_in(input, sz); // static function
// returns an instance or throws
If you want to keep access to the data simple and the data itself public, there is a way to achieve what you want without changing the way you access data. First, you can use std::string instead of the char arrays to store the addresses:
#include <string>
using namespace std; // using this to shorten notation. Preferably put 'std::'
// everywhere you need it instead.
struct ArpHeader
{
unsigned char hardwareAddressLength;
unsigned char protocolAddressLength;
string senderHardwareAddress;
string senderProtocolAddress;
string targetHardwareAddress;
string targetProtocolAddress;
};
Then, you can overload the conversion operator operator const char*() and the constructor arpHeader(const char*) (and of course operator=(const char*) preferably too), in order to keep your current sending/receiving functions working, if that's what you need.
A simplified conversion operator (skipped some fields, to make it less complicated, but you should have no problem in adding them back), would look like this:
operator const char*(){
char* myRepresentation;
unsigned char mySize
= 2+ senderHardwareAddress.length()
+ senderProtocolAddress.length()
+ targetHardwareAddress.length()
+ targetProtocolAddress.length();
// We need to store the size, since it varies
myRepresentation = new char[mySize+1];
myRepresentation[0] = mySize;
myRepresentation[1] = hardwareAddressLength;
myRepresentation[2] = protocolAddressLength;
unsigned int offset = 3; // just to shorten notation
memcpy(myRepresentation+offset, senderHardwareAddress.c_str(), senderHardwareAddress.size());
offset += senderHardwareAddress.size();
memcpy(myRepresentation+offset, senderProtocolAddress.c_str(), senderProtocolAddress.size());
offset += senderProtocolAddress.size();
memcpy(myRepresentation+offset, targetHardwareAddress.c_str(), targetHardwareAddress.size());
offset += targetHardwareAddress.size();
memcpy(myRepresentation+offset, targetProtocolAddress.c_str(), targetProtocolAddress.size());
return myRepresentation;
}
While the constructor can be defined as such:
ArpHeader& operator=(const char* buffer){
hardwareAddressLength = buffer[1];
protocolAddressLength = buffer[2];
unsigned int offset = 3; // just to shorten notation
senderHardwareAddress = string(buffer+offset, hardwareAddressLength);
offset += hardwareAddressLength;
senderProtocolAddress = string(buffer+offset, protocolAddressLength);
offset += protocolAddressLength;
targetHardwareAddress = string(buffer+offset, hardwareAddressLength);
offset += hardwareAddressLength;
targetProtocolAddress = string(buffer+offset, protocolAddressLength);
return *this;
}
ArpHeader(const char* buffer){
*this = buffer; // Re-using the operator=
}
Then using your class is as simple as:
ArpHeader h1, h2;
h1.hardwareAddressLength = 3;
h1.protocolAddressLength = 10;
h1.senderHardwareAddress = "foo";
h1.senderProtocolAddress = "something1";
h1.targetHardwareAddress = "bar";
h1.targetProtocolAddress = "something2";
cout << h1.senderHardwareAddress << ", " << h1.senderProtocolAddress
<< " => " << h1.targetHardwareAddress << ", " << h1.targetProtocolAddress << endl;
const char* gottaSendThisSomewhere = h1;
h2 = gottaSendThisSomewhere;
cout << h2.senderHardwareAddress << ", " << h2.senderProtocolAddress
<< " => " << h2.targetHardwareAddress << ", " << h2.targetProtocolAddress << endl;
delete[] gottaSendThisSomewhere;
Which should offer you the utility needed, and keep your code working without changing anything out of the class.
Note however that if you're willing to change the rest of the code a bit (talking here about the one you've written already, ouside of the class), jxh's answer should work as fast as this, and is more elegant on the inner side.

passing objects into function through void pointer

I am writing a simple Memory Manager. I am trying to simplify this function so others can
just add the object they want to allocate as the first parameter. The Memory Manager will
allocate the space for that object, and set the object's pointer to point to the allocated
space. Problem is I'm not sure how to go about making the parameter so just about any type
of object can be passed in, without having to cast it like crazy to get it to work.
Here is the function:
bool MemoryManager::Allocate(void** data, unsigned int allocSize, bool isArray)
{
if((m_Heap.m_Pool == nullptr) || (*data != NULL))
return false;
if(isArray)
allocSize += sizeof(unsigned int) * 4;
void* mem = m_Heap.Allocate(allocSize);
if(mem)
{
*data = mem;
return true;
}
else
return false;
}
This is currently how I have to call it to get it to work:
int* Test = NULL;
MemoryManager::GetInstance()->Allocate((void**)(&Test), sizeof(int), false);
Any help or guidance would be greatly appreciated! :)
Using templates and overloading, you can operate directly on the type of data, including its size:
template<typename T>
bool MemoryManager::Allocate(T*& data)
{
size_t allocSize = sizeof(T);
...
}
When it comes to arrays though, normally we try to steer clear of pointers in C++. Use vector<T> for example. You can specify your own allocator.
I would consider whether you even want to return a raw pointer in fact; you might consider returning a smart pointer object.
Your array size calculation is flawed; I am not really sure what you're trying to do there. I would expect that allocSize is really element size, and thus the calculation is:
allocSize = (allocSize * elementCount);
But you don't have any way to know how many elements the user is requesting.