pointer question.

C

ctx2002

hi guys:

I am reading Sqlite code at moment, my c language skill not good
enough , hope some one here can help me.

In function listAdd(PagerLruList *pList, PagerLruLink *pLink, PgHdr
*pPg);
there is a line:
int iOff = (char *)pLink - (char *)pPg;

from my understanding, a pointer is just a memory address, so one
memory address minus an other
memory adress equal to what? what that iOff stand for?

I thought author of sqlite thought pLink will greater than pPg, it
that right?

also what is result of cast a pointer of struct into a pointer of
char. if the struct pLink has data inside,
what is result of (char *)pLink++?

also can any one explains to me what this is mean?
PagerLruLink *pLastLink = (PagerLruLink *)(&((u8 *)pList->pLast)
[iOff]);

thanks very much.


following are code copied from sqlite;

typedef struct PagerLruList PagerLruList;
struct PagerLruList {
PgHdr *pFirst; /* First page in LRU list */
PgHdr *pLast; /* Last page in LRU list (the most recently
used) */
PgHdr *pFirstSynced; /* First page in list with PgHdr.needSync==0
*/
};

/*
** The following structure contains the next and previous pointers
used
** to link a PgHdr structure into a PagerLruList linked list.
*/
typedef struct PagerLruLink PagerLruLink;
struct PagerLruLink {
PgHdr *pNext;
PgHdr *pPrev;
};

/*
** Add page pPg to the end of the linked list managed by structure
** pList (pPg becomes the last entry in the list - the most recently
** used). Argument pLink should point to either pPg->free or pPg-
** depending on whether pPg is being added to the pager-specific or
** global LRU list.
*/
static void listAdd(PagerLruList *pList, PagerLruLink *pLink, PgHdr
*pPg){
pLink->pNext = 0;
pLink->pPrev = pList->pLast;

#ifdef SQLITE_ENABLE_MEMORY_MANAGEMENT
assert(pLink==&pPg->free || pLink==&pPg->gfree);
assert(pLink==&pPg->gfree || pList!=&sqlite3LruPageList);
#endif

if( pList->pLast ){
int iOff = (char *)pLink - (char *)pPg;
PagerLruLink *pLastLink = (PagerLruLink *)(&((u8 *)pList->pLast)
[iOff]);
pLastLink->pNext = pPg;
}else{
assert(!pList->pFirst);
pList->pFirst = pPg;
}

pList->pLast = pPg;
if( !pList->pFirstSynced && pPg->needSync==0 ){
pList->pFirstSynced = pPg;
}
}
 
S

s0suk3

hi guys:

I am reading Sqlite code at moment, my c language skill not good
enough , hope some one here can help me.

In function listAdd(PagerLruList *pList, PagerLruLink *pLink, PgHdr
*pPg);
there is a line:
    int iOff = (char *)pLink - (char *)pPg;

from my understanding, a pointer is just a memory address, so one
memory address minus an other
memory adress equal to what?

If you rest a pointer to another pointer, both pointers should point
to elements in the same array. The result of the operation is an
integer: the rest of the relative positions of the elements that the
pointers point to within the array. For example, if 'a' is an array,
and 'i' and 'j' are integers, then the expression '&a - &a[j]' is
the same as 'i - j'.
what that iOff stand for?

iOff is assigned the distance (measured in array positions) between
the element that pLink points to and the element that pPg points to.
I thought author  of sqlite thought pLink will greater than pPg, it
that right?

If you mean "greater" in the sense that it points to an array element
a number of positions *after* the one that pPg points to, then
probably yes.
also what is result of cast a pointer of struct into a pointer of
char. if the struct pLink has data inside,
what is result of (char *)pLink++?

Just that: a pointer of type char. But why the increment? The code you
showed didn't have an increment.
also can any one explains to me what this is mean?
PagerLruLink *pLastLink = (PagerLruLink *)(&((u8 *)pList->pLast)
[iOff]);

A declaration of a pointer of type PagerLruLink that's initialized to
a pointer to the element iOff of the pList->pLast array cast to an u8
pointer. But to understand well what the whole thing does, we'd need
to know what the 'u8' type is.
thanks very much.

following are code copied from sqlite;

typedef struct PagerLruList PagerLruList;
struct PagerLruList {
  PgHdr *pFirst;         /* First page in LRU list */
  PgHdr *pLast;          /* Last page in LRU list (the most recently
used) */
  PgHdr *pFirstSynced;   /* First page in list with PgHdr.needSync==0
*/

};

/*
** The following structure contains the next and previous pointers
used
** to link a PgHdr structure into a PagerLruList linked list.
*/
typedef struct PagerLruLink PagerLruLink;
struct PagerLruLink {
  PgHdr *pNext;
  PgHdr *pPrev;

};

