Void Pointer Arithmetic in C++11 [closed] - c++

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 6 years ago.
Improve this question
I really want to use some void casts to hold binary data but this is either g++ warning cascade or a lot of casting. Is there an easy and safe way to do void pointer arithmetics in C++ (preferably c++11 or higher)?
I am working only on posix systems with gnu compiler so that not a problem here.
Usecase:
I have void * ptr to data with size > 1GB.
I have other function to do things, lets call it stuff() its part of external library and gets (void *, size_t) as params.
stuff(ptr, n) is likely to mutate underlying memory. basically I need to pass slice of ptr*.
Code suppose to, is, and i guess, will not be portable.
I guess i will go just with -Wno-pointer-arithmetics if i wont be able to find some more elegant solution, but the one proposed in answers helped

Depends on what you have in mind when asking about arithemtics. Following code is perfectly fine, and compilable by GNU g++ -std=c++11 :
#include <cstdlib>
#include <cstdio>
int main()
{
void * x = std::malloc(100);
std::printf("%p\n", x);
std::printf("%p\n", x+20);
return 0;
}
(Edit2)
Question is pretty confusing, but if gnu compiler is something to work on, void pointer arithmetics is perfectly ok. GNU basically defines void * as pointer with one byte increments, and by that all statements in above code are correct. I did not tested it with other compilers, and as far as this question is considered, I do not have to.
For compilers other than GNU, using unsigned integer type perfectly safe and correct : first cast pointer to either one of 1byte integer type:
size_t
uintptr_t / intptr_t
or if you know memory size and model - precise fixed width integer }
If ever memory addressing will be changed to any other weird size per cell - you would need to use type that after adding +1 to address will point to next physical storage cell.
Also to clarify = bool is not 1bit type... its padded (aliased) char with some wrapper magic inside.

Related

What happens when a paddr_t is passed to a linked list that is expecting unsigned on a 64bit system? [closed]

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 10 months ago.
Improve this question
After looking harder at the code, I figured out the answer to my question. I was mistaken in thinking the initial declaration of linked list meant all future types had to be the same
The code I am looking at is for linked list insertion. The linked list is used to store logical addresses. The linked list is defined as unsigned 32 bit, but the addresses being inserted are defined as void*.
A logical address is cast to paddr_t and is then inserted. paddr_t was used to be reverse compatible with 32bit or 64 bit systems, since the void* size changes.
When the paddr_t is passed to the insert function, will the insert function parameter be promoted to paddr_t? Will the linked list member be promoted as well once the insertion is complete?
Abbreviated example of the code
LinkedList <unsigned> foo;
unsigned bar = 1001;
void* Laddr = &bar;
foo.insert((paddr_t)Laddr);
Assuming a common-sense definition of LinkedList: You don't pass paddr_t to the insert function. You pass unsigned to the insert function. If you try to pass paddr_t, the compiler will add an (unsigned) cast for you, and may or may not emit a warning.
If paddr_t and unsigned are the same type, it's unlikely that you'll get a warning, and extremely likely that it will work fine.
If paddr_t is bigger than unsigned, and you have a paddr_t that doesn't fit in an unsigned, then the extra bits will be removed to make it fit in unsigned, and that number will be stored in the list, and whatever code get the number back out of the list and converts it back to paddr_t will not work properly because it gets the wrong number.

