+- +-
Say hello if visiting :) by Gecko
11 Jan 2023, 07:43:05 pm

Seti is down again by Mike
09 Aug 2017, 10:02:44 am

Some considerations regarding OpenCL MultiBeam app tuning from algorithm view by Raistmer
11 Dec 2016, 06:30:56 am

Loading APU to the limit: performance considerations by Mike
05 Nov 2016, 06:49:26 am

Better sleep on Windows - new round by Raistmer
26 Aug 2016, 02:02:31 pm

Author Topic: Pondering Pointer Portability.  (Read 12861 times)

Offline Jason G

  • Construction Fraggle
  • Knight who says 'Ni!'
  • *****
  • Posts: 8980
Pondering Pointer Portability.
« on: 17 Nov 2007, 07:20:31 am »
Okay Okay, nerdy topic for today is Converting pointer types to same sized Integral Types in C++.  ;D [Without Warnings! ]

 I know that if you're compiling for 32 bit and are careful,  despite all the warnings this works just fine:

   if( ( (size_t)src ) & 15u ) { ///some code} // casting a Pointer to same sized Integral Type Generates Warnings

And I also realise that most, if not all, those places are using that for examining offsets.  no problem , they're needed ;).

Then I would guess if you switch to 64 bit then you just go through and check, or change, the types and/or casts right? >:( (I don't know, I haven't had the pleasure of working with 64 bit windows yet)

Darnit how hard can it be to get the last few bits of the end of a pointer, without creating all sorts of DANGER DANGER WARNING WARNING rubbish messages? whether it's 32, 64, 128 or however many bits you want...

Could this situation be one of those few that union casts would be more appropriate? Of course given that reinterpret_cast is also considered unsafe  & generates the same warning as the explicit cast in the example ?
see Dr Dobb's Portal article: Flexible C++ #8: Union Casts Considered Harmful, but Necessary for more elaborate explanations of union casts.

I figure something like this maybe 'typedeffed' would work for the 32 bit case, and require only changing the type definition if portability is needed:
//----------------------------------------------------------------------
union {
   void * p;  // pointer is 32 bits
   unsigned int i; // unsigned int is 32 bits
} source;

....
source.p = (void *)src;
if( ( source.i & 15u) { //some code}
//----------------------------------------------------------------------


with 64 bit variant of the union (possibly typedeffed if needed often):
union {
   void * p;  // pointer is 64 bits
   UINT64 i; // UINT64  is 64 bits
} source;

wrapped of course in appropriate preprocessor directives to select the 32 or 64 bit version.

... Anyone know a better way?
... Anyone tried something like this or other alternatives ?
... Anyone else get annoyed by stacks of warnings, or am I the only one pedantic enough  ;D (that's would be okay too!)

Jason
« Last Edit: 17 Nov 2007, 11:18:01 am by j_groothu »

Offline Josef W. Segur

  • Janitor o' the Board
  • Knight who says 'Ni!'
  • *****
  • Posts: 3112
Re: Pondering Pointer Portability.
« Reply #1 on: 17 Nov 2007, 03:11:22 pm »
For the specific case you've chosen for illustration, I think

if( (uintptr_t) &src & (uintptr_t)15) { //some code}

should work for any size pointer because that type is specifically meant for pointer to integer conversion. Whether it will do so without complaint from any particular compiler I don't know. To be purely pedantic it should probably be converted to the verbose form of C++ cast, too.

I also ran across a PtrToULong() "helper" function documented for the MS compiler which suggests there may be no normal casting method which works there, and the DDJ article was obviously dealing only with MS in spite of the "portable" term.

I certainly agree we should be working toward code which compiles cleanly on different platforms and different bitness.
                                               Joe

Offline Jason G

  • Construction Fraggle
  • Knight who says 'Ni!'
  • *****
  • Posts: 8980
Re: Pondering Pointer Portability.
« Reply #2 on: 18 Nov 2007, 02:10:03 am »

I certainly agree we should be working toward code which compiles cleanly on different platforms and different bitness.
                                               Joe

LOL, Now there's a challenge :D, might get to play with a few things next week.  I have MS2005, ICC/IPP, & a somewhat broken MinGW/GCC installed at the moment. (all win32, no 64 bit yet ...)

I Haven't gotten around to playing with Linux for about twelve years (the good old days when you had to compile your kernel just to get a network card going) , But do have an Ubuntu DVD I might play with on my holidays (about three weeks away. 

'They' tell me the learning curve is much less steep than before, and that the headaches of X11 are completely gone.  Also suggested to me (for work related non-seti stuff)  is that FreeBSD will be worth a look.... So cross platform issues (even though still on x86 really) will be on my mind.

'till next week, cheers.
« Last Edit: 18 Nov 2007, 02:29:36 am by j_groothu »

Offline Jason G

  • Construction Fraggle
  • Knight who says 'Ni!'
  • *****
  • Posts: 8980
Re: Pondering Pointer Portability.
« Reply #3 on: 18 Nov 2007, 07:46:01 am »
Okay, I should be doing other things but couldn't resist having a play, ::) this time with an example from code closer to what exists in many places in the app code.. 

With  ICC on Win32 ,  Methods #1, #2, & #3 generate warnings , Method #4 union cast doesn't.  (Haven't tried straight MS yet).  Still in all cases 'seem' much more unwieldy than the original (#1) elegant line, Recombination and/or use of macro(s) may improve that.

@Joe: Not sure, but I hope Method 2 captured 'spirit' of the uintptr_t typecast, depends if you rather intended &src to be a buffer pointer, or  buffer pointer pointer (if that makes any difference in casting I don't know:D, can always tweak another method #5

Jason

//---------------------------------------------------------------------
//METHOD 1: typical code
//   Original code Generates warning #1684: conversion from pointer to
//         same-sized integral type (potential portability problem)
//
// defined elsewhere : 'typedef size_t PointerArith' and 'typedef unsigned int size_t'
    palignedMem = ( void * ) ( ((PointerArith) pmem + byteAlignment + sizeof(void *)) &~(byteAlignment) );
//---------------------------------------------------------------------
//METHOD 2: uintptr_t integral type casts
//adapted attempt from Joe's suggestion for different example: (uintptr_t) &src & (uintptr_t)15
// Arithmetic seperated out for analysis
// Additionally defined elsewhere: #define PTR_SIZE sizeof(void *)
    uintptr_t uipt = (uintptr_t) pmem; // This line makes the warning
    uipt += (byteAlignment + PTR_SIZE);
    uipt &= ~byteAlignment;
    palignedMem = (void *) uipt;
//---------------------------------------------------------------------
//METHOD 3: similar integral type casts
//Another try slightly different (Arithmetic also broken up for analysis)
    UINT_PTR uipMem = (UINT_PTR) pmem; // This line generates the same warning
    uipMem += (byteAlignment + PTR_SIZE);
    uipMem &= ~byteAlignment;
    palignedMem = (void *) uipMem;
//---------------------------------------------------------------------
//METHOD 4: Trying out the union cast - no warnings!
// the typedef PtrCheck union { ...i, ...p } can be any platform specific one:
//      where i is of integral type same size as pointer p
    ptrCheck ptrcheckMem;
    ptrcheckMem.p = (void *) pmem;
    ptrcheckMem.i += (byteAlignment + PTR_SIZE);
    ptrcheckMem.i &= ~byteAlignment;
    palignedMem = (void *) ptrcheckMem.p;
//---------------------------------------------------------------------
« Last Edit: 18 Nov 2007, 08:12:09 am by j_groothu »

Offline Jason G

  • Construction Fraggle
  • Knight who says 'Ni!'
  • *****
  • Posts: 8980
Re: Pondering Pointer Portability.
« Reply #4 on: 19 Nov 2007, 04:39:39 am »
Now we're getting silly :D

//---------------------------------------------------------------------
//METHOD 5: union cast, trying reduced assignments- no warnings!
//changed type of pAlignedMem....
    ptrCheck pAlignedMem;
    pAlignedMem.i = ( ((ptrCheck *)&pmem)->i + byteAlignment + PTR_SIZE ) & ~byteAlignment;
        // For access Use pAlignedMem.p or .i Instead;
        // Starting to Look suspiciously like Joe's earlier suggestion, may still end up getting that to work
//---------------------------------------------------------------------

[EDIT: we're back to 1 line apart from instantiation of pAlignedMem, getting there]

Now this stuff would seem to be leading to creation of an Aligned Buffer Class of some sort  instead  :-\

Jason
« Last Edit: 19 Nov 2007, 04:59:40 am by j_groothu »

Offline Jason G

  • Construction Fraggle
  • Knight who says 'Ni!'
  • *****
  • Posts: 8980
Re: Pondering Pointer Portability.
« Reply #5 on: 19 Nov 2007, 05:15:14 am »
//---------------------------------------------------------------------
//METHOD 6: attempt to revisit/adapt Joe's suggestion // Works now no Warnings
   uintptr_t uiptAlignedMem = (uintptr_t) ( *((uintptr_t *)&pmem) + byteAlignment + PTR_SIZE ) & ~byteAlignment;
    palignedMem = (void *) uiptAlignedMem;
//---------------------------------------------------------------------

LOL Now there's one cryptic line :D

I am now considering this ultra nerdy topic closed  ;D [Unless someone has a neater, more portable , preferrably easier to read method for performing integer arithmetic with pointers... without generating compile time warnings] 

Another solvable problem through cryptic casting and pointer juggling!

Jason

« Last Edit: 19 Nov 2007, 05:32:37 am by j_groothu »

 

Welcome, Guest.
Please login or register.
 
 
 
Forgot your password?
Members
Total Members: 97
Latest: ToeBee
New This Month: 0
New This Week: 0
New Today: 0
Stats
Total Posts: 59559
Total Topics: 1672
Most Online Today: 355
Most Online Ever: 983
(20 Jan 2020, 03:17:55 pm)
Users Online
Members: 0
Guests: 133
Total: 133
Powered by EzPortal