鱼C论坛

 找回密码
 立即注册
查看: 2335|回复: 19

[已解决]结构体指针做形参,实参可用结构体数组访问??

[复制链接]
发表于 2018-8-22 23:40:12 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能^_^

您需要 登录 才可以下载或查看,没有账号?立即注册

x
本帖最后由 我是大甲鱼 于 2018-8-22 23:42 编辑
  1. #include <stdio.h>
  2. typedef struct ex
  3. {
  4.         int a;
  5.         int b;
  6. }ex,*p_ex;

  7. void fun(p_ex temp);
  8. ex msg;
  9. int main()
  10. {       
  11.         msg.a=2;
  12.         printf("befor msg.a=%d\n",msg.a);  //msg.a的值
  13.         printf("&(msg.a)=%p\n",&(msg.a));  //msg.a的地址

  14.         fun(&msg);  //经过函数处理  msg.a的值被函数中的temp[0].a=3;改变

  15.         printf("after msg.a=%d\n",msg.a); // 为什么msg.a会被temp[0].a改变呢?可能是他们的地址是一样的

  16.         //可是为什么temp[1].a temp[2].a  可以被赋值,又应该怎么用temp来访问??
  17.         putchar('\n');
  18.         return 0;
  19. }
  20. void fun(p_ex temp)
  21. {
  22.         printf("-------------对应值---------------\n");
  23.         temp->a=1;
  24.         printf("temp->a=%d\n",temp->a);

  25.         temp[0].a=3;
  26.         printf("temp[0].a=%d\n",temp[0].a);

  27.         temp[1].a=4;
  28.         printf("temp[1].a=%d\n",temp[1].a);

  29.         temp[2].a=5;
  30.         printf("temp[2].a=%d\n",temp[2].a);

  31.         temp[0].b=6;
  32.         printf("temp[0].b=%d\n",temp[0].b);

  33.         temp[1].b=7;
  34.         printf("temp[1].b=%d\n",temp[1].b);

  35.         temp[2].b=8;
  36.         printf("temp[2].b=%d\n",temp[2].b);
  37.         printf("-------------对应地址---------------\n");

  38.         printf("&(temp->a)=%p\n",&(temp->a));
  39.         printf("&(temp->b)=%p\n",&(temp->b));
  40.         printf("&(temp[0].a)=%p\n",&(temp[0].a));
  41.         printf("&(temp[0].b)=%p\n",&(temp[0].b));
  42.         printf("&(temp[1].a)=%p\n",&(temp[1].a));
  43.         printf("&(temp[1].b)=%p\n",&(temp[1].b));
  44.         printf("&(temp[2].a)=%p\n",&(temp[2].a));
  45.         printf("&(temp[2].b)=%p\n\n",&(temp[2].b));
  46. }
复制代码



运算结果:
befor msg.a=2
&(msg.a)=00427E60
-------------对应值---------------
temp->a=1
temp[0].a=3
temp[1].a=4
temp[2].a=5
temp[0].b=6
temp[1].b=7
temp[2].b=8
-------------对应地址---------------
&(temp->a)=00427E60
&(temp->b)=00427E64
&(temp[0].a)=00427E60
&(temp[0].b)=00427E64
&(temp[1].a)=00427E68
&(temp[1].b)=00427E6C
&(temp[2].a)=00427E70
&(temp[2].b)=00427E74

after msg.a=3

Press any key to continue
最佳答案
2018-8-23 11:21:02
claws0n 发表于 2018-8-23 10:53
嵌入式,还没学过
呼叫大神 @无符号整形
程序透过结构体指针改变结构体内容,但 ...

总算明白你要问什么了。
temp[0]就相当于*(temp+0),相当于temp
temp[1]就相当于*(temp+1),相当与temp的下一个地址
以此类推
小甲鱼最新课程 -> https://ilovefishc.com
回复

使用道具 举报

 楼主| 发表于 2018-8-22 23:41:28 | 显示全部楼层
为什么不能本地上传图片 ??
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2018-8-22 23:46:25 | 显示全部楼层
我是大甲鱼 发表于 2018-8-22 23:41
为什么不能本地上传图片 ??

进入高级模式
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2018-8-23 00:12:23 | 显示全部楼层

不管他什么模式了,大佬知道这是我为什么吗
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2018-8-23 00:20:14 | 显示全部楼层
当然可以换 *p_ex 与 ex 是属于同一个结构体
没错,因为地址一样,所以被改变了
第二个情况没有遇过,不过这样写是很危险的。结构体本身就可大可小,也许是因为这样,所以编译器让你自由扩充结构体的空间。
可以赋值就可以直接访问了 int a  = 3; printf("%d", a) == 3
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2018-8-23 00:40:06 | 显示全部楼层
claws0n 发表于 2018-8-23 00:20
当然可以换 *p_ex 与 ex 是属于同一个结构体
没错,因为地址一样,所以被改变了
第二个情况没有遇过,不 ...

(temp+0)->a==temp[0].a    (temp+1)->a==temp[1].a     (temp+2)->a==temp[2].a
(temp+0)->a==temp[0].a的地址相同可以理解为什么可以赋值。感觉传进来的结构体指针变成了一个结构体数组。我是在学嵌入式的时候看到这种写法,看了好久没看懂。百度也不好描述。
  1. typedef struct i2c_msg {
  2.         unsigned int addr;  /* 7bits   地址*/   
  3.         int flags;  /* 0 - write, 1 - read */
  4.         int len;                //数据长度
  5.         int cnt_transferred;
  6.         int err;
  7.         unsigned char *buf;                //存数据
  8. }i2c_msg, *p_i2c_msg;

  9. int s3c2440_master_xfer(p_i2c_msg msgs, int num)
  10. {
  11.         int i;
  12.         int err;
  13.        
  14.         for (i = 0; i < num; i++)       
  15.         {
  16.                 if (msgs[i].flags == 0)/* write */
  17.                         err = do_master_tx(&msgs[i]);
  18.                 else
  19.                         err = do_master_rx(&msgs[i]);
  20.                 if (err)
  21.                         return err;
  22.         }
  23.         return 0;
  24. }
