Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/68.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
c编译器:数组作为函数参数_C_Compiler Construction - Fatal编程技术网

c编译器:数组作为函数参数

c编译器:数组作为函数参数,c,compiler-construction,C,Compiler Construction,我正在为类c语言编写编译器。目前,编译器支持本地范围内的数组。可以使用括号表示法--a[0]、a[1]、…访问数组的每个元素。为了支持此数据结构,使用符号表跟踪当前范围内的符号以及下一个可用内存空间的地址。为了演示,请考虑下面的代码: inta[5];int b 使用堆栈实现,并给定一个4字节对齐的内存:为了访问,例如元素a[1],我通过 元素=((索引+1)*4)+a.地址;//a、 地址是存储在符号表中的a的地址,在本例中索引为1。 因此,符号表不存储“a”的每个单独元素的地址,只存储符号的

我正在为
类c语言编写编译器。目前,编译器支持本地范围内的数组。可以使用括号表示法--
a[0]、a[1]、…
访问数组的每个元素。为了支持此数据结构,使用符号表跟踪当前范围内的符号以及下一个可用内存空间的地址。为了演示,请考虑下面的代码:

inta[5];int b

使用堆栈实现,并给定一个4字节对齐的内存:为了访问,例如元素
a[1]
,我通过

元素=((索引+1)*4)+a.地址;//a、 地址是存储在符号表中的a的地址,在本例中索引为1。

因此,符号表不存储“a”的每个单独元素的地址,只存储符号的地址以及每个符号的下一个内存地址

我假设c语言对本地范围内的数组使用基于堆栈的实现,就像我所做的那样。但是,C语言如何将本地数组作为参数传递给函数,如下所示

foo(int[]a){}


C编译器会使用堆或堆栈来传递前面的数组吗?

int[]a
不是有效的参数,您的意思肯定是
int a[]

在C语言中,不能将数组传递给函数,并且这种形式:

void foo(int a[]) { ... } 
相当于:

void foo(int *a) { ... }

C总是按值传递,通常指针
a
的副本存储在堆栈上。

int[]a
不是有效的参数,您的意思肯定是
int a[]

在C语言中,不能将数组传递给函数,并且这种形式:

void foo(int a[]) { ... } 
相当于:

void foo(int *a) { ... }
C总是按值传递,并且通常会在堆栈上存储指针
a
的副本。

(以下内容与C有关;如果您想为您的语言更改它,请务必执行。)

首先,要意识到不能将数组传递给函数。您只能向函数传递指针,因此当您看到

void f(int a[]) { ... }
它实际上和

void f(int* a) { ... }
既然我已经说过了,我可以说指针是在堆栈上传递的。

(下面是关于C的;如果您想为您的语言更改它,那么无论如何,请继续。)

首先,要意识到不能将数组传递给函数。您只能向函数传递指针,因此当您看到

void f(int a[]) { ... }
它实际上和

void f(int* a) { ... }

既然我已经说过了,我可以说指针是在堆栈上传递的。

在C中,数组作为函数参数传递时会衰减为指针
foo(int a[])
foo(int*a)
相同,只有指向第一个元素的指针“存活”到函数调用中。无法从函数调用中的指针恢复数组大小。

在C中,数组作为函数参数传递时会衰减为指针
foo(int a[])
foo(int*a)
相同,只有指向第一个元素的指针“存活”到函数调用中。无法从函数调用中的指针恢复数组大小。

C不会通过其内容,而是通过其地址将数组传递给函数

因此,函数的参数实际上只是一个
int*
,需要发送它的值是
a.Address


让我们想象一下你的假设语言。如果语言的语义规定数组需要通过其内容发送到函数,则需要使用堆栈,因为函数的参数位于堆栈上

请注意,这带来了另一个复杂性:

让我们考虑这个函数:

int f(int arg1, struct some_struct arg2, float arg3);
让我们调用这个函数中的某个指针,作为指向这个函数堆栈框架的指针。让我们称之为
bp
(基本指针)

因此在函数中,您将知道
arg1
位于地址
bp+8
(例如,
arg2位于地址
bp+12
arg3
位于地址
bp+36
(假设
sizeof(struct some_struct)
为20)

现在,如果按数组的内容发送数组,这个函数怎么样

int f(int arg1, int arg2[], float arg3);
arg1
arg2
在同一位置,但是
arg3
呢?您如何知道
arg3
的位置?为此,您需要知道
arg2
的大小

不过,有一个解决办法。您可以将数组的大小存储在其前4个字节中(如果您认为数组可能大于4GB,则可以存储8个字节)。然后,您可以通过数组的内容(包括其大小)安全地传递数组。在这种情况下,
a[i]
的地址将是
a.address+4(或8)+i*sizeof(*a)

您需要考虑以下几个权衡:

  • 保留阵列大小的额外内存。在C诞生时,这曾经是一个问题,但现在可能不再是问题了
  • 函数调用的速度要慢得多,因为需要复制数组
  • 更健壮的代码,因为绑定检查可以在运行时完成。但我个人不喜欢这样,执行速度会变慢,而且程序也不应该超出数组边界!不过,对于调试模式,它可能是一个非常有用的选项
  • 一个更好的
    sizeof
    操作,用于实际给出数组大小的数组。这对于只接收数组而没有其大小的函数很有用<例如,代码>strlen将是O(1)
  • 指向数组中间的指针将是无用的。考虑合并排序
  • 等等

C不是通过数组的内容,而是通过其地址将数组传递给函数

因此,函数的参数实际上只是一个
int*
,需要发送它的值是
a.Address


让我们想象一下你的低血压