Sign in to follow this  

array size/length in C

This topic is 4398 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

Does anyone know how to check for the length of an arbitrary array in C? I used to know this... I think it was something like: #define length(a) (sizeof(a)/sizeof(a[0])) however, the above hasn't worked out so well when I tried it so I'm guessing it's incorrect :p Any ideas?

Share this post


Link to post
Share on other sites
Quote:
Original post by Oluseyi
It can't be done. You can use that trick only to account for the length of a statically allocated array within the scope in which it was allocated.


This is correct, to add to the above: the actually variable types are different between static and dynamic arrays. static arrays are known to the compiler as an array, but a dynamic array is known as a pointer. I've never been a 100% certain about all of this, never seen really good documentation either.

void foo()
{
int a[16];
int * b = malloc(sizeof(int) * 16);
}

"a" is of type int[16] and "b" is of type int*... this explains why that length() macro doesn't work.

Share this post


Link to post
Share on other sites
You could check how much space one entry takes, and then simply count the number of entries in the array and multiply with the size of one. ;)

Share this post


Link to post
Share on other sites
Quote:
Original post by Rasmadrak
You could check how much space one entry takes, and then simply count the number of entries in the array and multiply with the size of one. ;)


Just for clarification, the OP want's to find the number of entries, so he cannot use that method [wink]

Share this post


Link to post
Share on other sites
Quote:
Original post by Drew_Benton
Just for clarification, the OP want's to find the number of entries, so he cannot use that method [wink]

Actually, he can - if he appends an "end of sequence" identifier to every one of his arrays. That, after all, is how C strings and strlen work...

[Edit:] Alternately, he could prepend length information, so that his custom routine doesn't need to traverse the array to determine length. That's how Pascal strings work. Ultimately, though, it's better to use std::vector if C++ is an option. The benefits are many, well beyond trivial sequence length calculation.

Share this post


Link to post
Share on other sites
Thanks for the replies guys. I guess it can't be done :( or the closest way to doing it would be to use an identifier like Oluseyi mentioned. Thanks!

Share this post


Link to post
Share on other sites
Typically, you'll define an "array" as a struct, that contains both the count (and possibly a separate logical vs physical count), and a pointer to the data. This has the added benefit that if you resize the array data, the pointer to the array doesn't change.

Share this post


Link to post
Share on other sites
If it was an array of structs or classes wouldn't sizeof() return the padding between members also? Just asking for my own sanity. I just woke up, but I should know the answer and it's not coming to me right away.

Share this post


Link to post
Share on other sites
The sizeof a struct includes the padding, thus the division works out right.

Share this post


Link to post
Share on other sites
With C++, rather than C, you can use:


template <typename T, int N>
int ArraySize(T const (&val)[N])
{
return(N);
}

void foo(void)
{
char s[40] = "some text";
std::cout << "Size of " << s << " is " << ArraySize(s) << std::endl;
}

Share this post


Link to post
Share on other sites
Quote:
Original post by LilBudyWizer
With C++, rather than C, you can use:

*** Source Snippet Removed ***


that boils down to sizeof(someArray) in c, but it will not work with dynamically allocated arrays.

anyway the poster stated that they were using c.

if you are using c++ you might as well use a vector.

Share this post


Link to post
Share on other sites
Quote:
Original post by mikeman
In C, _msize( void *memblock ) returns the the size in bytes of a block allocated with malloc,realloc or calloc.


Non standard function. Not all compilers support it. Well, technically it's the version of the C runtime that supports it. Ex: it doesn't work with most gcc installations.

Share this post


Link to post
Share on other sites
If you want a really nasty hack to get the job done, allocate extra memory and store an integer in the first few bytes, then offset the pointer. Here's how:


#define HACK_MALLOC(resultPtr,type,num){ unsigned char* mem = (unsigned char*)malloc( (num * sizeof(type)) + sizeof(unsigned int) ); if (mem){ *((unsigned int*)mem) = num; resultPtr = (type*)(mem + sizeof(unsigned int)); }else{ resultPtr = 0; } }

#define HACK_REAL_PTR(ptr) (((unsigned char*)ptr) - sizeof(unsigned int))

#define HACK_LENGTH(ptr) (*(unsigned int*)(HACK_REAL_PTR(ptr)))

#define HACK_FREE(ptr) free(HACK_REAL_PTR(ptr))

int main(){
//A quick example.
int* array = 0;
HACK_MALLOC(array,int,16);
printf("# ELEMS: %d\n",HACK_LENGTH(array));
HACK_FREE(array);
return 0;
}





[EDIT]
Changed the code a bit since the backslashes in the HACK_MALLOC macro don't show up. Looks a little cleaner now.

[EDIT 2]
Added some error checking (to the HACK_MALLOC macro). Now it'll return 0 if malloc() fails.

[EDIT 3]
Here's the 'routine' version, as requested by bytecoder:


void* hackMalloc(unsigned int num,unsigned int typeSize){
unsigned char* mem = (unsigned char*)malloc(
(num * typeSize) + sizeof(unsigned int)
);
if (mem){
*((unsigned int*)mem) = num;
mem += sizeof(unsigned int);
}
return mem;
}

void* hackRealPtr(void* ptr){
return (((unsigned char*)ptr) - sizeof(unsigned int));
}

unsigned int hackLength(void* ptr){
return (*(unsigned int*)(hackRealPtr(ptr)));
}

void hackFree(void* ptr){
free(hackRealPtr(ptr));
}

int main(){
int* array = (int*)hackMalloc(16,sizeof(int));
printf("# ELEMS: %d\n",hackLength(array));
hackFree(array);
return 0;
}



[Edited by - Gorax on January 1, 2006 10:38:36 AM]

Share this post


Link to post
Share on other sites
Why are you using macros for something that could easily be done with routines?

edit:
In any event, the only hack in there was the use of macros. It's basically just a simplified container, and works almost exactly like hplus0603's suggestion except it dynamically allocates the size instead of putting it in a struct. Personally, though, I like the struct method better.

Share this post


Link to post
Share on other sites
Quote:
Original post by bytecoder
Why are you using macros for something that could easily be done with routines?


Added it to my previous post.

Quote:

edit:
In any event, the only hack in there was the use of macros. It's basically just a simplified container, and works almost exactly like hplus0603's suggestion except it dynamically allocates the size instead of putting it in a struct. Personally, though, I like the struct method better.


A 'quick hack' (and subsequently a 'hack') as I know it, is something that's hacked together to get the job done, just like magic numbers. The struct method looks nicer, but if you wanted to avoid the whole 'myStruct.data' thing, my method'd be better.

Share this post


Link to post
Share on other sites
thanks for all the help! just to let you guys know though in the end I just added a var to each of the necessary structs to track how many items are in the array. so something like:


typedef struct poly{
VECTOR* vertex;
u8 nVertices;
} POLY;

and I just have to make sure to keep the variables updated.

Share this post


Link to post
Share on other sites
Sign in to follow this