Programming Language & Its Applications — Pointers, Structure and Data Files in C, NEC licence examination syllabus (Nepal Engineering Council).
a[i] is defined as *(a+i). But an array is not a pointer — and sizeof proves it.
C blurs arrays and pointers deliberately: the subscript operator is defined in terms of pointer arithmetic, and an array name in most expressions decays to a pointer to its first element. But they are not the same type. The array name is not a modifiable object, and sizeof reports different things. Knowing exactly where the equivalence holds and where it breaks is the point of this topic.
char *argv[] in int main(int argc, char *argv[]) is exactly the array-of-pointers from this topic — every command-line argument you have ever typed arrives that way. And the dynamic-array section at the end is how std::vector, Python's list and Java's ArrayList all work internally: malloc, fill, realloc to double the capacity when full. Search "why does vector double its capacity" — the answer is amortised analysis and it is a beautiful piece of reasoning.#include <stdio.h>
int main(void) {
int a[5] = {10,20,30,40,50};
int *p = a; /* decay */
/* four spellings, one element */
printf("%d %d %d %d\n", a[2], *(a+2), p[2], *(p+2));
printf("sizeof a = %zu sizeof p = %zu\n",
sizeof a, sizeof p);
/* walking with an index vs walking the pointer */
for (int i = 0; i < 5; i++) printf("%d ", a[i]);
printf("\n");
for (int *q = a; q < a + 5; q++) printf("%d ", *q);
printf("\n");
/* a = p; <-- ERROR: assignment to expression
with array type */
return 0;
}
Output:
30 30 30 30
sizeof a = 20 sizeof p = 8
10 20 30 40 50
10 20 30 40 50
#include <stdio.h>
int main(void) {
char s[] = "NEPAL";
/* 1. index */
for (int i = 0; s[i]; i++) putchar(s[i]);
putchar('\n');
/* 2. pointer walk - the idiomatic C form */
for (char *p = s; *p; p++) putchar(*p);
putchar('\n');
/* 3. pointer arithmetic on the array name */
for (int i = 0; *(s+i); i++) putchar(*(s+i));
putchar('\n');
/* count length by pointer subtraction */
char *end = s;
while (*end) end++;
printf("length = %ld\n", end - s);
return 0;
}
Output:
NEPAL
NEPAL
NEPAL
length = 5
The for (char *p = s; *p; p++) form is how experienced C programmers write string loops — the loop condition *p is false exactly when it reaches the null terminator.
#include <stdio.h>
int main(void) {
int a=1, b=2, c=3;
/* array of pointers */
int *arr[3] = {&a, &b, &c};
for (int i = 0; i < 3; i++) printf("%d ", *arr[i]);
printf(" sizeof arr = %zu\n", sizeof arr);
/* pointer to an array of 5 ints */
int m[5] = {10,20,30,40,50};
int (*ptr)[5] = &m;
printf("(*ptr)[2] = %d sizeof ptr = %zu\n",
(*ptr)[2], sizeof ptr);
/* the classic use: array of strings */
const char *names[] = {"Ram", "Sita", "Hari"};
for (int i = 0; i < 3; i++) printf("%s ", names[i]);
printf("\n");
return 0;
}
Output:
1 2 3 sizeof arr = 24
(*ptr)[2] = 30 sizeof ptr = 8
Ram Sita Hari
#include <stdio.h>
int main(void) {
int m[3][4] = {{1,2,3,4},{5,6,7,8},{9,10,11,12}};
/* m decays to int(*)[4] - pointer to a ROW of 4 */
printf("m = %p\n", (void*)m);
printf("m+1 = %p (+16 bytes = one ROW)\n",
(void*)(m+1));
printf("m[0] = %p (decays to int*)\n", (void*)m[0]);
printf("m[0]+1 = %p (+4 bytes = one INT)\n",
(void*)(m[0]+1));
/* five equivalent ways to reach m[1][2] = 7 */
printf("%d %d %d %d %d\n",
m[1][2], *(m[1]+2), *(*(m+1)+2),
*(&m[0][0] + 1*4 + 2), ((int*)m)[1*4+2]);
return 0;
}
Output:
m = 0x7ffd8a1c2430
m+1 = 0x7ffd8a1c2440 (+16 bytes = one ROW)
m[0] = 0x7ffd8a1c2430 (decays to int*)
m[0]+1 = 0x7ffd8a1c2434 (+4 bytes = one INT)
7 7 7 7 7
void f(int m[][4], int rows) — the column count is part of the type, needed to compute i*COLS + j. The row count can be omitted because it never enters the address formula. Getting this backwards is a common exam error.
#include <stdio.h>
#include <stdlib.h>
int main(void) {
int n = 5;
/* 1-D dynamic array */
int *a = malloc(n * sizeof *a);
if (!a) return 1; /* ALWAYS check */
for (int i = 0; i < n; i++) a[i] = (i+1)*(i+1);
for (int i = 0; i < n; i++) printf("%d ", a[i]);
printf("\n");
/* grow it */
int *tmp = realloc(a, 8 * sizeof *a);
if (tmp) { a = tmp; n = 8; }
for (int i = 5; i < 8; i++) a[i] = 100 + i;
for (int i = 0; i < n; i++) printf("%d ", a[i]);
printf("\n");
free(a); /* every malloc needs exactly one free */
/* 2-D as an array of row pointers */
int rows = 3, cols = 4;
int **m = malloc(rows * sizeof *m);
for (int i = 0; i < rows; i++)
m[i] = malloc(cols * sizeof **m);
for (int i = 0; i < rows; i++)
for (int j = 0; j < cols; j++) m[i][j] = i*cols + j;
printf("m[2][3] = %d\n", m[2][3]);
for (int i = 0; i < rows; i++) free(m[i]); /* rows */
free(m); /* then the array */
return 0;
}
Output:
1 4 9 16 25
1 4 9 16 25 105 106 107
m[2][3] = 11
sizeof, and array names not being assignable). The int *arr[5] vs int (*ptr)[5] distinction is a standard question — use the right-left reading rule. For 2-D, be ready to explain why m+1 advances a whole row while m[0]+1 advances one int, and why the column count must appear in a function parameter.Create a free account to tick topics off, take notes as you read, watch the video lessons and get a day-by-day study plan built around your exam date.
Loading…