C Newbie - Help Finding Size Of Arrays?

Okay, I’ve finally come back to learning C/C++… Well I’m trying to find a way to write a function to return the size of an array, basically… I know that you have to do something like:

arrLen = sizeof(testArr)/sizeof(int)

However, when I put that into a function or itself, it returns an incorrect value…? …
I’m basically trying to do something along the lines of:

int getLength(auto a[])
{
	int len = sizeof(a)/sizeof(auto);
	return len;
}

I know that auto isn’t a valid in this case, it’s kinda like the pseudo code I’m trying! :stuck_out_tongue:
As you can tell, I’m back to level 1… :joy:

Getting the size of an array is impossible. C does not store the array’s size along with the data and thus cannot determine where the array ends.

You may have seen sizeof being applied to arrays, but that is only possible where the array was allocated because the size is still known at that point.

2 Likes

That makes more sense to me now… Can you suggest a function that would return the length of any type of array in C? … If not I can always do something like:

int testArr[] = {1,10,10,12}, 
arrLen = sizeof(testArr)/sizeof(int);

It’s hardly hard to do it this way, but I just thought that a function/shortcut for it… No biggie either way?

Is this array pre-populated, or are you seeding it yourself in the program?

If the latter, think about incrementing a counter as you add/subtract to the array. It’s clodgy, but it may work for what you need.

1 Like

AFAIK the only way is:

size_t len = sizeof(arr)/sizeof(arr_elem_t);

EDIT: but I think doesn’t work for malloc'ed stuff:

$ cat tmp.c    
#include <stdlib.h>
#include <stdio.h>
#include <stddef.h>
#include <stdint.h>
#include <stdbool.h>


int main(void)
{
	int32_t arr[] = {1, 2, 3, 4, 5, 6, 7, 8};
	size_t arr_size = sizeof(arr) / sizeof(int32_t);

	int32_t* harr = (int32_t*)malloc(8 * sizeof(int32_t));
	if(!harr)
		return -1;

	size_t harr_size = sizeof(harr) / sizeof(int32_t);
	free(harr);

	printf("len(arr) = %zu; len(harr) = %zu;\n", arr_size, harr_size);

	return 0;
}
$ gcc tmp.c    
$ ./a.out 
len(arr) = 8; len(harr) = 2;
$

It’s 2 because sizeof pointer is on 64bit PC and OS is 8 bytes int32_t is 4 so, it’s 2. It literally just sees the array as pointer, coz that what it is.

Arrays are sequences of bytes in memory. Unless the array contains some sort of marker to identify the last element finding out the length is literally impossible.

I suppose you could create a macro which defines an array and returns it’s length, but that will only make your code harder to read. Your solution is the way to go imo

EDIT: If you are in C++ use std::vector instead. Those are encapsulated arrays which also keep track of their size.

It doesn’t work for any array that has not been declared in the same scope. Regardless of whether the array is on the heap or the stack, there is no way for the compiler to determine it’s length.

To add to this, this is happening because Arrays != Pointers, at compile time at least. sizeof is a compile time “operator”.

Local arrays have constant size known at compile time, so sizeof can return their size (in bytes). When you malloc an array, compiler has no way to know the size (since it can change during runtime) so it cannot do anything but return the size of the pointer, or if you deference it, the size of type (both in bytes ofc).

Also as @pFtpr said, when you pass the array to some function, you pass it as a pointer, so you lose all the compile-time knowledge of it. Because it is in different scope, compiler can’t make any assumptions there. It’s another scope, that pointer can come from anywhere.

Okay, I’m honestly grateful for you sharing this with me, I didn’t know this was the case.

I guess it’s no hardship to pre-define the size of the array and pass it into some function, I mean in all fairness, adding a feature to just return the length of the array would probably end up require more lines than just getting the length within local scope?

I will look more into it, just to learn how to actually do it. But for now, the code I’ve been working on works well enough, I’ve just built a simply program where you have to define the size of an array, then enter an int for x number of times, x being the predefined length of the array. I’ve also included some error handling, let’s say you enter a char, it’ll just break and return an error output of ‘invalid input’.

Finally, I’m glad I’ve started learning C, purely because I knew it was fairly low level, but for some strange reason I thought it was more high level than what it actually is. I’ve had experience with assembly itself, so I get the idea of how assembly works, i.e. how to make a loop yourself. I just thought C had more features than what it actually does have! :slight_smile:

You’re wrong. EDIT: actually, pFtpr said the same thing as me, my bad. In C, an array is a continuous memory region.

sizeof(arr)/sizeof(arr[0]) works if you use it where you have declared the array and not in a function. The reason for this is that C promotes and array to a pointer when the array is passed as an argument to a function.

Use a macro for this, and not a function. Example here: Linux kernel

So which part do we disagree on? I’ve said the same thing you have.

Sorry, misread part of your post. I’ll edit my reply.

Would it be easier to just use a doubly linked list?
That way you can traverse and your list can be dynamic in size. You could essentially make a mini vector in C using this methodology and import it into all of your code. You then do not have to worry about scope and what not. Maybe that is more complex than what you need?

You should only use arrays when you know the size. If you won’t know the size, like at run-time, then you need to use a vector.

2 Likes

The size of an array is only known in the scope it was declared, you could try making a macro instead of a function, but it would only work if you use it in the same function you declared the array. Depending on what the contents of the array will be, you could put a value you know won’t be in the array at the end, but normally you just have to keep a variable with the size on it. On c++, you can use std::vectors, at the cost of some efficiency.