Search code examples
cvoid-pointers

Converting a void pointer to an unsigned long


I am working on a C program that takes in a void pointer that I know for a fact points to an integer but I cant figure out how to correctly cast it to such. For example, the following will produce a C6011 warning.

int convert(PVOID val) 
{
   int value = *((int *) val); 
   return value;
}

However, I plan to use this in my kernel driver so warnings will be a problem and I really need to cast the PVOID into a ULONGLONG so that I can compare it to another ULONGLONG but I am not sure how to do that. When I print the value of the void pointer it prints the value as a ULONGLONG but its in hex when I need it in decimal in order to make comparing and printing the value easier.

Anyways the following code will produce a C222 error and a C4047 warning because it does not like me casting a void pointer to a ULONGLONG but I am not sure how to do this without generating any warnings, errors, or BSOD's.

bool same(PVOID val, ULONGLONG otherVal) 
{
   ULONGLONG value = val;
   return value == otherVal;
}

Solution

  • I am working on a C program that takes in a void pointer that I know for a fact points to an integer but I cant figure out how to correctly cast it to such. For example, the following will produce a C6011 warning.

    int convert(PVOID val) 
    {
       int value = *((int *) val); 
       return value;
    }
    

    Based on the format of the error number, I guess you're compiling with MSVC. MSVC warning C6011 complains that you are dereferencing a pointer that may be null. Apparently, then, MSVC is not as sure as you are that the pointer actually points to an integer. Your cast & dereference is the correct way to get the int to which the pointer points. It's only a warning, but you should be able to silence it by performing a null check before the dereference, something like this:

    int convert(PVOID val) {
       if (val == NULL) {
          // abort or return a default value
       } else {
          return *((int *) val); 
       }
    }
    

    However, I plan to use this in my kernel driver so warnings will be a problem and I really need to cast the PVOID into a ULONGLONG so that I can compare it to another ULONGLONG but I am not sure how to do that.

    That sounds suspect, but if you intend to do it then you do exactly what you describe: cast, via a cast operator. C explicitly allows such conversions.

    Anyways the following code will produce a C222 error and a C4047 warning because it does not like me casting a void pointer to a ULONGLONG but I am not sure how to do this without generating any warnings, errors, or BSOD's.

    A C4047 makes sense, but I have no idea what a C222 is. I do not find it documented. In any case, standard C permits you to convert pointers to integers, but such conversions are not implicit. A cast is required:

    bool same(PVOID val, ULONGLONG otherVal) {
       return otherVal == (ULONGLONG) val;
    }
    

    However, although that should clear the C4047, the code still has bad smell. I don't know the circumstances that make such comparisons (seem) appropriate, but there is probably a cleaner approach.