1

I have read several posts on stackoverflow such as size_t vs. uintptr_t and Is sizeof(size_t) == sizeof(void*) always true? and understood that per the C++ standard, the sizes of SIZE_T and void* can be different to account for architectures such as 16-bit segmented architectures.

So I'd like to limit the platforms of my scenario to be Windows, whether it's x86, x64, WoA (Windows on Arm): On Windows, if I malloc to create a pointer of type void*, and I want to do pointer-arithmetic before passing it to memcpy or something, I'd have to something like:

void* p = malloc(100);
memcpy(reinterpret_cast<void*>((reinterpret_cast<SIZE_T>(p) + offset), p2, 100);

Which seems very tedious, especially if you have to litter this type of casting back-and-forth everywhere (I am working with various offsets). Given this is on a Windows platform, I wonder if there's some simplifications that can be made to reduce this type of boilerplate code?

Thanks.

Community
  • 1
  • 1
lancery
  • 658
  • 1
  • 6
  • 18
  • Ideally, create the right type in the first place. Otherwise, use `char *` for the cast to do arithmetic. That will always work (and as long as you pay attention to alignments and such, can be cast back to whatever type you need it to be). – Mats Petersson May 18 '14 at 07:44
  • In C++ there are better options than `void *` and `malloc` and `memcpy`, for nearly every problem – M.M May 18 '14 at 07:45
  • Looks pretty unsafe for any value of `offset` other than 0. Did you mean `memcpy(...,100-offset)`? – barak manos May 18 '14 at 07:46
  • This is an excellent time to use an inline template function, and to a less-desirable extent macros. – rwong May 18 '14 at 07:48

2 Answers2

7

Cast it to unsigned char * and do pointer arithmetic with that instead.

user541686
  • 205,094
  • 128
  • 528
  • 886
  • Hmmmm... I wonder what is the difference between this answer and @Matt McNabb's (for this to get 6 up-votes and the other to get 1 down-vote)... – barak manos May 18 '14 at 07:49
  • @barakmanos: Not sure why Matt's got downvoted, but mine was posted first so that's probably why it got upvoted... – user541686 May 18 '14 at 07:50
  • @barakmanos: Well, I generally consider `unsigned` types to be more suitable for this (since their overflow behavior is defined), but often I'm just being super paranoid. I don't think in this case it actually makes a difference. Generally though `unsigned` is less error prone. – user541686 May 18 '14 at 07:52
  • Gotcha thanks... There an additional (non-related) insight here, with regards to the reliability of the voting system :) – barak manos May 18 '14 at 07:54
  • @barakmanos: Yep. Also btw, I mentally regard `signed char` and `unsigned char` as *integer* types, whereas I regard `char` and `wchar_t` as *character* types... in this case there are no strings involved, so involving `char` makes less sense and might mislead the reader into thinking the memory holds a string. – user541686 May 18 '14 at 07:54
  • @barakmanos: Well, yeah, but they're all different types -- so it makes sense to separate them logically and treat them differently instead of mixing and matching them. =P – user541686 May 18 '14 at 07:56
  • So it looks like the key is to cast it to a pointer-type that has a size-concept (i.e. unsigned char * is ideal since it iterates on a byte-to-byte basis) and it would automatically be resized based on the platform (4 bytes on 32-bit platforms and 8 bytes on 64-bit platforms) and can be implicitly casted back to void * since it's a pointer type to begin with? – lancery May 18 '14 at 08:03
  • @lancery: Not sure what you mean by the 32-bit or 64-bit issue (that doesn't really enter the picture), but yes, what you said is otherwise correct. – user541686 May 18 '14 at 08:11
0

Based on your description I think you just want:

memcpy( (char *)p + offset, p2, 100);
M.M
  • 138,810
  • 21
  • 208
  • 365