In introductory books on C it is often claimed that pointers more or less are arrays. Isn't this a vast simplification, at best?
There is an array type in C and it can behave completely different from pointers, for example:
#include <stdio.h>
int main(int argc, char *argv[]){
int a[10] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
int *b = a;
printf("sizeof(a) = %lu\n", sizeof(a));
printf("sizeof(b) = %lu\n", sizeof(b));
return 0;
}
gives the output
sizeof(a) = 40
sizeof(b) = 8
or as another example a = b
would give a compilation error (GCC: "assignment to expression with array type").
Of course there is a close relationship between pointers and arrays, in the sense that yes, the content of an array variable itself is the memory address of the first array element, e.g. int a[10] = {777, 1, 2, 3, 4, 5, 6, 7, 8, 9}; printf("a = %ul\n", a);
prints the address containing the 777.
Now, on the one hand, if you 'hide' arrays in structs, you can easily copy large amounts of data (arrays if you ignore the wrapping struct) just by using the =
operator (and that's even fast, too):
#include <sys/time.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define ARRAY_LENGTH 100000000
typedef struct {int arr[ARRAY_LENGTH];} struct_huge_array;
int main(int argc, char *argv[]){
struct_huge_array *a = malloc(sizeof(struct_huge_array));
struct_huge_array *b = malloc(sizeof(struct_huge_array));
int *x = malloc(sizeof(int)*ARRAY_LENGTH);
int *y = malloc(sizeof(int)*ARRAY_LENGTH);
struct timeval start, end, diff;
gettimeofday(&start, NULL);
*a = *b;
gettimeofday(&end, NULL);
timersub(&end, &start, &diff);
printf("Copying struct_huge_arrays took %d sec, %d µs\n", diff.tv_sec, diff.tv_usec);
gettimeofday(&start, NULL);
memcpy(x, y, ARRAY_LENGTH*sizeof(int));
gettimeofday(&end, NULL);
timersub(&end, &start, &diff);
printf("memcpy took %d sec, %d µs\n", diff.tv_sec, diff.tv_usec);
return 0;
}
Output:
Copying struct_huge_arrays took 0 sec, 345581 µs
memcpy took 0 sec, 345912 µs
But you cannot do this with arrays itself. For arrays x, y
(of the same size and of the same type) the expression x = y
is illegal.
Then, functions can't return arrays. Or if arrays are used as arguments, C collapses them into pointers -- it does not care if the size is explicitly given, so the following program gives the output sizeof(a) = 8
:
#include <stdio.h>
void f(int p[10]){
printf("sizeof(a) = %d\n", sizeof(p));
}
int main(int argc, char *argv[]){
int a[10] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
f(a);
return 0;
}
Is there any logic behind this aversion to arrays? Why isn't there a true robust array type in C? What bad would happen if there was one? After all, if an array is hidden in a struct
the array does behave as in Go, Rust, ..., i.e. the array is the whole chunk in memory and passing it around will copy its content, not just the memory address of the first element. For example like in Go the following program
package main
import "fmt"
func main() {
a := [2]int{-777, 777}
var b [2]int
b = a
b[0] = 666
fmt.Println(a)
fmt.Println(b)
}
gives the output:
[-777 777]
[666 777]
%lu
, you should use%zu
forsize_t
arguments. – Manhoura
'contains' the string itself,p
'contains' the address of the string. The same syntax works for both examples, but the underlying assembly is different. – Complementarya
decays to a pointer if evaluated. Arrays cannot be passed in C, so what does printf receive? A pointer. – Complementary