If you write a simple loop, the array and pointer forms are usually compiled into the same machine code.
There are differences in the especially non-constant loop exit conditions, but this only matters if you are trying to optimize the loop for a particular compiler and architecture.
So, what about an example of a real world that builds on both?
These types implement a dynamically determined double-precision floating-point matrix with a separate data store with counting:
struct owner {
long refcount;
size_t size;
double data[];
};
struct matrix {
long rows;
long cols;
long rowstep;
long colstep;
double *origin;
struct owner *owner;
};
, , struct matrix. struct owner C99. , , "" . : , , ( ).
, , , , . , , . , refcount . , , "" , (), .
; .
struct matrix m, r, c, 0 <= r < m.rows 0 <= c < m.cols, m.origin[r*m.rowstep + c*m.colstep].
, m.rows m.cols m.rowstep m.colstep. , , - , ( ).
( , origin , 0, 0, rowstep colstep . "" , ..)
C99 - , , data . ( ). , data , , , , .
- , ( , ), - , , , , . , ,
#define MATRIXELEM(m, r, c) ((m).origin[(r)*(m).rowstep + (c)*(m).colstep])
, , , m. ( , MATRIXELEM(m++,0,0) m .) m struct matrix, . , ,
struct matrix m1, m2;
MATRIXELEM(m1, 0, 0) = MATRIXELEM(m2, 0, 0);
"" , , i + 4*j , ((i + 4*j)*m.rowstep, i + 4*j*m.rowstep). "". , , "" , , . ( , " " , , , "" , .)
, , : , , , . "Foo"[1] 'o', *("Foo"+1) . ( , 1["foo"], C .)
, , ; , , - , , , , , . , C, .