Passing a pointer of the wrong type

Hi, I'm using some code that I found in an article by Vikash Agarwal on writing an ODBC driver.

I'm attempting to build a skeleton using this code (my background is in SQL but no experience with C++), and after a few days of fizzing around the net and using the fab tutorial on this site, I've been able to understand some of it.

But on compile I get an error on the last line shown below. The code E0167 says it all: argument of type "UCHAR *" is incompatible with parameter of type "Const char *"

So far so understandable; it seems function strlen expects a const pointer arg, but the pointer I'm using is the wrong type. If I peek at the def for UCHAR I see: typedef unsigned char UCHAR; And there is also a warning that says "Conversion from integral type to pointer type requires reinterpret_cast, C-style cast, or function-style cast." How good is that, it even tells me what to do.

Now, in SQL I might cast a value from one type to another with a light heart, but pointers are a whole new ballgame for me.

I have 3 questions. If someone could assist that would be super:
i) Can I safely recast from UCHAR * to const char *?
ii) If so, how?
iii) What should I be looking for in future, to determine whether I can do this safely in other circumstances? In other words, I guess what I am saying is, what does the error really mean?

Thanks heaps,

Jack


1
2
3
4
5
6
7
8
9
10
RETCODE SQL_API SQLDriverConnect(
    HDBC             hDBC, HWND     hWnd,
    UCHAR* ptrConnStrIn, SWORD   lenConnStrIn,
    UCHAR* ptrConnStrOut, SWORD   lenConnStrOut,
    SWORD* pcbConnStrOut, UWORD    uwMode)
{
    OutputDebugString("SQLDriverConnect called\n"); // for DBMON

    if (lenConnStrIn == SQL_NTS && ptrConnStrIn) // get in-string length
        lenConnStrIn = strlen(ptrConnStrIn);
It depends on the value of the uchar if it is safe to cast to a char
If the value is > 127 you will lose some information.
The GSL have a narrow cast. It will throw an exception if it is not safe
https://github.com/gsl-lite/gsl-lite, if you don't have a choice you can use static_cast or gsl::narrow_cast
Thanks Thomas! 20 past midnight here, and now you've got me thinking again, I was just about to call it a night.

So I thought this was a pointer, and that it would therefore be very likely to be much larger than 127? Like, all the time?



Are you sure that you need it?
Doesn't lenConnStrIn specify the length of ptrConnStrIn?

BTW: if it is so late why don't you look at it with a fresh mind tomorrow?
Last edited on
In short, fresh mind and all, I think I do need it because, as far as I can see, that is what the code is trying to do. That is, find the length of the input string.

What about the 3rd argument
UCHAR* ptrConnStrIn,

I assume from the format of the argument that this is a pointer, am I correct? If I peek at the definition of strlen I see
1
2
3
4
_Check_return_
size_t __cdecl strlen(
    _In_z_ char const* _Str
    );


So that makes sense: strlen wants a pointer, and I pass it the pointer, and it should return the length (up to \0). But it wants a const pointer, and I only have what I think is called a volatile pointer.

Can I cast a volatile pointer to a const pointer?

You need to cast an unsigned char* to char* - at least in C++. I am not sure in C
Does your code has sth. to do with this:
https://docs.microsoft.com/en-us/sql/odbc/reference/syntax/sqldriverconnect-function?view=sql-server-ver15
Yes, my code has everything to do with that Microsoft SQLDriverConnect, I am trying to compile the skeleton for the ODBC driver.

What is the best way to cast an unsigned char* to char*? The reinterpret cast allows me to compile, but will it work at run time? Or should I use C-style or function cast?
reinterpret_cast<char*>(ptrConnStrIn)

Also, for the information of beginners like myself, the mistakes I have been making are:
1) parameters are passed by value, so that the purpose of the const is to ensure that you can pass values to a function that are not alterable by the function.
2) because of 1), the pointer that is being passed 'ptrConnStrIn' is const by default i.e. strlen only gets a copy
3) the definition of the strlen argument in <string.h> is _In_z_ char const* _Str. That does not mean that it expects a pointer constant, which would be unnecessary since it only gets a copy of the pointer anyway. It means that the value pointed to by the pointer is constant and cannot be changed by the function.
4) I changed the original code so that parameter names were not eg 'szConnStrIn', but 'ptrConnStrIn'. I did that because it appeared 'szConnStrIn' should contain a numeric value for a size. But the sz prefix is widely used in C++ to indicate that it is a null terminated string.
5) If you are a lit graduate like me, be careful, C++ people love metonymy and can confound you by talking about a string and then writing down a pointer. For more information about metonymy and The Container For The Thing Contained, go here: https://www.newyorker.com/magazine/1942/03/21/here-lies-miss-groby
Topic archived. No new replies allowed.