C对数组的厌恶 [英] C's aversion to arrays

查看:95
本文介绍了C对数组的厌恶的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在C入门书籍中,通常声称指针或多或少是 数组.充其量,这不是一个极大的简化吗?

In introductory books on C it is often claimed that pointers more or less are arrays. Isn't this a vast simplification, at best?

在C中有一个 数组类型,它的行为可能与指针完全不同,例如:

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;
}

提供输出

sizeof(a) = 40 
sizeof(b) = 8 

或作为另一个示例a = b会给出编译错误(GCC:分配给具有数组类型的表达式").

or as another example a = b would give a compilation error (GCC: "assignment to expression with array type").

在指针和数组之间当然存在紧密关系,因为是的,数组变量 itself 的内容是第一个数组的内存地址元素,例如int a[10] = {777, 1, 2, 3, 4, 5, 6, 7, 8, 9}; printf("a = %ul\n", a);打印包含777的地址.

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;
}

输出:

Copying struct_huge_arrays took 0 sec, 345581 µs
memcpy took 0 sec, 345912 µs

但是您不能对数组本身执行此操作.对于数组x, y(大小相同,类型相同),表达式x = y是非法的.

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.

然后,函数无法返回数组.或者,如果将数组用作参数,则C将它们折叠成指针-不在乎是否明确给出了大小,因此以下程序给出输出sizeof(a) = 8 :

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;
}

这种对数组的厌恶背后有逻辑吗?为什么C中没有 true 健壮数组类型?如果有一个,会发生什么不好的事情?毕竟,如果数组隐藏在struct中,则数组确实的行为与Go,Rust等相​​同,即数组整个 内存中的块并将其传递将复制其内容,而不仅仅是第一个元素的内存地址.例如,在Go下面的程序中

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)
}

给出输出:

[-777 777]
[666 777]

推荐答案

这部分问题...

这种对数组的厌恶背后有逻辑吗?为什么C中没有真正的健壮数组类型?如果有一个会发生什么坏事?

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?

...并不是一个真正的代码问题,值得猜测,但是我认为一个简短的答案可能会有所帮助:创建C时,它的目标是RAM很少,CPU速度很慢的计算机(以千字节为单位)和兆赫兹).本意是将Assembler替换为系统编程语言,但没有引入其他现有高级语言所需的开销.出于同样的原因,由于C可以控制生成的程序,因此C仍然是微控制器的流行语言.

... is not really a code question and open to speculation, but I think a short answer might be beneficial: when C was created, it was targeted at machines with very little RAM and slow CPUs (measured in Kilo-Bytes and Megahertz, resp.). It was meant to replace Assembler as systems programming language, but without introducing the overhead that the other existing high-level languages required. For the same reasons, C is still a popular language for micro controllers, due to the control it gives you over the generated program.

引入健壮"的数组类型会对编译器和运行时带来潜在的性能和复杂性损失,而这并不是所有系统都无法承受的.同时,C为程序员提供了创建自己的健壮"数组类型并仅在合理使用它的情况下使用它们的功能.

Introducing a 'robust' array type would have had under-the-hood performance and complexity penalties for both the compiler and the runtime, which not all systems couldn't afford. At the same time, C offers the capabilities for the programmer to create their own 'robust' array type and use them only in those situations where its use was justified.

在这种情况下,我发现这篇文章很有趣: Dennis Ritchie: C语言(1993)

I found this article interesting in this context: Dennis Ritchie: Development of the C Language (1993)

这篇关于C对数组的厌恶的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