tags:

views:

240

answers:

5

When declaring a const table, it is possible to get the size of the table using sizeof. However, once you stop using the symbol name, it does not work anymore. is there a way to have the following program output the correct size for table A, instead of 0 ?

#include <stdio.h>

struct mystruct {
    int a;
    short b;
};

const struct mystruct tableA[] ={
    { 
        .a = 1,
        .b = 2,
    },
    { 
        .a = 2,
        .b = 2,
    },
    { 
        .a = 3,
        .b = 2,
    },
};

const struct mystruct tableB[] ={
    { 
        .a = 1,
        .b = 2,
    },
    { 
        .a = 2,
        .b = 2,
    },
};


int main(int argc, char * argv[]) {
    int tbl_sz;
    const struct mystruct * table;

    table = tableA;
    tbl_sz = sizeof(table)/sizeof(struct mystruct);
    printf("size of table A : %d\n", tbl_sz);

    table = tableB;
    tbl_sz = sizeof(tableB)/sizeof(struct mystruct);
    printf("size of table B : %d\n", tbl_sz);

    return 0;
}

Output is :

size of table A : 0
size of table B : 2

This is the intended behavior of sizeof. But is there a way for a compiler to know the size of a const table, given a pointer to the table instead of the symbol name ?

+5  A: 

you are asking for the sizeof a pointer. That is always the pointer size (ie usually 4 bytes on a 32-bit machine and 8 bytes on a 64-bit machine). In the 2nd attempt you are asking for the sizeof the array and hence you get the result you'd expect.

Goz
I understand the behavior, I am looking for a way to get the size of tableA without using its symbol
shodanex
C simply doesn't do that. It's pointers do not magically know the size of arrays that they point to.If they did, it would be odd. Imagine a pointer to an entry in the middle of an array: what would `sizeof()` that return? Right now, it's either the size of the pointer or the size of the element pointed to (depending on dereferencing level). That established, why is pointing to the start of the array any more special? (Answer: it isn't.)
Donal Fellows
A: 

Although syntactically correct, your sample is more conventionally written as:

const struct mystruct tableA[] = {
    {1, 2},
    {2, 2},
    {3, 3}, 
};

Which is less verbose and therefore more readable.

msw
Because I initialised all fields,and it is a simple structure, but add some field or even other struct, and the initialisation style you propose quickly becomes unreadable. Anyway, this is not an answer to my question, and not the place to discuss this.
shodanex
+1  A: 

No - you're asking for the sizeof() a pointer. But since what you're really trying to get is the number of elements in an array, you can use a macro that will return that value but will generally give you an error if you pass a pointer instead of an array:

#define COUNT_OF(x) ((sizeof(x)/sizeof(0[x])) / ((size_t)(!(sizeof(x) % sizeof(0[x])))))

See this SO answer for more details: http://stackoverflow.com/questions/1598773/is-there-a-standard-function-in-c-that-would-return-the-length-of-an-array/1598827#1598827

For an even safer solution when using C++ instead of C, see this SO answer that uses templates to ensure that trying to get an array count on a pointer will always generate an error: http://stackoverflow.com/questions/1500363/compile-time-sizeof-array-without-using-a-macro/1500917#1500917

Michael Burr
+2  A: 

Is there a way for a compiler to know the size of a const table, given a pointer to the table instead of the symbol name?

No, because sizeof() is evaluated at compile-time (unless it is a VLA, but a VLA is not a constant table), and the compiler cannot, in general, tell which table the pointer is pointing to. Granted, in the scenario shown, it might be possible in some hypothetical variation of the C language, but that would mean varying definitions of what sizeof() returns, which would be a bigger problem than not getting the answer you might like but do not get.

So, as everyone else ably pointed out, when you take the size of a pointer, you get the size of the pointer. Assuming a standard 32-bit machine since the results are consistent with that assumption, your structure is 8 bytes and your pointers are 4 bytes, so the result of the division is zero, as expected.

Jonathan Leffler
+1  A: 

Short answer is no; if all you have is a pointer, then there's no (standard) way to get the size of the thing being pointed to through that pointer.

John Bode