/*
** Add page pPg to the end of the linked list managed by structure
** pList (pPg becomes the last entry in the list - the most recently
** used). Argument pLink should point to either pPg->free or pPg->gfree,

** depending on whether pPg is being added to the pager-specific or
** global LRU list.
*/
static void listAdd(PagerLruList *pList, PagerLruLink *pLink, PgHdr
*pPg){
  pLink->pNext = 0;
  pLink->pPrev = pList->pLast;

#ifdef SQLITE_ENABLE_MEMORY_MANAGEMENT
  assert(pLink==&pPg->free || pLink==&pPg->gfree);
  assert(pLink==&pPg->gfree || pList!=&sqlite3LruPageList);
#endif

  if( pList->pLast ){
    int iOff = (char *)pLink - (char *)pPg;
    PagerLruLink *pLastLink = (PagerLruLink *)(&((u8 *)pList->pLast)
[iOff]);
    pLastLink->pNext = pPg;
  }else{
    assert(!pList->pFirst);
    pList->pFirst = pPg;
  }

  pList->pLast = pPg;
  if( !pList->pFirstSynced && pPg->needSync==0 ){
    pList->pFirstSynced = pPg;
  }

}

Sebastian
 
C

CBFalconer

ctx2002 said:
I am reading Sqlite code at moment, my c language skill not good
enough , hope some one here can help me.

In function listAdd(PagerLruList *pList, PagerLruLink *pLink,
PgHdr *pPg);
there is a line:
int iOff = (char *)pLink - (char *)pPg;

from my understanding, a pointer is just a memory address, so one
memory address minus an other memory adress equal to what? what
that iOff stand for?

That difference is simply the difference between the pointers.
Note that the statement is not valid UNLESS both the pointers are
pointing within the same memory assignment block. In other words
something like:

int pthings[LARGENUM];
int *pPg, *pLink;
...
pPg = &pthings[a];
pLink = &pthings;

where a and b are non-negative and less than LARGENUM, will work
for your sample. However:

int pthing1[2];
int pthing2[3];
int *pPg, *pLink;
...
pPg = &pthing1[0];
pLink = &pthing2[0];

is not guaranteed to work at all, although it often will. You may
have found a bug.
 
B

Barry Schwarz

hi guys:

I am reading Sqlite code at moment, my c language skill not good
enough , hope some one here can help me.

In function listAdd(PagerLruList *pList, PagerLruLink *pLink, PgHdr
*pPg);
there is a line:
int iOff = (char *)pLink - (char *)pPg;

from my understanding, a pointer is just a memory address, so one
memory address minus an other
memory adress equal to what? what that iOff stand for?

Normally, pointer arithmetic is conducted in units that have the same
size as the objects pointed to. For example, with the code
int a[2];
int x = &a[1] - &a[0];
x will have the value 1 independent of the size of an integer. The
reason is that a[1] is always located exactly sizeof(int) bytes beyond
a[0].

If you want to know how many bytes there are between two addresses,
then you need to perform the pointer arithmetic as if the pointers
pointed to objects that are exactly 1 byte in size. char happens to
be the type whose size will always be 1. Therefore, subtracting two
char pointers yields a byte count instead of an object count.
Continuing with the above code
int y = (char*)&a[1] - (char*)&a[0];
y will have the same value as sizeof(int) for the exact same reason
mentioned above.

Therefore, iOff is the number of bytes between the address in pLink
and the address in pPg.
I thought author of sqlite thought pLink will greater than pPg, it
that right?

There is no way to tell from what you posted. If pLink > pPg, iOff
will be positive. If they have the same value, iOff will be zero.
Otherwise, iOff will be negative.
also what is result of cast a pointer of struct into a pointer of
char. if the struct pLink has data inside,
what is result of (char *)pLink++?

Since ++ and cast have the same precedence but associate right to
left, this code will be compiled as
(char*)(pLink++)
The expression pLink++ evaluates to the current value of pLink. The
cast converts that value to a char*. It still points to the exact
same address but the data at that single bye will be treated as a
char. As an unrelated side effect, the value in pLink will be
incremented by 1, which causes the value to increase by the number of
bytes in whatever type of object pLink points to. (For example, if
pLink was an int* and sizeof(int) is 4, the pLink will have a new
value four greater than its current value.)
also can any one explains to me what this is mean?
PagerLruLink *pLastLink = (PagerLruLink *)(&((u8 *)pList->pLast)
[iOff]);

It looks like a syntax error to me. I don't think you can apply the &
operator to the result of a cast.
 
B

Ben Bacarisse

Barry Schwarz said:
also can any one explains to me what this is mean?
PagerLruLink *pLastLink = (PagerLruLink *)(&((u8 *)pList->pLast)
[iOff]);

It looks like a syntax error to me. I don't think you can apply the &
operator to the result of a cast.

It's fine (all the postfix operators like [] bind more tightly than
any prefix operator like &).

A pointer is being converted to a PagerLruLink *. That pointer is the
value of &((u8 *)pList->pLast)[iOff]. This expression has the form
&addr[iOff] -- i.e. it is the address of the iOff element of an array
pointed to by (u8 *)pList->pLast. It is more normal to write (u8
*)pList->pLast + iOff for this, but the & form is fine too.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,776
Messages
2,569,602
Members
45,182
Latest member
BettinaPol

Latest Threads

Top