Thread: Problem with PQexecPrepared
Hi, I am having a problem with a compiler warning using PQexecPrepared. It is with the paramValues argument. warning: passing arg 4 of `PQexecPrepared' from incompatible pointer type The type I am passing is a char** and it is expecting const char* const* The parameters I am passing in a generated at runtime so I can supply a const pointer. Am I missing something? Also, does someone have an example using PQexecPrepared or PQexecParams using non-text params? -- David Stanaway <david@stanaway.net>
On Wed, Jun 09, 2004 at 04:44:12PM -0500, David Stanaway wrote: > The type I am passing is a char** and it is expecting const char* const* I'm not sure I understand your question entirely, so forgive me if I'm telling you things you already know... The C type system needs to be strict here to guard against the case where people try pass a "char **" argument to a "const char **" parameter. Why is that a problem? Because the function might try to insert a "const char *" into the array, thinking it got passed an array of "const char *"s. But after the function returned, the caller might overwrite the actual string this pointer pointed to because it never told the function that the chars were to be kept const. This is a case where "adding a const" is not type-safe. Not that it would be a problem here, because the array itself is const and so the function could never write its own pointer into it. I think it's one of those rare situations where a cast is justified. > The parameters I am passing in a generated at runtime so I can supply a > const pointer. Generating something at runtime doesn't mean you can't have a const pointer to it. Declaring the thing a pointer points to "const" is a promise that you won't use the pointer to modify that thing. Which doesn't mean that it can't be modified through another pointer! Jeroen
On Wed, 2004-06-09 at 17:21, Jeroen T. Vermeulen wrote: > On Wed, Jun 09, 2004 at 04:44:12PM -0500, David Stanaway wrote: > > > The type I am passing is a char** and it is expecting const char* const* > Not that it would be a problem here, because the array itself is const > and so the function could never write its own pointer into it. I think > it's one of those rare situations where a cast is justified. Thanks for the clarification. I thought it was odd to have to cast to a const in this case. I changed the call like such: res = PQexecPrepared(serverp->connection, serverp->queryps[BILLING_INSERTROUTED]->prephandle, nparm,(const char*const*)parms,NULL,NULL,1); If the prototype had been for const char** I would not have needed to change anything, the API author I guess is being thorough. -- David Stanaway <david@stanaway.net>
David Stanaway <david@stanaway.net> writes: > On Wed, 2004-06-09 at 17:21, Jeroen T. Vermeulen wrote: >> Not that it would be a problem here, because the array itself is const >> and so the function could never write its own pointer into it. I >> think it's one of those rare situations where a cast is justified. > If the prototype had been for const char** I would not have needed to > change anything, the API author I guess is being thorough. The author was me, and I didn't think I was creating any problems by const-ifying the declaration :-(. Jerome, are you sure this isn't a compiler glitch? I really have a problem with the notion that a library routine can over-constify its input declarations... regards, tom lane
On Jun 10, 2004, at 12:34 AM, Tom Lane wrote: > David Stanaway <david@stanaway.net> writes: >> On Wed, 2004-06-09 at 17:21, Jeroen T. Vermeulen wrote: >>> Not that it would be a problem here, because the array itself is >>> const >>> and so the function could never write its own pointer into it. I >>> think it's one of those rare situations where a cast is justified. > >> If the prototype had been for const char** I would not have needed to >> change anything, the API author I guess is being thorough. > > The author was me, and I didn't think I was creating any problems by > const-ifying the declaration :-(. Jerome, are you sure this isn't > a compiler glitch? I really have a problem with the notion that a > library routine can over-constify its input declarations... Hi there, The library prototype is fine. My GCC is gcc (GCC) 3.3.3 (Debian 20040422). Do you have an example of PQexecParams or PQexecPrepared using non text parameters? -- David Stanaway <david@stanaway.net>
On Thu, Jun 10, 2004 at 01:34:12AM -0400, Tom Lane wrote: > David Stanaway <david@stanaway.net> writes: > > If the prototype had been for const char** I would not have needed to > > change anything, the API author I guess is being thorough. > > The author was me, and I didn't think I was creating any problems by > const-ifying the declaration :-(. Jerome, are you sure this isn't > a compiler glitch? I really have a problem with the notion that a > library routine can over-constify its input declarations... I don't think this is a compiler glitch. The way the C type system works (well, in its current form anyway) was thought out pretty well and I wouldn't bet on gcc getting it wrong. You can't hoist const qualifiers across pointers, because the constness of a pointer is a very different thing from the constness of whatever it points to. The former can be converted implicitly in this case, but the latter cannot because it's at least as fundamental a property of the pointer's type as the "char" is. It's hidden away a level too deep to meddle with, if you will. This particular usage (converting "TYPE **" to "const TYPE *const *") might probably have been allowed as a special case, but such exceptions make for convoluted type systems and perhaps even paradoxes. Compilers used to be full of such ad-hockery IIRC, and the standardization process got rid of it so that all compilers could implement a single, consistent language. And as the poem goes, there was dancing in the dock; and a day of celebration was commanded in Bangkok. I wouldn't say that the library routine over-constified the parameter either. Think about it: what other type could you possibly give it? It's a char const *const * by nature, and there's no point in denying it. Whether this problem turns up in practice probably depends a lot on one's programming style: const char **array = malloc(strings * sizeof(*array));for (n=0; n<strings; ++n){ char buf[100]; char *mystring; int len; len = get_a_string(buf, 100); array[n] = mystring = malloc(len); strcpy(mystring, buf);}pass_parameter(array); Note how the strings are generated at runtime, but the array only sees const char *'s. The array itself may be nonconst, but that is the one implicit conversion that is allowed while passing it as a parameter. Jeroen