What's a data type?



  • Just found this gem while attempting to introduce type checking and meaningful variable names to a C++ code base.

            case embed_meta_file:
             {
             	long		meta;
             	
             	meta = (long)item->data;
             	meta = (long)CopyMetaFile((HMETAFILE)meta, NULL);
             	item->data = (void FAR *)meta;
             }


  •  To be fair, far pointers haven't existed for years, so that code is really old.  Probably from win16 or something.  Not that that excuses the lack of proper types, but the only other way to really do that would be a union or something.



  •  The original programmer could have used 2 variables, each with the right type, given meta is reassigned in the middle. There's no need for a union.



  • @DescentJS said:

    ...but the only other way to really do that would be a union or something.

    I don't see any reason why declaring it a HANDLE (typedef to some kind of pointer used in the API) all the way should not work. No union needed. The long simply makes no sense.

    For the added WTF, Win64 is the first (and only so far I believe) where a pointer will not fit in a long, so it won't work in 64-bits

    (64-bit platforms have 64-bit pointers. Most of them chose to make "long" 64-bit, but Microsotft, probably because of their own horrible mess with int vs. long in the API, chose to keep it 32-bit. To make matters worse, they chose to keep size_t 32-bit too, so you can't actually allocate more than 4GB block anyway -- plus ptrdiff_t and size_t are different size.)



  • @Bulb said:

    For the added WTF, Win64 is the first (and only so far I believe) where a pointer will not fit in a long, so it won't work in 64-bits

     

    [Insert rant about DWORD_PTR here.]



  • @thosrtanner said:

     The original programmer could have used 2 variables, each with the right type, given meta is reassigned in the middle. There's no need for a union.

    The original programmer could have used 0 variables, couldn't they?

            case embed_meta_file:
    {
    item->data = CopyMetaFile((HMETAFILE)item->data, NULL);
    }

    Casting a pointer to void* is superfluous in both C and C++.  And why use a temporary to store the result of a cast?  And cast the same thing two different ways?  WTF?

     



  • @Bulb said:

    To make matters worse, they chose to keep size_t 32-bit too

    Really? This prints two eights:

    #include <stdio.h>
    #include <stddef.h>
    
    int main()
    {
        printf("%d %d\n", (int) sizeof(size_t), (int) sizeof(ptrdiff_t));
        return 0;
    }
    


  • @DaveK said:

    @thosrtanner said:

     The original programmer could have used 2 variables, each with the right type, given meta is reassigned in the middle. There's no need for a union.

    The original programmer could have used 0 variables, couldn't they?

            case embed_meta_file:
    {
    item->data = CopyMetaFile((HMETAFILE)item->data, NULL);
    }

    Casting a pointer to void* is superfluous in both C and C++.  And why use a temporary to store the result of a cast?  And cast the same thing two different ways?  WTF?

     



    Not sure you can play around with (void FAR *) in the same way you can with void *, but yes, he could have had no temporary items. I claim eyes crossing due to finding out that there are people who can write code in C++ that makes bad fortran look readable.


  • @Spectre said:

    @Bulb said:
    To make matters worse, they chose to keep size_t 32-bit too

    Really? This prints two eights:

    Hm, I probably misremeber something from what the 64-bit portability warnings. I guess it was the fact, that ptrdiff_t was declared with the __w64 attribute, but size_t was not.

  • Discourse touched me in a no-no place

    @Bulb said:

    Hm, I probably misremeber something from what the 64-bit portability warnings. I guess it was the fact, that ptrdiff_t was declared with the __w64 attribute, but size_t was not.
    Considering they're different types (one is signed, the other unsigned) and they represent two completely unrelated things it's not surprising that there should be other differences.



  • @Bulb said:

    I guess it was the fact, that ptrdiff_t was declared with the __w64 attribute, but size_t was not.

    That's hardly a fact either...

    @crtdefs.h said:


    #if !defined(_W64)
    #if !defined(__midl) && (defined(X86) || defined(_M_IX86)) && _MSC_VER >= 1300
    #define _W64 __w64
    #else
    #define _W64
    #endif
    #endif

    /* ... */

    #ifndef _SIZE_T_DEFINED
    #ifdef _WIN64
    typedef unsigned __int64 size_t;
    #else
    typedef _W64 unsigned int size_t;
    #endif
    #define _SIZE_T_DEFINED
    #endif

    /* ... */

    #ifndef _PTRDIFF_T_DEFINED
    #ifdef _WIN64
    typedef __int64 ptrdiff_t;
    #else
    typedef _W64 int ptrdiff_t;
    #endif
    #define _PTRDIFF_T_DEFINED
    #endif


Log in to reply