C & C++ DISCUSSION

Why does sizeof return the pointer size instead of the array length inside a C function?

Started by btbx sizeof operatorarray decaypointers vs arraysfunction parametersarray length
4 replies 248 views 5 participants
Latest activity · 30 Sep 2026

Why does sizeof return the pointer size instead of the array length inside a C function?

btbx C & C++ Forum
#1

I have uint16_t samples[64]; and use sizeof(samples) / sizeof(samples[0]) to get 64 in main. When I pass the array to void filter(uint16_t buf[]) and use the same expression inside the function, I get 2 on my 32-bit microcontroller and 4 on my PC, so the loop only processes the first few samples.

Why does the same expression give a different answer inside the function, and what is the normal way to write a function that works on arrays of any length?

Community replies 4

Re: Why does sizeof return the pointer size instead of the array length inside a C function?

#2

In a parameter list an array declarator is adjusted to a pointer. void filter(uint16_t buf[]), void filter(uint16_t buf[64]) and void filter(uint16_t *buf) declare exactly the same function; the 64 is ignored. Inside the function sizeof(buf) is therefore the size of a pointer: 4 bytes on the 32-bit MCU and 8 on a 64-bit PC. Divided by sizeof(uint16_t), which is 2, that gives your 2 and 4.

At the call site the expression samples is converted to a pointer to its first element, &samples[0]. The length is not passed along, so the function has no way to recover it.

Re: Why does sizeof return the pointer size instead of the array length inside a C function?

#3

Arrays and pointers are different types; an array is merely converted to a pointer in most expressions. The exceptions are the operand of sizeof, the operand of unary &, and a string literal used to initialise a char array. That is why sizeof(samples) is 128 in main.

It is also why &samples has the type uint16_t (*)[64], a pointer to the whole array. It holds the same address as samples, but &samples + 1 moves 128 bytes while samples + 1 moves 2. One more consequence: extern uint16_t *samples; in another file does not match an array definition and reads garbage; it has to be extern uint16_t samples[];.

Re: Why does sizeof return the pointer size instead of the array length inside a C function?

#4

The standard fix is to pass the length explicitly: void filter(uint16_t *buf, size_t n), called as filter(samples, ARRAY_LEN(samples)) with #define ARRAY_LEN(a) (sizeof(a) / sizeof((a)[0])). Use the macro only where the real array is in scope.

Compilers help here. GCC and Clang warn when sizeof is applied to a parameter declared as an array (-Wsizeof-array-argument), and -Wsizeof-pointer-div catches a pointer size being divided by an element size. Keep -Wall switched on and do not ignore either message.

Re: Why does sizeof return the pointer size instead of the array length inside a C function?

#5

Two other designs are worth knowing. If the function only makes sense for 64 samples, take a pointer to the whole array: void filter(uint16_t (*buf)[64]), called as filter(&samples). Then sizeof(*buf) is 128 and passing an array of another size draws a diagnostic.

Or keep pointer and length together in a struct, struct span { uint16_t *data; size_t len; };, so they cannot get out of step as they travel through several layers. In C++ the same job is done by std::array, a reference-to-array parameter, or std::span from C++20. A bare pointer is only enough when the data carries its own terminator, as a C string does.

TEP COMMUNITY