Closed 。这个问题需要细节或清晰度 。目前不接受答案。
在 C 的入门书籍中,经常声称指针或多或少are 数组。这充其量不是一个巨大的简化吗?
There is C 中的数组类型,它的行为与指针完全不同,例如:
#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;
}
给出输出
sizeof(a) = 40
sizeof(b) = 8
或者作为另一个例子a = b
会给出编译错误(GCC:“分配给具有数组类型的表达式”)。
当然有一个亲密的关系 介于指针和数组之间,从某种意义上说,是的,数组变量的内容itself 是第一个数组元素的内存地址,例如int a[10] = {777, 1, 2, 3, 4, 5, 6, 7, 8, 9}; printf("a = %ul\n", a);
打印包含 777 的地址。
现在,一方面,如果您在结构中“隐藏”数组,则只需使用以下命令即可轻松复制大量数据(如果忽略包装结构,则为数组)=
运算符(而且速度也很快):
#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
但你不能用数组本身来做到这一点。对于数组x, y
(相同大小和相同类型)表达式x = y
是非法的。
然后,函数不能返回数组。或者如果使用数组作为参数,C崩溃 它们变成指针——它不关心大小是否是明确给出, 所以下面的程序给出了输出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;
}
这种对数组的厌恶背后有什么逻辑吗?为什么没有一个true C 中的健壮数组类型?如果有的话,会发生什么糟糕的事情呢?毕竟,如果一个数组隐藏在struct
数组does 行为与 Go、Rust 等中一样,即数组is the whole 内存中的块并将其传递将复制其内容,而不仅仅是第一个元素的内存地址。例如,在 Go 中,下面的程序
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)
}
给出输出:
[-777 777]
[666 777]