How come that a pointer can freely be used as an array?
Unless it's the operand of a sizeof
or unary &
(address-of) operator, an array expression is converted to a pointer expression...
I thought pointers are more powerful and important in memory manipulation? Can somebody explain to me in which scenario do pointers become more important?
Arrays have different use cases than pointers; they're related, but can't be substituted for each other. Neither is more important than the other.
For example, as Mohamed Fouad mentioned in his answer, an array is a contiguous group of elements. We can't store a group of elements with a pointer, unless the pointer points into an array.
As another example where either can be used but pointers are generally more appropriate, consider how fscanf
works. When you want to read a sequence of decimal digit characters as an int
, you can write something like int destination; fscanf(source_file, "%d\n", &destination);
. The &
(address-of) operation produces a pointer to destination
, and the pointer allows fscanf
to write to destination
in a way that's visible once fscanf
returns.
You could also write this as int destination[1]; fscanf(source_file, "%d\n", destination);
, but then later on you'll be referring to destination[0]
, probably numerous times, rather than destination
... You should keep unnecessary clutter in code to a minimum, and thus the former approach (int destination; ...
) has become an idiomatic use for scanf
(rather than the array-based version) because it's cleaner.
There are more examples where pointers don't even point at objects, and so can't be stored in arrays to begin with. For example, let us consider bsearch
. bsearch
returns a void *
, and uses void *
in its arguments, along-side a function pointer. Neither of these are considered to be pointing at a specific type of object, and indeed the former could be made to point at any type object or no object at all. Hence, when bsearch
fails to locate an item in your array, it returns NULL
(a pointer to nothing), which is a usecase which arrays could not sanely replace.
Functions aren't objects or values, can't be stored within arrays and so arrays have no such related analogy to function pointers.
They print the same results.
Perhaps you meant to write char myString1[] = "This is my String";
. That's how we declare arrays. What you wrote, char * myString1 ...
denotes a pointer declaration.
The expression myString1
in myString1[j]
and myString1[j++]
is converted from an array expression to a pointer expression. Does that make sense?
The array[subscript]
operator is actually a pointer[subscript]
operator. It is the equivalent to *(array + subscript)
, but recall that the array
expression becomes a pointer expression
, so it might make more sense to write *(pointer + subscript)
.
To augment the function pointer mention above, the function(call)
operator is actually a pointer(call)
operation, which bares striking resemblance to the pointer[subscribt]
operation in the way the implicit conversions occur. It's observable nonetheless:
typedef int main_func(void); // declare a new type named main_func to point at
int main(void) {
int x[1];
int *y = x; // notice lack of ampersand, array-to-pointer conversion happens implicitly
main_func *m = main; // notice lack of ampersand, function-to-pointer conversion happens implicitly
return (*m)(); // main calls itself via pointer m (don't do this)
}
You might notice the equivalence, now: In your first example, you increment your pointer variable repeatedly, whilst in your second example you increment the subscript repeatedly. Aside from that, the operations are virtually identical.
If you're compiling with any modern-day optimising compiler (use -O3
), there shouldn't be any difference between the binaries. Try to avoid premature optimisation; it's often non-constructive. Write clear code, then use your profiler to determine where the most significant bottlenecks are.