In converting an MS C (v6) program from Scalable SQL to the Btrieve API (BTRV function), I need to understand the intricacies of pointers in order to resolve a "different levels of indirection" compilation error.
The original program declared cursors and hence read in several records at a go (using xNew and xFetch). Relevant code, I hope, below...
Code:
#define N_FETCH 20
#define NIBBLE 0x000F /* binary representation 0000000000001111 */
/* This half-byte is used to mask off all but the
four bits of interest in each conversion step. */
#define BYTE 0x00FF /* binary representation 0000000011111111 */
struct crdRec
{ int Recordlen;
char CrCustnum [6];
<snip>
char CrFxfwddelex [7];
char CrSgnfxfdlex [1];
};
struct i1bRec
{ int Recordlen;
char Custnum [6];
<snip>
char Sgnfxfdlex [1];
char Fxfwddelex [14];
};
struct crdRec crdVRec [N_FETCH];
struct i1bRec i1bVRec [N_FETCH];
int rind;
char hexbuf [5];
char *inPtr, *outPtr;
char hextab[] = { '0', '1', <snip> 'F' };
char *byte2hex (unsigned char, char *);
That is most of the relevant declarations. Here is some code.
Code:
/* code to select cursor of data*/
status = xFetch (cursorID1, &bufLen, opt, &recCount,
&rejCount, (char *) crdVRec);
if (status == 0 || status == 9)
{
/* total number of records selected */
t_recCount += recCount;
for (rind = 0; rind < recCount; rind++)
{
i1bVRec[rind].Recordlen = sizeof(struct i1bRec) -2 ;
strncpy (i1bVRec[rind].Custnum, crdVRec[rind].CrCustnum, 6);
<snip>
/* convert packed data field */
inPtr = (char *) &crdVRec[rind].CrFxfwddelex ;
outPtr = (char *) &i1bVRec[rind].Fxfwddelex ;
for (i = 0; i < 7 ; ++i)
{
strcpy (outPtr, byte2hex (*inPtr++, hexbuf));
outPtr += 2;
}
It is on the strcpy, on my converted version, where it gives the compilation error. I haven't tried compiling this original code yet; I'll do that shortly, it may not compile itself for all I know. I've had that happen before!
For info, the byte2hex function:
Code:
/* ========================= byte2hex () ================ */
/* Convert a byte to a string representation of its hexadecimal value */
/* The function byte2hex() , converts a byte-sized(8-byt) quantity to */
/* hexadecimal. */
/* The hextab array is a conversion lookup table. It uses a number in */
/* the range of 0 through 15 as an index into the table, where the */
/* corresponding character constant (number or letter) is found. */
/* =================================================== */
char *byte2hex (data, buf)
unsigned char data;
char *buf;
{
char *cp;
unsigned int d;
d = data & BYTE; /* turn off the 4 high order bits */
cp = buf; /* assign pointer to output buffer */
/* Right-shift operations are used to pull the needed bits into the
correct position for convertion to a hexadecimal digit. */
/* move 1st 4 low order bits to right and turn off all other bits */
*cp++ = hextab [(d >> 4) & NIBBLE];
/* turn off last 4 low order bits */
*cp++ = hextab [d & NIBBLE];
*cp = '\0';
return (buf);
}
/* End of byte2hex */
Now for my converted version, using the Btrieve API. I am not using a cursor, hence only reading one record at a time. I am not using crdVRec and i1bVRec,
but am doing the following:
Code:
struct crdRec CRD_REC_BUF, *pj;
struct i1bRec OUT_BUF, *po;
pj = &CRD_REC_BUF;
po = &OUT_BUF;
Then the similar point in the code as before is
Code:
memcpy 9po->Custnum, pj->CrCustnum, 6);
<snip>
/* convert packed data field */
inPtr = (char *) pj->CrFxfwddelex;
outPtr = (char *) po->Fxfwddelex;
for (i = 0; i < 7; ++1)
{
strcpy (outPtr, byte2hex (*inPtr++, hexbuf));
outPtr += 2;
}
At first I thought the different levels of indirection seemed clear, in that there is a pointer and a character array (inPtr and hexbuf), but then thought further that the compiler should be looking at the output from the function byte2hex (which is a pointer) so it should be ok? Obviously, I am confused! :?
Actual messages from compiler as follows:
warning C4047: 'argument' : different levels of indirection
warning C4024: 'strcpy' : different types : parameter 2
Any help gratefully received.