OpenEdv-开源电子网

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

请教STM32字符串变量问题: strlen()和sizeof()均不返回长度值(软件仿真)?

[复制链接]

2

主题

9

帖子

0

精华

论坛元老

Rank: 8Rank: 8

积分
5645
金钱
5645
注册时间
2016-12-23
在线时间
336 小时
发表于 2016-12-23 12:30:12 | 显示全部楼层 |阅读模式
3金钱
新手注册,赏金不多,见谅!刚刚因为工作需要要熟悉STM32,以前编过几年的51……
开发环境为Keil MDK 5, 使用了原子的部分库函数。
最近碰到要组合字符串的需求,输出一个版本信息。

用main函数初步测试,发现无论使用 strlen() 还是 sizeof() 均不能返回字符串(数组)的长度(容量大小)。
请问各位有没有谁碰到过这种情况?

Use MicroLIB 状态下:
测试代码如下:
1.首先包含了必要的标准库文件:
[mw_shl_code=c,true]
/*************ANSI C 标准库头文件************/
//禁止半主机模式
#pragma import(__use_no_semihosting)
#include <stdio.h>  //struct __FILE, printf, sprintf... Need Target->Use MicroLIB
//#include "mystdio.h"//struct __FILE, printf, sprintf... Need Target->Use MicroLIB
#include <string.h> //standard string operation: strcpy, strcat...
.......
[/mw_shl_code]

2.main()下加入如下代码:
[mw_shl_code=c,true]
int main(void)
{
    char * s[2], str[30], sTmp[20];
    const char *pcc = "abcdef";
    uint16_t i = 103, f;
    size_t len = 0;

    s[0] = "JLP280";
    s[1] = "-A/A-";
    sprintf(sTmp, "%s", s[0]);
    strcat(sTmp, s[1]); //sTmp = s[0] + s[1]
    f = i;
    i /= 100;
    f %= 100;
    len = 1000; //如果注释此句, 编译会出warning: len 定义了但没使用. 说明下面改变len值得3句没有作用...
    //str = sTmp + "1.03"
    sprintf(str, "%s%s%d.%02d,len=%.5u", s[0], s[1], i, f, len);

    len = sizeof(str); //设断点, len的值没有被改变!!
    len = strlen(str);
    len = strlen(pcc);


    //......
}
[/mw_shl_code]


然后编译,可以通过,无warning。
问题1:软件仿真,设断点在len改变之处,发现 len 的数值无变化。
问题2:同时查看到 strlen() 的 type 怎么是 “void f()” ?? 而 strcat() [string.h] , sprintf() [stdio.h] 功能均正常.


以下是软件仿真截图,个人认为跟软件仿真没关系,这都是C标准库操作,跟硬件基本无关也不会影响硬件什么……求解!

软件仿真 strlen 01

软件仿真 strlen 01


软件仿真 strlen 02

软件仿真 strlen 02


各位帮忙看看哪里不对吗?谢先,必须有请原子兄~~

最佳答案

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

很简单的问题,用strlen,如果不能出来,说明你的str可能有问题,用printf,打印出来看看,或者仿真的时候,看看str的内容即可。
正点原子逻辑分析仪DL16劲爆上市
回复

使用道具 举报

530

主题

11万

帖子

34

精华

管理员

Rank: 12Rank: 12Rank: 12

积分
165516
金钱
165516
注册时间
2010-12-1
在线时间
2116 小时
发表于 2016-12-23 12:30:13 | 显示全部楼层
很简单的问题,用strlen,如果不能出来,说明你的str可能有问题,用printf,打印出来看看,或者仿真的时候,看看str的内容即可。
我是开源电子网www.openedv.com站长,有关站务问题请与我联系。
正点原子STM32开发板购买店铺http://openedv.taobao.com
正点原子官方微信公众平台,点击这里关注“正点原子”
回复

使用道具 举报

5

主题

90

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
282
金钱
282
注册时间
2016-8-5
在线时间
158 小时
发表于 2016-12-23 12:48:32 | 显示全部楼层
自己写吧
while(*p != '\0')
{
    p++;
   i++;
}
回复

使用道具 举报

2

主题

9

帖子

0

精华

论坛元老

Rank: 8Rank: 8

积分
5645
金钱
5645
注册时间
2016-12-23
在线时间
336 小时
 楼主| 发表于 2016-12-23 13:08:31 | 显示全部楼层
