Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

C pointer returning data other than the expected contents, but the data remains the same no matter the index accessed?

I have a 2d array, const unsigned long test_tileset[n][8], which I’m trying to load into a struct.

The struct is defined as:

typedef struct DynamicTileset {
    unsigned long **tileset;
    LinkedList* usedTiles;
    short* tilemap;
} DynamicTileset;

and I assign the value using the function:

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

DynamicTileset* createDynamicTileset(unsigned long **tileset) {
    DynamicTileset* dynamicTileset = malloc(sizeof(DynamicTileset));
    dynamicTileset->tileset = tileset;
    dynamicTileset->usedTiles = createLinkedList();
    dynamicTileset->tilemap = NULL;
    return dynamicTileset;
}

called as:

DynamicTileset* title_tileset = createDynamicTileset(test_tileset);

And verify that title_tileset->tileset == test_tileset.

The problem arises when I try to access any of the tiles from the struct. I can access indices in the original tileset just fine via test_tileset[i][j], but when I try to do the same through title_tileset->tileset[i][j], I get a specific set of seemingly random data every time. I’m guessing I’ve messed something up with the pointers here, but I can’t seem to figure out what. How can I assign one of these tilesets to the struct?

Minimal example:

//You likely want to include these in a separate .c file and include the .h, to prevent the error  
//"multiple definitions" from happening when compiling. I do not know if this happens to others
//or if it is simply my compiler.
const unsigned long test_tileset[1][8] = {
    {   0x12345678,
        0x23456789,
        0x3456789A,
        0x456789AB,
        0x56789ABC,
        0x6789ABCD,
        0x789ABCDE,
        0x89ABCDEF
    }
};

typedef struct Node
{
    int data;
    struct Node *next;
} Node;

typedef struct LinkedList
{
    Node *head;
    Node *tail;
    int size;
} LinkedList;

typedef struct DynamicTileset {
    unsigned long **tileset;
    LinkedList* usedTiles;
    short* tilemap;
} DynamicTileset;


struct LinkedList* createLinkedList() {
    struct LinkedList* list = malloc(sizeof(struct LinkedList));
    list->head = NULL;
    list->tail = NULL;
    list->size = 0;
    return list;
}

DynamicTileset* createDynamicTileset(unsigned long **tileset) {
    DynamicTileset* dynamicTileset = malloc(sizeof(DynamicTileset));
    dynamicTileset->tileset = tileset;
    dynamicTileset->usedTiles = createLinkedList();
    dynamicTileset->tilemap = NULL;
    return dynamicTileset;
}

//this should be in the main file
int main() {
    DynamicTileset* title_tileset = createDynamicTileset(test_tileset);

    if (title_tileset->tileset != test_tileset) {
        printf("tileset pointer is wrong");
    }
    for (int i=0; i<8; i++) {
        if (title_tileset->tileset[0][i] != test_tileset[0][i]) {
            printf("first tile is wrong");
            break;
        }
    }
}

>Solution :

I added the missing headers and typedefs. Removed the struct name LinkedList and used the typedef name in your code. Then I changed the type of your test_tileset to match your use (both u32/unsigned long, and [][] to **). Added a const cast when you compare the const and non-cost types values. Your code now compiles without warning and prints nothing (success):

#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
typedef uint32_t u32;
typedef int16_t s16;

const u32 **test_tileset = (const u32 *[]) {
    (u32 []) {
        0x12345678,
        0x23456789,
        0x3456789A,
        0x456789AB,
        0x56789ABC,
        0x6789ABCD,
        0x789ABCDE,
        0x89ABCDEF
    }
};

typedef struct Node
{
    int data;
    struct Node *next;
} Node;

typedef struct
{
    Node *head;
    Node *tail;
    int size;
} LinkedList;

typedef struct DynamicTileset {
    u32 **tileset;
    LinkedList* usedTiles;
    s16* tilemap;
} DynamicTileset;


LinkedList *createLinkedList() {
    LinkedList* list = malloc(sizeof(*list));
    list->head = NULL;
    list->tail = NULL;
    list->size = 0;
    return list;
}

DynamicTileset* createDynamicTileset(const u32 **tileset) {
    DynamicTileset* dynamicTileset = malloc(sizeof(DynamicTileset));
    dynamicTileset->tileset = (u32 **) tileset;
    dynamicTileset->usedTiles = createLinkedList();
    dynamicTileset->tilemap = NULL;
    return dynamicTileset;
}

int main() {
    DynamicTileset* title_tileset = createDynamicTileset(test_tileset);
    if ((const u32 **) title_tileset->tileset != test_tileset) {
        printf("tileset pointer is wrong");
    }
    for (int i=0; i<8; i++) {
        if (title_tileset->tileset[0][i] != test_tileset[0][i]) {
            printf("first tile is wrong");
            break;
        }
    }
}
Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading