Reputation: 392
I have defined my own type. It contains a pointer to an array, as well as how many items are in that array
struct neighborList
{
unsigned int nNeighbors;
unsigned int* pNeighbors;
};
These get instantiated, populated, and eventually I want to go back through them. Then something very strange happens. I think screenshots are better than words here.
I've shown the next statement to execute. I have an array of the aforementioned data type, and the one under consideration here has 1 neighbor and the address of that 1 neighbor is 0x107a28; Cool. But what actually gets assigned to pLook?
The address is always off by 0x40. Has anyone seen anything like this? Help here is appreciated.
EDIT: Here's the whole thing since several people want to see it.
#include "stdafx.h"
#include <stdlib.h>
#include <time.h>
//#define NVERTEX 875714
#define NVERTEX 9
struct linkedNode
{
unsigned int node;
linkedNode* pNextLinkedNode;
linkedNode* pPrevLinkedNode;
};
struct neighborList
{
unsigned int nNeighbors;
unsigned int* pNeighbors;
};
struct linkedNodeList
{
linkedNode* pHead;
linkedNode* pTail;
};
void populateNeighbors(neighborList* pNeighborList, FILE* fp);
void DFSLoop(neighborList* pNeighborList, linkedNode* pOutput, unsigned int nNodes);
void append(linkedNodeList* pLinkedList, unsigned int node);
void DFSLoop(neighborList* pNeighborList, linkedNodeList* pOutput, unsigned int nNodes)
{
bool* visitedArray;
bool* cashedArray;
unsigned int* leaderArray;
unsigned int* finishingTimes;
unsigned int t = 0;
visitedArray = (bool*)malloc(nNodes*sizeof(bool));
cashedArray = (bool*)malloc(nNodes*sizeof(bool));
leaderArray = (unsigned int*)malloc(nNodes*sizeof(unsigned int));
finishingTimes = (unsigned int*)malloc(nNodes*sizeof(unsigned int));
//initialize all arrays to all false/0
for (unsigned int i = 0; i < nNodes; i++)
{
visitedArray[i] = false;
cashedArray[i] = false;
leaderArray[i] = 0;
finishingTimes[i] = 0;
}
//firstly, pick a starting node and put it on the linkedList
//initialize head and tail
(pOutput->pHead)->node = 1;
(pOutput->pHead)->pNextLinkedNode = NULL;
(pOutput->pHead)->pPrevLinkedNode = NULL;
(pOutput->pTail)->node = 1;
(pOutput->pTail)->pNextLinkedNode = NULL;
(pOutput->pTail)->pPrevLinkedNode = NULL;
unsigned int curNode = (pOutput->pTail)->node;
for (;;)
{
//Start DFS
//#1 If current node under consideration has an unexplored neighbor, make it the new tail and repeat
// If not, current node is cashed. Set it's finishing time, and leader. Work back through the list
// Until you find a node with an unexplored neighbor
unsigned int nNeighbors = pNeighborList[curNode].nNeighbors;
for (unsigned int i = 0; i < nNeighbors; i++)
{
unsigned int* pLook = (pNeighborList[curNode]).pNeighbors;
unsigned int neighbor = pLook[0];
/*
unsigned int nodeUnderConsideration = (pNeighborList[curNode].pNeighbors)[i];
if ( !cashedArray[nodeUnderConsideration])
{
append(pOutput, (pNeighborList[curNode].pNeighbors)[i]);
curNode = (pOutput->pTail)->node;
continue;
}
*/
}
//#2 If you make it back to the head and have no unexplored neighbors, pick new vertex (if unvisited) and repeat
}
free(visitedArray);
free(cashedArray);
free(leaderArray);
free(finishingTimes);
}
int _tmain(int argc, _TCHAR* argv[])
{
//open file
FILE* fp;
FILE* fpRev;
//fp = fopen("SCC.txt", "rb");
//fpRev = fopen("SSCrev.txt", "rb");
fp = fopen("SSCsmall1.txt", "rb");
fpRev = fopen("SSCsmall1rev.txt", "rb");
/* read file. When reading, keep track of how much memory to malloc */
/* for each vertex */
neighborList* pAllEdges;
neighborList* pAllEdgesRev;
pAllEdges = (neighborList*)malloc(NVERTEX*sizeof(neighborList));
pAllEdgesRev = (neighborList*)malloc(NVERTEX*sizeof(neighborList));
populateNeighbors(pAllEdges, fp);
populateNeighbors(pAllEdgesRev, fpRev);
//instantiate pointers for linkedlists needed for DFS
linkedNodeList NodesFirstPass, NodesSecondPass;
NodesFirstPass.pHead = (linkedNode*)malloc(sizeof(linkedNode));
NodesFirstPass.pTail = NodesFirstPass.pHead;
NodesSecondPass.pHead = (linkedNode*)malloc(sizeof(linkedNode));
NodesSecondPass.pTail = NodesSecondPass.pHead;
DFSLoop(pAllEdges, &NodesFirstPass, NVERTEX);
free(pAllEdges);
free(pAllEdgesRev);
return 0;
}
void populateNeighbors(neighborList* pNeighborList, FILE* fp)
{
unsigned int v1 = 1;
unsigned int v2 = 1;
unsigned int v1_next = 1;
unsigned int v2_next = 1;
unsigned int neighbors [1000];
fscanf(fp, "%u", &v1_next);
fscanf(fp, "%u", &v2_next);
for (unsigned int i = 0; i < (NVERTEX - 1); i++)
{
//initialize nNeigbors to 0
unsigned int nNeighbors = 0;
for (;;)
{
//if v1_next is a different vertex then v1, then copy v1_next to v1,
//malloc what we need to, copy over the array and continue
if (v1_next != v1)
{
pNeighborList[i].nNeighbors = nNeighbors;
if (nNeighbors != 0)
{
pNeighborList[i].pNeighbors = (unsigned int*)malloc(nNeighbors * sizeof(unsigned int));
for (unsigned int j = 0; j < nNeighbors; j++)
{
pNeighborList[i].pNeighbors[j] = neighbors[j];
}
}
v1++;
break;
}
//else, increment the neighbor count for this particular vertex and continue
//within this loop, getting new neighbors (edges)
else
{
neighbors[nNeighbors] = v2_next;
nNeighbors++;
if (nNeighbors == 1000)
{
break;
}
fscanf(fp, "%u", &v1_next);
fscanf(fp, "%u", &v2_next);
}
}
}
}
void append(linkedNodeList* pLinkedList, unsigned int node)
{
//make new node with the intention that it's going to be the new tail
linkedNode* pNewNode = (linkedNode*)malloc(sizeof(linkedNode));
pNewNode->node = node;
pNewNode->pNextLinkedNode = NULL;
pNewNode->pPrevLinkedNode = pLinkedList->pTail;
//set next node of current tail to new node
(pLinkedList->pTail)->pNextLinkedNode = pNewNode;
//new tail becomes new node
pLinkedList->pTail = pNewNode;
//lastly, set old tail's next node to point to new tail
(pLinkedList->pTail->pPrevLinkedNode)->pNextLinkedNode = pLinkedList->pTail;
}
Upvotes: 0
Views: 58
Reputation: 3351
Judging by the screenshots, and assuming you are on a 64 bit system (a pointer being 8 bytes wide), the pointer pNeighborList
links to the start of the list, while pLook
links to the pNeighbors
attribute of a neighborList
element at index 5:
// assuming sizeof(neighborList) == 4 (int) + 8 (pointer) = 12 bytes
neighborList* pNeighborList = new neighborList[10];
// pNeighborList points to the start of the list, 0x00107a28
// pNeighborList[5] is at address 0x00107a64 (start + 5 * sizeof(neighborList)
// .pNeighbors is offset 4 more bytes (sizeof(unsigned int)) = 0x00107a68
int curNode = 5;
unsigned int* pLook = (pNeighborList[curNode]).pNeighbors;
// pLook points to pNeighbors of the element at index 5, 0x00107a68
When you hover the pointer pNeighborList
in Visual Studio, it shows you the pointer (which points to the start of the list), not the full value ((pNeighborList[curNode]).pNeighbors
).
Upvotes: 1