Should integer types be cast explicitly (eg `int` to `unsigned`) or does this just add clutter? [closed]

Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 4 years ago.
Improve this question
This is a pretty minor question, so my apologies if it is too broad or possibly a duplicate. I searched and found several questions regarding how implicit integer conversion works, but none asking whether it is a good thing. I wouldn't ordinarily have cared about this at all, but all the loud and irritating warnings that compilers give about implicit conversions made me wonder whether this is considered a problem.
As a simple example, here is a snippet calling a function that takes a linked list, an integer (index), and an unsigned integer (range) which removes the specified range from the linked list.
const int64_t first = foo;
const int64_t last = bar;
const int diff = last - first; /* int for example's sake */
/* ... */
ll_delete_range_at(baz->ll, first+1, diff-1);
Dead simple; not terribly interesting. But clang complains that the values passed to the function are shortened and in the second case the sign is changed. Assuming that I know (as I do here) that there will not be an overflow problem, and that the values are always positive, is this actually a problem? Should one explicitly cast like this?
ll_delete_range_at(baz->ll, (int)(first+1), (unsigned)(diff-1));
As far as I understand it, this changes nothing other than to add clutter and explicitly state that the programmer is aware of the casts being done and is confident that they are OK. Is that worth the clutter?
Clutter from frequent casting is a sign of bad architecture, not a sign that explicit casting is wrong.
If you know that specific variables or members will always be in a specific range or size, then declare them with the appropriate type from the beginning.
If the types you have to work with need to be declared with a specific range or size, then that has a reason, and that reason will be valid wherever you use them, so stick to the types throughout your code.
If you have a special case where you must cast (e.g. when combining two libraries that use different types), then encapsulate that cast in a helper function or wrapper class with proper error handling.
C style casting to int snd unsigned should be avouded, because in my experience accidentally feeding them pointers and it becoming a reinterpret cast. Use static_cast.
Second, those casts are a sign of errors waiting to happen; if int doesn't fit the int64_t we just got an unspecified overflow. And a large unsigned value above 2^31 is probably not the number of elements we want to delete when diff==0.
So in that sense they are great documentation of where the code has dangerous problems.
The current programmer "knows" that the values are safe. The different programmer 7 years, months or days from now "knows" that any valid 64 bit value can be used for first and last, and that a diff of 0 is reasonable and later code shouldn't choke.
Describing the contract of code where diff cannot be 0 and two 64 bit values must be within 2^31-1 of each other makes the code smell here more apparent.
All of which follows from an innocuous scary pair of C style casts and some numerically questionable function calls.
Explicit casts are better than implicit conversion, but the type conversion itself is fraught here. Often type changes are a sign of bugs and fencepost errors to come. Program defensively and deal with the bounds checks unless you know the code is in a critical performance path; then, get the types right in the critical performance path.

C++ to Delphi convert. `this` pointer [closed]

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 4 years ago.
Improve this question
In C++:
static_cast<unsigned int>(reinterpret_cast<unsigned int>(&this[-0x00003111]))
I don't understand &this[-0x00003111]
I can't understand "[-address]"
How to convert it to delphi code?
This is a strange piece of code. To understand this the operator precedences have to be considered.
However, the important missing piece is the class to which this refers to. I assume this happens in a method of class A. The following code does the same like
static_cast<unsigned int>(reinterpret_cast<unsigned int>(&this[-0x00003111]))
but with separated expressions:
A *pThis = this;
A &a = pThis[-0x00003111]; // aka. A &a = *(pThis - 0x00003111);
A *pA = &a;
unsigned int ui = reinterpret_cast<unsigned int>(pA);
unsigned int ui2 = static_cast<unsigned int>(ui);
(To get this compiling at all, I had to use -fpermissive.)
Considering that 64 bit CPUs are very common nowadays, may be, it is worth to mention that the unsigned int may have 32 bits only where the this pointer has 64 bit in this case. So, the reinterpret_cast clips half of the bits away in this case.
Life Demo on coliru
Dear children.
Please, don't do this at home.

