理解作为参数传递的语法 *y[]

如何解决理解作为参数传递的语法 *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 是一个指向 double1 的 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 作为参数调用 foo2x 时,如

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]

  1. 更准确地说,每个 *y == *(y + 0) == y[0] *y[i] == *(y[i] + 0) == y[i][0] 都指向 y[i] 的 2 元素数组的第一个元素。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


依赖报错 idea导入项目后依赖报错,解决方案:https://blog.csdn.net/weixin_42420249/article/details/81191861 依赖版本报错:更换其他版本 无法下载依赖可参考:https://blog.csdn.net/weixin_42628809/a
错误1:代码生成器依赖和mybatis依赖冲突 启动项目时报错如下 2021-12-03 13:33:33.927 ERROR 7228 [ main] o.s.b.d.LoggingFailureAnalysisReporter : *************************** APPL
错误1:gradle项目控制台输出为乱码 # 解决方案:https://blog.csdn.net/weixin_43501566/article/details/112482302 # 在gradle-wrapper.properties 添加以下内容 org.gradle.jvmargs=-Df
错误还原:在查询的过程中,传入的workType为0时,该条件不起作用 &lt;select id=&quot;xxx&quot;&gt; SELECT di.id, di.name, di.work_type, di.updated... &lt;where&gt; &lt;if test=&qu
报错如下,gcc版本太低 ^ server.c:5346:31: 错误:‘struct redisServer’没有名为‘server_cpulist’的成员 redisSetCpuAffinity(server.server_cpulist); ^ server.c: 在函数‘hasActiveC
解决方案1 1、改项目中.idea/workspace.xml配置文件,增加dynamic.classpath参数 2、搜索PropertiesComponent,添加如下 &lt;property name=&quot;dynamic.classpath&quot; value=&quot;tru
删除根组件app.vue中的默认代码后报错:Module Error (from ./node_modules/eslint-loader/index.js): 解决方案:关闭ESlint代码检测,在项目根目录创建vue.config.js,在文件中添加 module.exports = { lin
查看spark默认的python版本 [root@master day27]# pyspark /home/software/spark-2.3.4-bin-hadoop2.7/conf/spark-env.sh: line 2: /usr/local/hadoop/bin/hadoop: No s
使用本地python环境可以成功执行 import pandas as pd import matplotlib.pyplot as plt # 设置字体 plt.rcParams[&#39;font.sans-serif&#39;] = [&#39;SimHei&#39;] # 能正确显示负号 p
错误1:Request method ‘DELETE‘ not supported 错误还原:controller层有一个接口,访问该接口时报错:Request method ‘DELETE‘ not supported 错误原因:没有接收到前端传入的参数,修改为如下 参考 错误2:cannot r
错误1:启动docker镜像时报错:Error response from daemon: driver failed programming external connectivity on endpoint quirky_allen 解决方法:重启docker -&gt; systemctl r
错误1:private field ‘xxx‘ is never assigned 按Altʾnter快捷键,选择第2项 参考:https://blog.csdn.net/shi_hong_fei_hei/article/details/88814070 错误2:启动时报错,不能找到主启动类 #
报错如下,通过源不能下载,最后警告pip需升级版本 Requirement already satisfied: pip in c:\users\ychen\appdata\local\programs\python\python310\lib\site-packages (22.0.4) Coll
错误1:maven打包报错 错误还原:使用maven打包项目时报错如下 [ERROR] Failed to execute goal org.apache.maven.plugins:maven-resources-plugin:3.2.0:resources (default-resources)
错误1:服务调用时报错 服务消费者模块assess通过openFeign调用服务提供者模块hires 如下为服务提供者模块hires的控制层接口 @RestController @RequestMapping(&quot;/hires&quot;) public class FeignControl
错误1:运行项目后报如下错误 解决方案 报错2:Failed to execute goal org.apache.maven.plugins:maven-compiler-plugin:3.8.1:compile (default-compile) on project sb 解决方案:在pom.
参考 错误原因 过滤器或拦截器在生效时,redisTemplate还没有注入 解决方案:在注入容器时就生效 @Component //项目运行时就注入Spring容器 public class RedisBean { @Resource private RedisTemplate&lt;String
使用vite构建项目报错 C:\Users\ychen\work&gt;npm init @vitejs/app @vitejs/create-app is deprecated, use npm init vite instead C:\Users\ychen\AppData\Local\npm-