OpenEdv-开源电子网

 找回密码
 立即注册
正点原子全套STM32/Linux/FPGA开发资料,上千讲STM32视频教程免费下载...
查看: 3820|回复: 12

请教2个C的问题!

[复制链接]

9

主题

55

帖子

0

精华

初级会员

Rank: 2

积分
182
金钱
182
注册时间
2018-3-28
在线时间
30 小时
发表于 2018-9-23 11:38:48 | 显示全部楼层 |阅读模式
1金钱
本帖最后由 fight281 于 2018-9-23 11:41 编辑

问题1:u8 GetUartlen(u8 rcvd_len, u8 len){
    if (len > rcvd_len) //读取长度大于接收到的数据长度时,
    {
        len = rcvd_len; //读取长度设置为实际接收到的数据长度
    }
    rcvd_len = 0;  //清零接收计数器   
    return len;  //返回实际读取长度
}

实际带入实参rcvd_len后,发现并没有清零,即 rcvd_len = 0;  //清零接收计数器  没有起效,如果说函数带入的只是这个变量的常量,那么 rcvd_len = 0这一句函数是如何执行的?

问题2:
比如我创建了一个结构体:
struct student
{
   
char name;
   
char se[size=+0]x;
   
int age;
   
float score;
}stu1
;


能不能这样在定义一个共同体:
union A
{
   
char copyname;
    stu1.name
;
}s
;

如果我想让结构体中每一个成员都对应一个共同体,应该怎么做的?打散结构体的话又不好管理。








最佳答案

