Creating a list and struct arrays using C [duplica

2019-08-12 23:25发布

问题:

This question already has an answer here:

  • How to find the 'sizeof' (a pointer pointing to an array)? 13 answers
  • How do I determine the size of my array in C? 20 answers

I'm currently starting out with C so I thought I'd try creating my own custom list. Here's the code:

#include <stdio.h>

struct list {
    char data[10];
    struct list *n;
};

void clist(struct list *a) {
    int j=(sizeof(a)/sizeof(a[0]));
    j--;    
    for(int i=0; i<j-1; i++) {
        struct list *next=&a[i+1];
        a[i].n=next; 
    }
}

int main() {

    struct list first = {.data="one", .n=NULL};
    struct list second = {.data="two", .n=NULL};
    struct list third = {.data="three", .n=NULL};

    struct list arr[] = {first, second, third}; 
    struct list *p=&arr[0];

    clist(p);

    struct list looper = first;

    while(looper.n!=NULL) {
        printf("%s ", looper.data);
        looper = *looper.n;
    }

    return 0;
}

So basically I have a struct that saves a char array and a pointer. I initialize them and then I try to link them together by giving it to the clist method. There lies the problem: it seems clist isn't getting anything useful as the variable j stays at 0. If I do the whole size calculation before giving the array to the clist method, I'm getting the correct 3 as a result. Why is that?

回答1:

In C, array parameters are treated as pointers . So the expression sizeof(a)/sizeof(a[0]) becomes sizeof(int *)/sizeof(int).

So what you are essentially getting is (how big your address is) / (size of integer)

The solution to this would be to send the number of elements in array a as another parameter to the function.



回答2:

Your code has several errors.

The first one is that inside function clist expression

sizeof(a)/sizeof(a[0])

is equivalent to

sizeof( struct list * ) / sizeof( struct list )

and will be equal to 0 because there are used integer values and the size of the pointer is less than the size of the pointed structure object.

You need expicitly pass the size of the array to the function. But even the variable j will be indeed equal to the size of the array this code in the body of the function is invalid

j--;    
for(int i=0; i<j-1; i++) {
    struct list *next=&a[i+1];
    a[i].n=next; 
}

Let's assume that the array has two elements. In this case initial value of j will be also equal to 2. After statement

j--;    

it will be equal to 1 and inside the loop

for(int i=0; i<j-1; i++) {

condition

i<j-1

will be evaluated to false. So the loop will not be executed and the list will not be built.

Also this loop in main

while(looper.n!=NULL) {
    printf("%s ", looper.data);
    looper = *looper.n;
}

will not display the data member of the last element because the last element has data member n equal to NULL.

I suggest the following modification of your program

#include <stdio.h>

struct list 
{
    char data[10];
    struct list *next;
};

void clist( struct list *a, size_t n ) 
{
    for( size_t i = 0, j = 1; j < n; ++i, j++ )
    {        
        ( a + i )->next = a + j; 
    }
}

int main( void )
{
    struct list first  = { .data="one",   .next = NULL };
    struct list second = { .data="two",   .next = NULL };
    struct list third  = { .data="three", .next = NULL };

    struct list arr[] = { first, second, third }; 

    clist( arr, sizeof( arr ) / sizeof( *arr ) );

    for ( struct list *first = arr; first != NULL;  first = first->next ) 
    {
        printf( "%s ", first->data);
    }


    return 0;
}

Its output is as it is expected

one two three