How does type conversion affect the memory accessed by the program and its variables? [closed]

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 5 years ago.
Improve this question
If I have the following code:
int variable = 65;
double variable2 = 54.34;
double sum = (double)variable + variable2;
So, in this case there will be 2 bytes allocated to variable. Again, if the variable is typecasted into a double variable. So it will be assigned an additional 8 bytes for its representation.
Pertaining to this, my question is that, will the variable, "variable" be assigned 10 bytes of memory, or am I getting something wrong?
(double)variable is an rvalue, so it doesn't formally have any storage.
At a level much lower than C++, the hardware platform's implementation of "addition of two doubles" might mean that it has to put a copy of variable in the bit-format of a double somewhere in memory so it can be added.
Probably the double bit-format of variable will end up in a the register of an FPU (Floating Point Unit) instead and so will never occupy "memory".
Either way, you can't get at that memory with C++. You would need to tell the compiler to put it somewhere, i.e. make it an lvalue, or use it in a way where the C++ standard requires that an an lvalue be created, e.g., passing it to a function
That's probably also true of the int bit-format of variable and of variable2, which (even though lvalues) the compiler will hopefully shove them off into (CPU or FPU) registers if you never use the lvalueness, so they won't appear in memory either.
The size of int is actually compiler specific, so you can't make any size assumptions about it unless you only work with one compiler. I would strongly recommend #including <cstdint> and using the u/intX_t types(i.e. int16_t, int32_t, int64_t) so you know the size of the type you're dealing with. They're aliases that map to whatever built-in types are necessary to achieve a given minimum size.
Cast behavior can vary depending on the type. In general all casts perform a conversion of some kind. It helps to think of casting as "converting", where the conversion rules depend on the type. Unless you're dealing with a custom cast operator, the conversion is going to promote, demote, transform, or reinterpret the bytes of the thing being casted from. Promotions (i.e. short => int) extend the bits depending on if it's signed or unsigned. Demotions (i.e. int => short) trim off the higher bits, leaving you with the low part. Transformations (i.e. int => double) convert from one format to another. Reinterpretations (i.e. int* => double*) treat the bits as if it were the casted to type.
Your code converts an int to a double and adds it to another double. This has the same effect as if you had left out the cast, because int is implicitly casted to double when used in an arithmetic expression like that.

C++ Convert Address of Memory To Value? [closed]

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 8 years ago.
Improve this question
In C++, using the iostream, you can print a variable's memory address. For example:
std::cout << &variable << std::endl;
// Example Result: 002AFD84
However, what if I wanted to store this memory address into a variable? Such as converting the memory address to a string or double(or int, etc.)? Or even convert that string or double(or int, etc.) back again, to a memory address?
I'd like to do this for various reasons, one being: This would allow me to return the memory address for data within a DLL to a program calling the DLL and it's functions. On top of this, I won't have to keep track of the data itself within the DLL, since the data could then be referenced by it's memory address.
I cannot use pointers in this particular situation due to constraints. The constraints being: The interpreted programming language I am using does not have access to pointers. Due to this, pointers cannot be used to reference the data outside of the DLL.
As a side question, what number format do memory addresses use? They seem to always seems to be 8 characters in length, but I can't figure out what format this is.
To convert a pointer into a string representation, you can use a string stream. These are similar to the standard I/O streams std::cin and std::cout, but write to or read from a string rather than performing I/O.
std::ostringstream oss;
oss << &variable;
std::string address = oss.str();
To convert a pointer into an integer that represents the same address, use reinterpret_cast. The type uintptr_t, if it exists, is guaranteed to be large enough to hold any pointer value. But I think usually it suffices to use unsigned long.
unsigned long address = reinterpret_cast<unsigned long>(&variable);
Converting a pointer into a floating-point type seems fairly useless. You would have to convert into an integral type first, then convert to a floating-point type from there.
If you absolutely need to do this I suggest being selective about what types you convert to. Arbitrarily converting pointers to non-pointer types can be problematic and introduce problems that are difficult to detect. This is especially true if you are using reinterpret_cast to perform the conversions. One of the more common issues is the size of the destination type between various platforms. When you use something like reinterpret_cast you typically don't get warnings about loss of precision during the conversion.
For situations require you to convert a pointer to an integral type I suggest wrapping these conversion in a function template. This will allow you a bit of flexibility in performing the conversion and can perform compile-time size checks to ensure the destination type is large enough to hold the pointer.
Something like the code below might be helpful.
template<class DestType, class SourceType>
DestType bubblicious_value_cast(const SourceType& src)
{
static_assert(sizeof(DestType) >= sizeof(SourceType), "Destination size is too small");
return reinterpret_cast<DestType>(src);
}
int main()
{
void* ptr = nullptr;
int val = bubblicious_value_cast<int>(ptr);
}
You can use reinterpret_cast like this:
uintptr_t address = reinterpret_cast<uintptr_t>(&variable);
In 64-bit (or 32-bit) environment memory address has 64-bit (32-bit) length, respectively.