是啊,实在不行就自己写,效率还高,可如果想用sizeof做数组动态下标,就不行了 : (

还是想搞清楚是不是大家都碰到过,有解吗?
回复

使用道具 举报

2

主题

9

帖子

0

精华

论坛元老

Rank: 8Rank: 8

积分
5645
金钱
5645
注册时间
2016-12-23
在线时间
336 小时
 楼主| 发表于 2016-12-23 13:57:48 | 显示全部楼层
在线等??没人理我吗?……

好吧,顺便发个小共享置一下顶:
MDK 5的 'Use MicroLIB' 环境下(MDK 4也应该一样),sprintf衔接2个字符串,
【如:sprintf(dest_str, "%s%s", char * from_s1, char * from_s2),相当于 strcat 的效果:from_s1字符串结尾的空字符'\0'会被自动覆盖! 】用我此贴的例子可以验证. 因此如果strlen()仍然无法使用,需要自己写的话, 可以去掉 [string.h] 库的包含,直接使用 sprintf 即可实现字串组合目的.

难道ST的微库对此还是做了改动的?? 这个很细节啊。 按 谭浩强 那本书上的说(p75 printf), 标准ANSI C 的 sprintf() 做2字符串衔接,不会去除 s1 的'\0' . 这个原来好像还验证过,现在没环境了(DOS622+x86工控+Turbo C),是否像书上所说,不得而知。
回复

使用道具 举报

2

主题

9

帖子

0

精华

论坛元老

Rank: 8Rank: 8

积分
5645
金钱
5645
注册时间
2016-12-23
在线时间
336 小时
 楼主| 发表于 2016-12-24 00:00:54 | 显示全部楼层
没人回答,好失望~~
回复

使用道具 举报

11

主题

94

帖子

0

精华

初级会员

Rank: 2

积分
188
金钱
188
注册时间
2016-12-12
在线时间
55 小时
发表于 2016-12-24 10:07:10 | 显示全部楼层
友情支持一下,希望有人能够解答。
回复

使用道具 举报

0

主题

3

帖子

0

精华

新手上路

积分
44
金钱
44
注册时间
2016-12-25
在线时间
12 小时
发表于 2016-12-25 21:19:34 | 显示全部楼层
len后面没有使用,是否优化掉了?
回复

使用道具 举报

2

主题

9

帖子

0

精华

论坛元老

Rank: 8Rank: 8

积分
5645
金钱
5645
注册时间
2016-12-23
在线时间
336 小时
 楼主| 发表于 2016-12-27 09:30:34 | 显示全部楼层
正点原子 发表于 2016-12-23 12:30
很简单的问题,用strlen,如果不能出来,说明你的str可能有问题,用printf,打印出来看看,或者仿真的时候 ...

谢谢原子的回复。

我原文已经用软件仿真试了,我用 str 和 char *pcc 都试了,str内容我初始化成常量也不行,而且尾部是肯定有'\0'的。

所以,我感觉不是代码问题,可能还是环境哪里设置的问题,可找不出来~ 因为没明白为何 sizeof 也有问题??!!

另,len如果注释掉 'len=1000;' 就会抛warning,而不是被优化了。也可以从另外角度理解为被优化了,因为出的warning是说len未被使用,说明len初始化后没再被赋值,进而说明所有可以改变len值得 sizeof,strlen语句全没起作用,但是仿真可以看到它们是被编译过的。

所以,还望有熟悉此问题的仁兄悉心点明一下!
回复

使用道具 举报

2

主题

9

帖子

0

精华

论坛元老

Rank: 8Rank: 8

积分
5645
金钱
5645
注册时间
2016-12-23
在线时间
336 小时
 楼主| 发表于 2016-12-27 09:45:24 | 显示全部楼层
我再仿真试试吧,strlen可以自写程序实现(本来我也是想自己写的),但sizeof如果用不了,着实挺难受的……很多数组下标要用到……
或者,我挪到其他位置试试,比如其他函数?

再次谢谢回复仁兄!
回复

使用道具 举报

2

主题

9

帖子

0

精华

论坛元老

Rank: 8Rank: 8

积分
5645
金钱
5645
注册时间
2016-12-23
在线时间
336 小时
 楼主| 发表于 2016-12-30 17:11:41 | 显示全部楼层
最近又针对此问题仿真了一下,有如下截图的调整。。。。

无标题01.png

这里的 len=strlen(str); 和 len=sizeof(str); 都可以返回正常的数值:0x14(20) 和 0x1E(30)。
发现是2个问题造成的:
1)如果 len 不加 volatile 修饰,是会被莫名其妙优化掉!
2)MDK5的 shell 可能确实有问题,这可能就是自打出了uv4后就留下的后遗症:我为了每天工作方便,电脑下班是休眠关闭的(内存数据存硬盘),第二天再来启动会比较快,可是Win的休眠看来也有兼容性问题,有时恢复回来的RAM数据会有局部变化?…… 总之,即使不是休眠电脑,MDK5本身的shell可能有时会不更新,即便选择 “编译所有”,有时上次软件仿真的状态还会残留?! 应该只在软件仿真会出现!这个严重地误导了我更换N条语句(内容、顺序等),调试结果都一样的结论,发现某个断点没有清除,觉得应该是MDK环境问题,偶然重新打开一遍后,一切就正常了! 也就是, len=strlen(str); 等,放在sprintf之前,还是之后,len 加了 volatile 后,都可以返回正常值!只是MDK5环境的问题。后续验证了几遍确认了此问题。


【给64位Win7系统装MDK5的坛友提个醒,当软件仿真觉着有问题时,重启一下MDK环境试试~ 】


代码中,去掉 strcat 字符串内容追加函数的使用(这货以前也不好用,慎用!sprintf 基本可以实现这些函数的功能),增加另一个 size_t (unsigned int32) 变量 len1 ,验证了不加 volatile 修饰,还是会被优化掉的情况。拿 len1 取 char* pcc; len1 = sizeof(pcc); 会报pcc设置但未被使用(sizeof 没用, 可能 len1 被优化),取 len1 = sizeof(char *)是可以取到 4 的。提醒大家注意:sizeof(取变量长度) ,一定是取变量类型,而不是变量的 sizeof ...


最后,感谢 原子兄 的分析,加为 “最佳答案” 吧,跟 str 的状态确实有关! 同时 结贴 !!

回复

使用道具 举报

2

主题

21

帖子

0

精华

初级会员

Rank: 2

积分
65
金钱
65
注册时间
2016-1-4
在线时间
13 小时
发表于 2020-2-7 14:56:22 来自手机 | 显示全部楼层
十分感谢楼主!特地登录上来感谢
回复

使用道具 举报

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

本版积分规则



关闭

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

正点原子公众号

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

GMT+8, 2025-5-20 08:59

Powered by OpenEdv-开源电子网

© 2001-2030 OpenEdv-开源电子网

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