如何解决理解作为参数传递的语法 *y[]
我正在尝试理解 C
代码,但偶然发现了以下函数定义:
int foo(int n,double *y[]);
我无法理解如何处理和解释 *y[]
。此语法在多个函数中使用,但处理方式不同。在本例中,foo1()
用作二维数组:
int foo1(int n,double *y[]){
double var0 = 0;
double var1 = 0;
for (i = 0; i < n; i++) {
var1 += y[i][1] ;
var0 += y[i][0] ;
}
// do stuff
return 0;
}
这里使用了相同的语法,但 *y[]
用作数组,但这里它们使用指针 *
表示法:
int foo2(int n,double *y[]){
double var0 = 0;
for (i = 0; i < n; i++) {
var0 += *y[i] ;
}
// do stuff
return 0;
}
您能否准确解释一下 *y[]
的含义以及为什么它可以如此灵活地用作函数参数?
解决方法
在函数声明中,数组类型的参数被转换为指针。所以参数 double *y[]
完全等同于 double **y
。
关于 *y[i]
与 y[i][0]
的使用,来自于数组索引运算符 []
等同于指针算术和解引用。
表达式 E1[E2]
完全等同于 *((E1)+(E2))
这意味着 y[i][0]
与 *(y[i]+0)
或 *y[i]
相同。
这个参数声明
double *y[]
声明一个大小未知的数组,元素类型为 double *
。也就是说,它是一个 double *
类型的指针数组。
好像是这个函数的第一个参数
int foo(int n,double *y[]);
即变量 n
指定数组中元素的数量。
这个表达
y[i]
给出数组的 i-th
元素。由于数组的元素是一个指针(例如指向具有两个元素的数组的第一个元素的指针),那么这些表达式
y[i][1]
y[i][0]
产生尖头元素。
至于这个表达
*y[i]
那么就等价于表达式
y[i][0]
为了更清楚,我将提供一个演示程序,其中使用 double * []
类型的数组代替 char * []
类型的数组。
给你。
#include <stdio.h>
void f( size_t n,char * s[] )
{
for ( size_t i = 0; i < n; i++ )
{
for ( size_t j = 0; s[i][j] != '\0'; j++ )
{
putchar( s[i][j] );
}
putchar( '\n' );
}
}
int main(void)
{
char * s[] =
{
"Hello","World"
};
f( sizeof( s ) / sizeof( *s ),s );
return 0;
}
程序输出为
Hello
World
,
基于 foo1
中的用法,y
是一个指向 double
1 的 2 元素数组的指针数组,如下所示:>
+---+ +---+
y: | | y[0] ------------------------------------------> | | y[0][0]
+---+ +---+ +---+
| | y[1] -------------------------> | | y[1][0] | | y[0][1]
+---+ +---+ +---+
... | | y[1][1]
+---+ +---+ +---+
| | y[n-1] ----> | | y[n-1][0]
+---+ +---+
| | y[n-1][1]
+---+
并且可能声明为
double *x[N]; // or some other name,just picking x for convenience
并使用现有数组的地址进行初始化:
double a[2],b[2],c[2],...;
double *x[N] = { a,b,c,... };
或者内存是动态分配的:
for ( size_t i = 0; i < N; i++ )
x[i] = malloc( sizeof *x[i] * 2 );
在调用函数中。
除非它是 sizeof
或一元 &
运算符的操作数,或者是用于在声明中初始化字符类型数组的字符串文字,否则为 表达式 “T
的 N 元素数组”类型将被转换或“衰减”为“指向 T
的指针”类型的表达式,并且表达式的值将是第一个的地址数组的元素。
当您使用 foo1
作为参数调用 foo2
或 x
时,如
foo1( N,x );
foo2( N,x );
表达式 x
从类型“指向 double
的指针的 N 元素数组”类型转换为类型“指向指向 double
的指针的指针”,并且第一个元素 (&x[0]
) 的地址是实际传递给函数的地址。
在函数参数声明中,T a[N]
或 T a[]
形式的任何参数都“调整”为 T *a
- IOW a
始终被视为指向 { {1}},而不是数组。
因此即使 T
在函数参数列表中被声明为 y
,它实际上被视为 double *y[]
。
数组下标操作double **y
被定义为a[i]
- 给定一个起始地址,从该地址偏移*(a + i)
个元素(不是字节!)并取消引用结果。所以 i
等价于 y[i]
而 *(y + i)
等价于 y[i][j]
。这也意味着表达式 *(*(y + i) + j)
等价于 *y
,而 y[0]
等价于 *y[i]
。
y[i][0]
- 更准确地说,每个
*y == *(y + 0) == y[0] *y[i] == *(y[i] + 0) == y[i][0]
都指向y[i]
的 2 元素数组的第一个元素。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。