复制代码


老铁早些睡觉吧
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2018-8-23 10:53:31 | 显示全部楼层
我是大甲鱼 发表于 2018-8-23 00:40
(temp+0)->a==temp[0].a    (temp+1)->a==temp[1].a     (temp+2)->a==temp[2].a
(temp+0)->a==temp[0] ...

嵌入式,还没学过
呼叫大神 @无符号整形
程序透过结构体指针改变结构体内容,但是代码 24 - 46 对结构体扩充
我的回答: 5 楼

点评

ok  发表于 2018-8-23 11:09
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2018-8-23 11:09:23 | 显示全部楼层
本帖最后由 无符号整形 于 2018-8-23 11:21 编辑

见9楼
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2018-8-23 11:21:02 | 显示全部楼层    本楼为最佳答案   
claws0n 发表于 2018-8-23 10:53
嵌入式,还没学过
呼叫大神 @无符号整形
程序透过结构体指针改变结构体内容,但 ...

总算明白你要问什么了。
temp[0]就相当于*(temp+0),相当于temp
temp[1]就相当于*(temp+1),相当与temp的下一个地址
以此类推

点评

有句话:C语言根本没有实际上的数组,只有实际上的指针。 数组即指针  发表于 2018-8-23 11:21
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2018-8-23 11:29:55 | 显示全部楼层
无符号整形 发表于 2018-8-23 11:21
总算明白你要问什么了。
temp[0]就相当于*(temp+0),相当于temp
temp[1]就相当于*(temp+1),相当与temp ...

对这个线性扩充我知道,所以
第二个情况没有遇过,不过这样写是很危险的。结构体本身就可大可小,也许是因为这样,所以编译器让你自由扩充结构体的空间。

但是没有相对应的结构/变量,很危险,算野指针?
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2018-8-23 11:33:43 | 显示全部楼层
claws0n 发表于 2018-8-23 11:29
对这个线性扩充我知道,所以

但是没有相对应的结构/变量,很危险,算野指针?

小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2018-8-23 11:36:50 | 显示全部楼层
claws0n 发表于 2018-8-23 11:29
对这个线性扩充我知道,所以

但是没有相对应的结构/变量,很危险,算野指针?

那个地方如果是栈的话可能会超过栈顶,有可能超过栈底。假如是内存的话可能会访问到别的进程的地址空间,甚至有可能访问到系统内核保留空间(0x70000000~0xFFFFFFFF),这样会引发0xC000005错误,就是访问违规,会导致程序“停止工作”。(其实你可以通过try来捕获这些异常但是扯太远了)
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2018-8-23 11:42:29 | 显示全部楼层
无符号整形 发表于 2018-8-23 11:36
那个地方如果是栈的话可能会超过栈顶,有可能超过栈底。假如是内存的话可能会访问到别的进程的地址空间, ...

甚至有可能访问到系统内核保留空间(0x70000000~0xFFFFFFFF),这样会引发0xC000005错误,就是访问违规,会导致程序“停止工作”。可以理解,数字认不得~
(其实你可以通过try来捕获这些异常但是扯太远了)
初学者
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2018-8-23 11:48:37 | 显示全部楼层
啦啦啦啦啦啦

评分

参与人数 1荣誉 -2 鱼币 -2 收起 理由
claws0n -2 -2 请不要无意义灌水!

查看全部评分

小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2018-8-23 13:08:54 | 显示全部楼层
无符号整形 发表于 2018-8-23 11:21
总算明白你要问什么了。
temp[0]就相当于*(temp+0),相当于temp
temp[1]就相当于*(temp+1),相当与temp ...

1.当传入的是一个结构体地址的时候可以用temp->a访问  也能用temp[0].a访问,但是超出后可能会发生一些严重的错误。
2.当传入的是一个结构体数组的地址,在这个数组元素个数范围内都可以用temp[i].a来访问


这样理解对么?
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2018-8-23 14:14:49 | 显示全部楼层
我是大甲鱼 发表于 2018-8-23 13:08
1.当传入的是一个结构体地址的时候可以用temp->a访问  也能用temp[0].a访问,但是超出后可能会发生一些严 ...

对的
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2018-8-23 14:19:48 | 显示全部楼层
本帖最后由 无符号整形 于 2018-8-23 14:21 编辑
claws0n 发表于 2018-8-23 11:42
甚至有可能访问到系统内核保留空间(0x70000000~0xFFFFFFFF),这样会引发0xC000005错误,就是访问违规, ...

  1. try//尝试执行的语句部分
  2. {
  3.         ...
  4. }
  5. catch(xxx xx)//假如出现了异常,系统会抛出一个异常结构,这个结构是不确定的,你需要根据上面的可能会出现的错误来决定
  6. {
  7.         ...
  8. }
复制代码

PS:什么?你是初学者??我不信~别那么谦虚嘛~

点评

是的,我是初学者,私聊~  发表于 2018-8-23 14:34
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Archiver|鱼C工作室 ( 粤ICP备18085999号-1 | 粤公网安备 44051102000585号)

GMT+8, 2025-6-10 03:09

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表