Need Help or More Information?
Questions about this free C programming course, embedded C training or career guidance? Get in touch.
Array Name vs Pointer
Subscript a pointer variable, learn what an array name can and cannot do, and finish with a quiz and interview questions. The closing lecture of this group in our free C tutorial for embedded systems.
Topics in This Lecture
Arrays and pointers look so alike in C that many learners assume they are the same thing. They are not, and the difference between an array name vs pointer variable is one of the most tested topics in C interviews and one of the most common sources of bugs in embedded C programming. In this final lecture of the group from our free C programming course we show where the two behave identically, where they differ, and why. You will also find a hands-on quiz and a set of interview questions with answers.
Like the earlier lectures in this free embedded C course, every program and every compiler message below was produced by real GCC runs on 64-bit Linux.
What You Will Learn
- How to point a pointer variable at an array and subscript it with
ptr[i] - Why
*(ptr + i)andptr[i]are equivalent - What an array name cannot do that a pointer variable can
- How
sizeoftells an array and a pointer apart - Why an array parameter silently becomes a pointer inside a function
- How dynamic arrays rely on pointer subscripting
- Quiz questions and interview answers to test yourself
Prerequisites
Complete the previous three lectures first: array memory layout, array address arithmetic, and pointer notation for arrays. You should also know how to declare a pointer and use ++ on it.
Subscripting a Pointer Variable
Suppose you declare an array and a pointer, then store the array’s base address in the pointer. From that moment the pointer is a second route to the same memory.
int lut[4] = {10, 20, 30, 40};
int *p = lut; /* same as p = &lut[0] */
With p holding the base address, p + i is the address of element i and *(p + i) is its value. Since x[i] is defined as *(x + i) for any pointer x, you can also write p[i]. The subscript operator never cared whether the left side was an array or a pointer; it only needs an address and an index.
Two names, one block of memory
This equivalence is what makes dynamic arrays practical. When memory comes from malloc, all you ever receive is a pointer, yet you happily write buf[i]. And when you pass an array to a function, the function receives a pointer and uses the same notation.
Array Name vs Pointer Variable: The Differences
An array name is not a variable that stores an address. It names the whole block of elements. The address you get from it is computed by the compiler when the name appears in an expression. A pointer variable, in contrast, is a real object with its own storage that contains an address and can be changed.
| Property | Array name lut | Pointer variable p |
|---|---|---|
| What it is | The whole block of elements | A variable holding an address |
| Occupies extra storage for an address | No | Yes, one pointer-size object |
| Can be assigned a new address | No | Yes |
| Can be incremented or decremented | No | Yes |
sizeof result | Total bytes of all elements | Size of the pointer itself |
Can use [ ] | Yes | Yes |
Can use * and + | Yes (via decay) | Yes |
What you may do with each
Example 1: sizeof and Pointer Moves
This program shows sizeof for both, subscripts the pointer, moves the pointer around freely, and then passes the array to a function to reveal array decay.
#include <stdio.h>
static void show_param(int a[])
{
printf("inside function : sizeof a = %zu\n", sizeof a);
}
int main(void)
{
int lut[4] = {10, 20, 30, 40};
int *p = lut;
printf("sizeof lut = %zu, sizeof p = %zu\n", sizeof lut, sizeof p);
printf("p[2] = %d, *(p + 2) = %d\n", p[2], *(p + 2));
p++;
printf("after p++ : p[0] = %d\n", p[0]);
p--;
p = lut + 3;
printf("after p = lut + 3 : *p = %d\n", *p);
show_param(lut);
return 0;
}
Build and run
gcc -Wall -Wextra -std=c11 -o l19_ptr l19_ptr.c
./l19_ptr
GCC prints a helpful warning at the sizeof a line, which we will explain below:
l19_ptr.c:5:57: warning: 'sizeof' on array function parameter 'a' will return size of 'int *' [-Wsizeof-array-argument]
Expected output (64-bit Linux)
sizeof lut = 16, sizeof p = 8
p[2] = 30, *(p + 2) = 30
after p++ : p[0] = 20
after p = lut + 3 : *p = 40
inside function : sizeof a = 8
What each line teaches
sizeof lutis 16 because the array holds four 4-byte integers.sizeof pis 8 because a pointer on this machine is 8 bytes. On a 32-bit microcontroller it would be 4.p[2]and*(p + 2)print the same value, so a pointer variable can be subscripted just like the array.p++makesppoint at the second element, sop[0]is now 20. The pointer can walk, and it can also be reset or reassigned to any element.- Inside
show_param,sizeof agives 8, not 16. The parameter looks like an array but the compiler treats it asint *a. The size information is gone, and that is exactly what the warning says.
Array Decay in Function Parameters
The syntax int a[] and even int a[10] in a function parameter list is just another way of writing int *a. The number inside the brackets is ignored by the compiler. The function therefore cannot know how many elements the caller’s array has.
This is why C library functions and your own functions usually take a pointer plus a separate length argument, for example void process(const uint16_t *samples, size_t count). Always pass the count; never compute it with sizeof inside the callee.
Example 2: What the Compiler Says About lut++
Try to move the array name like a pointer and the compiler stops you.
int main(void)
{
int lut[4] = {10, 20, 30, 40};
lut++;
return 0;
}
gcc -Wall -std=c11 l19_bad.c -o bad
l19_bad.c:4:8: error: lvalue required as increment operand
4 | lut++;
| ^~
“Lvalue required” means the operand must be something that can be assigned to. An array name is not such an object, so lut++, lut-- and lut = &other are all rejected. If you need a movable position, create a pointer and move that instead.
Example 3: Dynamic Array With Pointer Subscripts
A heap-allocated array has no array name at all. You only have a pointer, and subscripting is how you use it.
#include <stdio.h>
#include <stdlib.h>
int main(void)
{
size_t n = 5;
int *sq = malloc(n * sizeof *sq);
if (sq == NULL)
return 1;
for (size_t i = 0; i < n; i++)
sq[i] = (int)(i * i);
for (size_t i = 0; i < n; i++)
printf("sq[%zu] = %d\n", i, sq[i]);
free(sq);
return 0;
}
gcc -Wall -Wextra -std=c11 -o l19_heap l19_heap.c
./l19_heap
sq[0] = 0
sq[1] = 1
sq[2] = 4
sq[3] = 9
sq[4] = 16
Writing malloc(n * sizeof *sq) instead of repeating the type is a good habit: if you later change the pointer type, the allocation size follows automatically. Many small embedded systems avoid malloc altogether, but the same pointer-subscript pattern applies to static buffers handed around as pointers.
Real-World Embedded Use Cases
- A UART driver receives a
uint8_t *and a length, then indexes it withbuf[i]. - A DMA setup function takes the base address of the array as a pointer.
- A sensor library exposes
const int16_t *samplesand walks it with a moving pointer. - A table in flash is declared as an array in one file and accessed through a pointer parameter in another.
Common Mistakes and Troubleshooting
| Mistake | Symptom | Fix |
|---|---|---|
Using sizeof on an array parameter | Gets pointer size, loop covers too few elements | Pass the element count as a separate argument |
| Incrementing the array name | Compile error: lvalue required | Use a separate pointer variable |
Assuming sizeof(p) is the array size when p is a pointer | Wrong buffer lengths | Track length yourself |
Forgetting to check malloc result | Crash on first write | Test for NULL before use |
| Returning a pointer to a local array | Dangling pointer, garbage data | Use static storage, caller buffer or heap |
Best Practices, Performance and Security
Best practices
- Declare read-only array parameters as
const T *plus asize_tcount. - Use
sizeof(arr) / sizeof(arr[0])only where the real array is in scope. - Keep the original array name or base pointer unchanged, and walk with a second pointer.
- Compile with
-Wall -Wextrato catchsizeofmisuse.
Performance: passing a pointer copies only an address, not the whole array, so function calls stay cheap even for large buffers.
Security: because a pointer parameter carries no length, always validate the count against the real buffer capacity. A wrong count is the classic cause of buffer overflows in network and file parsers.
Summary and Key Takeaways
- A pointer variable pointing at an array can be subscripted:
p[i]equals*(p + i). - An array name is not a modifiable variable; it cannot be incremented or reassigned.
sizeofof an array is the total bytes;sizeofof a pointer is the pointer size.- Array parameters in functions are really pointers, so length must be passed separately.
- Dynamic arrays are used through pointers with the same subscript notation.
Conclusion
You have now seen both sides of the array and pointer relationship. They share notation and arithmetic, yet an array is a block of storage while a pointer is a variable holding an address. Keeping that distinction clear will save you from subtle bugs in embedded C programming and from missed questions in technical interviews. Work through the quiz and the interview section below, then try writing your own small function that takes a pointer and a count and returns the largest element.
Quiz: Test Your Understanding
Quick Quiz: Arrays and Pointers
Try each question first, then open the answer. Assume a 64-bit Linux system where int is 4 bytes and a pointer is 8 bytes.
- If
int a[6];has base address B, what is the address ofa[4]?Show answer
B + 16 bytes, because 4 elements of 4 bytes each lie before it.
- Which of these is NOT equivalent to
a[2]:*(a + 2),*(2 + a),2[a],*a + 2?Show answer
*a + 2. It reads element 0 and adds 2 to the value, instead of reading element 2. - True or false: an array name can be incremented to walk through the array.
Show answer
False. The array name is not a modifiable lvalue. Use a pointer variable.
- What does
sizeofreturn forint x[10]in the same function where it is declared?Show answer
40, which is ten elements of 4 bytes.
- A function is declared
void f(int a[10]). What issizeof ainside it?Show answer
8 on this system. The parameter is really
int *a, so you get the pointer size. - Predict the output:
int a[4] = {3, 6, 9, 12}; int *p = a + 1; printf("%d %d %d\n", *p, p[1], *(p - 1));Show answer
6 9 3. The pointer starts at element 1; p[1] is element 2; p – 1 is element 0. - Predict the output:
int a[4] = {3, 6, 9, 12}; int *p = a; p += 2; printf("%d %td\n", *p, p - a);Show answer
9 2. After adding 2 the pointer references element 2, and the difference from the base is 2 elements. - Predict the output:
int a[3] = {10, 20, 30}; int *p = a; p++; *p = 99; printf("%d %d %d\n", a[0], a[1], a[2]);Show answer
10 99 30. Writing through the moved pointer changes the original array’s element 1. - Which loop condition is safe for a pointer walk over
nelements starting atp = a, withend = a + n:p <= endorp != end?Show answer
p != end. Using<=would run one step too far and read the one-past-the-end position. - Why should you pass a length alongside an array to a function?
Show answer
The array decays to a pointer, which carries no size information, so the function has no other way to know the element count.
Interview Questions on Arrays and Pointers
C Interview Questions With Answers
1. Are arrays and pointers the same thing in C?
No. An array is a contiguous block of elements; a pointer is a variable that stores an address. They are related because an array name converts to a pointer to its first element in most expressions, and because the subscript operator works on any pointer.
2. Why is arr[i] equal to i[arr]?
The subscript operator is defined as *(arr + i), and addition is commutative, so *(i + arr) is identical. It is valid but should not be used in real code.
3. When does an array NOT decay to a pointer?
When it is the operand of sizeof, the operand of unary &, or a string literal used to initialise a character array. In those cases the array keeps its identity as the whole block.
4. Why does sizeof give a different answer inside a function?
Array parameters are adjusted to pointer parameters, so sizeof sees a pointer. Pass the number of elements separately.
5. What is the difference between &arr and &arr[0]?
They hold the same numeric address but have different types. &arr[0] is a pointer to one element, while &arr is a pointer to the whole array. Adding 1 to them moves by one element or by the whole array size respectively.
6. What is a one-past-the-end pointer?
It is the address just after the last element. You may form and compare it but must not dereference it. Loops use it as a termination marker.
7. How do you compute the number of elements in an array?
sizeof(arr) / sizeof(arr[0]), only where arr is a true array and not a function parameter.
8. What does pointer subtraction return?
The number of elements between two pointers into the same array, as a ptrdiff_t.
9. Why use const in a pointer parameter such as const uint8_t *buf?
It promises the function will not modify the data, allows passing read-only data such as tables in flash, and lets the compiler detect accidental writes.
10. How would you move a pointer by exactly one byte through a 32-bit array?
Cast it to a byte pointer first, for example (uint8_t *)arr + 1. Adding 1 to a uint32_t pointer would move four bytes.
11. Why is returning the address of a local array a bug?
The array lives on the function’s stack frame, which is gone after return. The pointer then dangles, and any use is undefined behaviour.
12. Why do embedded teams prefer stdint types for arrays shared with hardware?
The size of int and short varies by target. Fixed-width types guarantee the same element size and layout across compilers and processors.
Frequently Asked Questions
Can I subscript a pointer variable in C?
Yes. For any pointer p, p[i] means *(p + i). It works whether p points into an array, a malloc block or a static buffer.
What is the difference between an array name and a pointer variable?
An array name stands for the whole block and cannot be modified; a pointer variable is an object that stores an address and can be changed, incremented and reassigned.
Why can’t I do arr++ on an array?
An array name is not a modifiable lvalue. The compiler reports an error such as lvalue required as increment operand. Use a separate pointer to walk the array.
What is array decay?
It is the automatic conversion of an array name to a pointer to its first element when it appears in most expressions or is passed to a function.
Does passing an array to a function copy it?
No. Only the address of the first element is passed, so the function works on the original data, and it does not know the length.
Is this lecture useful for an embedded C interview?
Yes. Array versus pointer, sizeof behaviour and array decay appear in almost every embedded C interview. This free C tutorial covers them with runnable examples.
Keep Building Your Embedded C Skills
You have completed arrays and pointers in this group. Continue with the next topic in our free C programming course for embedded systems.
Need Help or More Information?
Questions about this free C programming course, embedded C training or career guidance? Get in touch.

2 Comments