0

In my initial approach to creating a trie, instead of using pointers going to the left/right I attempted to put an array of structs inside malloc'd memory. Is this possible? In principle can struct array[] = struct* head?

Ok here's the code I was using:

typedef struct node
{
    char letter;
    struct node* child;
}
node;

int main(void)
{
    node* head = malloc(26*sizeof(node));
    if (head == NULL)
        return 1;

    node* temp = head;

    node array[26];

    array = temp;
    //proceed to fill array...

What I don't understand is if pointers and array[] are both addresses in memory, how come they can't be equated?

Peter T
  • 11
  • 2
  • 2
    No, you can't. Try it and see ([demo](https://eval.in/667689)): _"error: incompatible types when assigning to type ‘int[10]’ from type ‘int *’"_. Fundamentally, ***a pointer is not an array, and an array is not a pointer***. An array merely decays into a pointer in certain cases. But the two are distinct types. Even if this were possible, it'd cause an infinite number of problems/UB: `arr = ptr; free(ptr); printf("%d\n", arr[0]);` == boom. Stuff like that – Elias Van Ootegem Oct 27 '16 at 17:17
  • No, but you can use the head pointer as an array, head[0].some_member, head[1].some_other_member and so forth – Bjorn A. Oct 27 '16 at 17:20
  • Could you clarify with code what you're trying to do? – xvan Oct 27 '16 at 17:35
  • Are you creating a **[trie](https://en.wikipedia.org/wiki/Trie)** (26 children per node), or a **[binary tree](https://en.wikipedia.org/wiki/Binary_tree)** (2 children per node)? – user3386109 Oct 27 '16 at 17:52
  • But surely if you free(ptr) you just automatically lose any access to arr? – Peter T Oct 27 '16 at 18:02
  • Any variable is in fact an address to memory. Pointers are just adresses that you can manage, and arrays are table of adresses to blocks of arrays type size. You can always dereference & reference from a variable or a pointer. Casting is just to indicate processor how many bytes to move it up & down. – DvTr Oct 27 '16 at 18:14
  • @user3386109 A trie. So to go down a level of the trie I was trying to do: `array[0].child = malloc(26*sizeof(node))` Then `array = array[0].child` – Peter T Oct 27 '16 at 18:15
  • In response to the updated question. You can think of `array` as a read-only pointer. It points to memory that contains 26 nodes, and can only point at that particular memory. On the other hand, `temp` is a read-write pointer. `temp` can point to the memory allocated by `malloc` or the memory allocated for `array`. So the statement `temp = array;` is valid, but the statement `array = temp;` is not.. – user3386109 Oct 27 '16 at 18:28
  • 1
    Ok thanks @user3386109. I think I get the problem now. – Peter T Oct 27 '16 at 19:36

1 Answers1

0

As you sure know, a pointer is not exactly a type of data, meaning this capacity (or number of bytes used), but just a memory direction reference: a number (expressed as XXXXX:XXXXX the main cases and in the main SO as a 4-bytes number) that indicates memory page & offset inside that page. Memory referenced by that direction could had been allocated, or not. That's it, marked to SO that is reserved for use for your program. But in any case it's protected just for that variable: your program can use that memory block, and for example, assign it to any type of variable. If you allocate correct sized memory for your struct, and then reference to that memory address, you can use it with no difference as if you had been declared as a normal variable.

In this example, you can use without any difference line ST S[3] or ST *S = malloc(sizeof(ST)*3); As seen, sizeof(ST) will give to you 4(int) + 1(char B) + 20*1(char[20]) = 25 bytes, and with padding, 28. malloc(sizeof(ST)*3) will then reserve 84 bytes for your program (surely more, surely 128 bytes reserving whole page block) and will give to you memory direction of the first byte reserved. In fact, this malloc it's about the same as declaring ST S[3];

Because of big number of possibilites pointers allow, as direct access to memory are (for example, a big number of variables sharing same memory, or capacity to go up & down along memory block) they are then difficult to manage, and so, a big nest of bugs, preferring then more uplevel abstraction. But your question's answer is yes, it is possible.

#include <malloc.h>

typedef struct ST
{
    int A;
    char B; 
    char C[20];
} ST;

int main(int agrc, char *agrv[])
{
    //  ST S[3];    
    ST *S = malloc(sizeof(ST)*3);
    //  ST *S = malloc(100);

    S[0].A = 1;         S[0].B = '1';       S[0].C[0] = 'a';
    S[0].C[1] = 'b';    S[0].C[2] = 'c';    S[0].C[3] = '\0';

    S[1].A = 2;         S[1].B = '2';       S[1].C[0] = 'A';
    S[1].C[1] = 'B';    S[1].C[2] = 'C';    S[1].C[3] = '\0';

    S[2].A = 3;         S[2].B = '3';       S[2].C[0] = 'Z';
    S[2].C[1] = 'z';    S[2].C[2] = 'Z';    S[2].C[3] = '\0';

    int i=0;
    for (i=0;i<3;i++)
    {
        printf("Struct %d\n",i);
        printf("%d\n",S[i].A);
        printf("%c\n",S[i].B);
        printf("%s\n",&S[i].C);
        printf("\n");
    }   
}

ADDED : This is the same, but from the other way : going to a direction of a string in memory, and interpreting it as it was our struct.

#include <malloc.h>

typedef struct ST
{
    short  A; // 2
    char B;  // 1
    char C[20]; // 20
} ST;

int main(int agrc, char *agrv[])
{
    char *s =malloc(28);

    s[0] = 65; // Lower byte of int
    s[1] = 65; // Higher byte of int
    s[2] = 'C'; 
    s[3] = 'a';
    s[4] = 'b';
    s[5] = 'c';
    s[6] = 0x00;

    printf("%s\n",s);

    ST *T;

    T = (void *)s;

    printf("%d\n",T[0].A);
    printf("%c\n",T[0].B);
    printf("%s\n",T[0].C);
}
Community
  • 1
  • 1
DvTr
  • 347
  • 1
  • 5