查看完整内容[请看2#楼]

问题一,参考一下函数参数的“按地址传递”和“按值传递”的区别。楼主所写的方式是按值传递,函数参数相当于新开了一个局部变量,进入函数的时候这个局部变量只是简单地按值把实参的值拷贝过来了,在函数的执行过程中,的确rcvd_len被清零了;但是清零的仅仅是这个局部变量,而不是实参的那个rcvd_len。楼主改写成这个样子即可: [mw_shl_code=c,true]u8 GetUartlen(u8* rcvd_len, u8 len){ if (len > *rcvd_len) //读取长 ...
正点原子逻辑分析仪DL16劲爆上市
回复

使用道具 举报

2

主题

756

帖子

0

精华

论坛元老

Rank: 8Rank: 8

积分
4163
金钱
4163
注册时间
2017-10-24
在线时间
251 小时
发表于 2018-9-23 11:38:49 | 显示全部楼层
问题一,参考一下函数参数的“按地址传递”和“按值传递”的区别。楼主所写的方式是按值传递,函数参数相当于新开了一个局部变量,进入函数的时候这个局部变量只是简单地按值把实参的值拷贝过来了,在函数的执行过程中,的确rcvd_len被清零了;但是清零的仅仅是这个局部变量,而不是实参的那个rcvd_len。楼主改写成这个样子即可:
[mw_shl_code=c,true]u8 GetUartlen(u8* rcvd_len, u8 len){
    if (len > *rcvd_len) //读取长度大于接收到的数据长度时,
    {
        len = *rcvd_len; //读取长度设置为实际接收到的数据长度
    }
    *rcvd_len = 0;  //清零接收计数器   
    return len;  //返回实际读取长度
}[/mw_shl_code]

在调用的时候,需要顺带修改一下函数实参的写的形式:

[mw_shl_code=c,true]u8 tmp;                //假设这个是rcvd_len这个函数形参所对应的实参
u8 len;
len=GetUartlen(&tmp,len);        //对应的函数实参要取地址[/mw_shl_code]

这部分的理解,楼主还是要好好学习一下函数中的参数,按值和按地址的区别。

问题二,这个方法是不能的,C语言中不允许直接对结构体“类型”的成员进行操作,直接这样写的话,编译器反而可能会认为stu1是变量。比较合适的做法是使用一个指针,当某个stu1对象呗声明后,让这个指针指向这个stu1的相关成员变量。这个时候就没有必要使用共用体,再声明一个结构体类型是比较方便的。详细的做法可以参考3#

十六进制带我飞。
回复

使用道具 举报

3

主题

1907

帖子

0

精华

论坛元老

Rank: 8Rank: 8

积分
4106
金钱
4106
注册时间
2018-8-14
在线时间
696 小时
发表于 2018-9-23 12:34:23 | 显示全部楼层
rcvd_len是函数的参数, 也是局部变量, 在没有使用被赋值的局部变量, 之前的赋值是会被优化掉的, 所以在编译后根压就没有rcvd_len=0
回复

使用道具 举报

3

主题

1907

帖子

0

精华

论坛元老

Rank: 8Rank: 8

积分
4106
金钱
4106
注册时间
2018-8-14
在线时间
696 小时
发表于 2018-9-23 12:40:56 | 显示全部楼层
union A
{
    char copyname;
    stu1.name;
}s;
这是不可以的, 如果说你想把s的成员关连到另外的结构体, 就用指针, 比如


union A
{
    char copyname;
    struct student*  student_struct_pointer;
}s;

s.student_struct_pointer = (struct student*)stu1;
然后
s.student_struct_pointer->name  的效果跟 stu1.name 是一样的
你要的是不是这种关联?
回复

使用道具 举报

9

主题

165

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
251
金钱
251
注册时间
2018-4-6
在线时间
31 小时
发表于 2018-9-24 08:31:42 | 显示全部楼层
问题一,把函数名改成u8 GetUartlen(u8 *rcvd_len, u8 len),就能改变rcvd_len的值了
回复

使用道具 举报

29

主题

338

帖子

1

精华

金牌会员

Rank: 6Rank: 6

积分
1181
金钱
1181
注册时间
2018-4-13
在线时间
170 小时
发表于 2018-9-24 10:57:46 | 显示全部楼层
只看了问题一,你是想调用函数后一起修改实际参数吗?比如把rcvd_len的实参清零复位?那就传入指针才能实现了。
对于问题二,联合的目的在于节省空间,你的目的是什么呢?是想要一个结构成员的别名吗?
回复

使用道具 举报

9

主题

55

帖子

0

精华

初级会员

Rank: 2

积分
182
金钱
182
注册时间
2018-3-28
在线时间
30 小时
 楼主| 发表于 2018-9-25 13:44:49 | 显示全部楼层
edmund1234 发表于 2018-9-23 12:40
union A
{
    char copyname;

感谢您的回答。
不好意思 这部分没有看懂。我的理解是copyname和student_struct_pointer这个结构体指针共用一个地址。结构体指针指向的是结构体的首地址,然后s.student_struct_pointer = (struct student*)stu1; 是指 共同体内student_struct_pointer的值 也就是地址对应于结构体stu1的的首地址。然后s.student_struct_pointer->name没看懂,name不是s的成员也可以这样用吗?而且name也不是结构体指针的内部成员啊。
请指教!
回复

使用道具 举报

9

主题

55

帖子

0

精华

初级会员

Rank: 2

积分
182
金钱
182
注册时间
2018-3-28
在线时间
30 小时
 楼主| 发表于 2018-9-25 13:46:04 | 显示全部楼层
DreamWaterPro 发表于 2018-9-23 11:38
问题一,参考一下函数参数的“按地址传递”和“按值传递”的区别。楼主所写的方式是按值传递,函数参数相当 ...

比较合适的做法是使用一个指针,当某个stu1对象呗声明后,让这个指针指向这个stu1的相关成员变量。这个时候就没有必要使用共用体,再声明一个结构体类型是比较方便的。详细的做法可以参考3#

这个能详细说明一下吗?感谢!4#的我没有看明白。
回复

使用道具 举报

9

主题

55

帖子

0

精华

初级会员

Rank: 2

积分
182
金钱
182
注册时间
2018-3-28
在线时间
30 小时
 楼主| 发表于 2018-9-25 13:48:15 | 显示全部楼层
本帖最后由 fight281 于 2018-9-25 13:54 编辑
DreamWaterPro 发表于 2018-9-23 11:38
问题一,参考一下函数参数的“按地址传递”和“按值传递”的区别。楼主所写的方式是按值传递,函数参数相当 ...

我只是想让变量a 和b 拥有共同的内存地址, 而a 是结构体内的成员,我不想打散结构体,4#的确实没看懂,水平有限。按我浅显的理解。就是:

struct student
{
   
u8 mem1;   u8 mem2;
  u8 mem3;
  u16 mem4;
}stu1
;

u8 temp[5];
temp=&stu1.mem1;
temp+1=&stu1.mem2;
temp+2=&stu1.mem3;
temp+3=(U8*)&stu1.mem4;
temp+4=(U8*)&stu1.mem4+1;

这样对吗?那这样的话编译器之前给temp分配的地址都去哪了呢?



回复

使用道具 举报

2

主题

756

帖子

0

精华

论坛元老

Rank: 8Rank: 8

积分
4163
金钱
4163
注册时间
2017-10-24
在线时间
251 小时
发表于 2018-9-27 08:01:10 | 显示全部楼层
fight281 发表于 2018-9-25 13:48
我只是想让变量a 和b 拥有共同的内存地址, 而a 是结构体内的成员,我不想打散结构体,4#的确实没看懂, ...

额我的意思不是这个。
楼主的疑问应该是在s.student_struct_pointer->name(来自4#的答案)
s是新定义的结构体,student_struct_pointer指向一个 student型的结构体变量,student_struct_pointer->name表示这个指针所指向的student型结构体变量的name成员变量。

这部分楼主可以看一下C语言书中,关于“->”运算符的使用方法。
十六进制带我飞。
回复

使用道具 举报

29

主题

338

帖子

1

精华

金牌会员

Rank: 6Rank: 6

积分
1181
金钱
1181
注册时间
2018-4-13
在线时间
170 小时
发表于 2018-9-27 14:57:49 来自手机 | 显示全部楼层
你在结构体里面再定义联合不就行了。
回复

使用道具 举报

9

主题

55

帖子

0

精华

初级会员

Rank: 2

积分
182
金钱
182
注册时间
2018-3-28
在线时间
30 小时
 楼主| 发表于 2018-9-28 17:27:02 | 显示全部楼层
DreamWaterPro 发表于 2018-9-27 08:01
额我的意思不是这个。
楼主的疑问应该是在s.student_struct_pointer->name(来自4#的答案)
s是新定义 ...

好的  谢谢!
回复

使用道具 举报

9

主题

55

帖子

0

精华

初级会员

Rank: 2

积分
182
金钱
182
注册时间
2018-3-28
在线时间
30 小时
 楼主| 发表于 2018-9-28 17:27:31 | 显示全部楼层
xiatianyun 发表于 2018-9-27 14:57
你在结构体里面再定义联合不就行了。

你说的这个好像可以,我回去试试,谢谢!
回复

使用道具 举报

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

本版积分规则



关闭

原子哥极力推荐上一条 /2 下一条

正点原子公众号

QQ|手机版|OpenEdv-开源电子网 ( 粤ICP备12000418号-1 )

GMT+8, 2025-6-20 06:03

Powered by OpenEdv-开源电子网

© 2001-2030 OpenEdv-开源电子网

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