简体   繁体   中英

How does this segment of C code for a priority queue work?

I'm a bit overwhelmed at this line specifically:

 Entry** newHeap = (Entry**)malloc(sizeof(Entry*) * newHeapLength);

in this code:

 /**
     * Expands the heap array of the given priority queue by 
     *   replacing it with another that is double its size.
     *
     * @param  pq  the priority queue whose heap is to be doubled in size
     * return  1 for successful expansion or an error code:
     */
    int expandHeap (PriorityQueue *pq)
    {
        int returnCode = 1;
        int newHeapLength = pq->heapLength * 2;
        Entry** newHeap = (Entry**)malloc(sizeof(Entry*) * newHeapLength);
        if (newHeap != NULL) 
        {
            int index;
            for (index = 0; index < pq->heapLength; index++) 
            {
                newHeap[index] = pq->heap[index];
            }
            free(pq->heap);
            pq->heap = newHeap;
            pq->heapLength = newHeapLength;
        }
        else
        {
            returnCode = -1;  // TODO: make meaningful error codes
        }
        return returnCode;
    }
Entry** newHeap = (Entry**)malloc(sizeof(Entry*) * newHeapLength);
      |                      |
newHeap is a             malloc allocates a chunk in memory that is the size of 
pointer to a             a pointer to an Entry times newHeapLength
pointer to an Entry

It just allocates an array for you, at run-time. Usually the size of array must be specified at compile-time. But here it is specified at run-time, it's newHeapLength . Each entry ("cell") in that array must be capable of storing a value of type Entry* in it. In C, arrays are contiguous, so the total size of the array, in bytes, is just a product of the two numbers: sizeof(Entry*) * newHeapLength . Now newHeap can be used to address this array in a usual manner: eg newHeap[8] . Of course, if 8 >= newHeapLength , this would be accessing past the allocated area, which is bad .

For array storing 10 int s, int ia[10]; , the type of ia is int * ( correction: almost. but we can pretend that it is, for the purposes of this explanation ). Here, similarly, for array storing values of type Entry* , the type is (Entry*)* . Simple. :)

And of course you must cast the return value of malloc to your type, to be able to address that array with it. malloc by itself returns an address as void* . Meaning. the size of memory cell which it points to, is proclaimed unknown . When we say that ia is of type int* , what we actually saying is that memory cell pointed to by it has size of sizeof(int) . So when we write ia[3] , it is actually translated into *(ia+3) which is actually *(int*)(void*)( (unsigned int)(void*)ia + 3*sizeof(int) ) . In other words, the compiler just adds sizeof(int) three times to the starting address, thus "hopping over" three sizeof(int) -wide cells of memory. And for newHeap[8] it will just "hop" over 8 sizeof(Entry*) -wide memory cells, to get the address of the 9-th entry in that array (counting from 1).

Also, see hashed array tree for an alternative to the geometric expansion, which is what that code is doing.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM