0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
会员中心
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

如何判断一段字符串的长度

鱼鹰谈单片机 来源:鱼鹰谈单片机 2024-08-12 17:42 次阅读

来源:公众号【鱼鹰谈单片机

作者:鱼鹰Osprey

ID :emOsprey

这周课上介绍断言实现的时候,莫名其妙被断言的真真假假搞晕了。

起因是看到一段关于判断一段字符串的长度,使用了 ASSERT 方式,原文大概是这样写的:

#define AES256_KEY                      "0123456789ABCDEF0123456789ABCDEF"  /* 必须等于 32 字节 */
#define AES256_IV                       "0123456789ABCDEF"                  /* 必须等于 16 字节 */
extern void Assert_Failed(uint8_t *func, uint32_t line);
#define ASSERT(expr)            ((expr) ? (void)0U : Assert_Failed((uint8_t *)__func__, __LINE__))
voidfunc()
{
  ASSERT(sizeof(AES256_KEY) != 32);
     ASSERT(sizeof(AES256_IV) != 16);
}

一开始总以为这种写法没问题,毕竟这么简单,模拟调试的时候确实也不会报错(打开了断言情况下)。

为了课上测试一下静态编译报错的效果,却发现始终有些问题,不该报错的时候报错了。

#define STATIC_ASSERT(...)      extern char (*_do_assert(void)) [sizeof(char[1 - 2*!(__VA_ARGS__)])]

为了方便,鱼鹰直接用 MDK 测试了 sizeof 字符串的结果,发现确实也是16(0x10)

285aa6f4-4d44-11ef-b8af-92fbcf53809c.png

然后我就困在了这两个前提上,STATIC_ASSERT 报错始终有问题。

#define AES256_KEY                      "0123456789ABCDEF0123456789ABCDEF"  /* 必须等于 32 字节 */
#define AES256_IV                       "0123456789ABCDEF"                  /* 必须等于 16 字节 */
extern void Assert_Failed(uint8_t *func, uint32_t line);
#define ASSERT(expr)            ((expr) ? (void)0U : Assert_Failed((uint8_t *)__func__, __LINE__))


#define STATIC_ASSERT(...)      extern char (*_do_assert(void)) [sizeof(char[1 - 2*!(__VA_ARGS__)])]
void func()
{
     ASSERT(sizeof(AES256_KEY) != 32);
     ASSERT(sizeof(AES256_IV) != 16);
STATIC_ASSERT(sizeof(AES256_IV)!=16);
}

286bd05a-4d44-11ef-b8af-92fbcf53809c.png

调试的时候,STATIC_ASSERT ,但是 ASSERT不报错

这让鱼鹰百思不得其解,一开始以为两个宏逻辑相反,不都是逻辑值为假时报错。

但是通过分析宏发现,都是假的时候报错。

那肯定哪里分析有问题了。

因为编译器如果能得到结果为真,ASSERT可能无法形成代码,即为空(void)0U。

因此鱼鹰使用了一个变量作为中间值,强行让编译器生成断言相关的代码,才算是发现了问题。

void func()
{
uint32_tsize = sizeof(AES256_IV); 

    ASSERT(sizeof(AES256_KEY) != 32);
    ASSERT(size!=16);
    STATIC_ASSERT(sizeof(AES256_IV) != 16);
}

这个size 的值竟然是 17,而不是 16,难怪初始代码不报错,17 != 16,当然为真,当然不报错。

但写代码的人是希望这个字符串的长度为始终是16(不包含null的情况下),而明显代码中使用sizeof 时计算了 null 的长度。

所以代码应该这样写才对:

void func()
{
ASSERT(sizeof(AES256_KEY)==32);
ASSERT(sizeof(AES256_IV)==16);
STATIC_ASSERT(sizeof(AES256_IV)==16);
}

但是又因为代码的sizeof 会计算null,因此需要去除这个数:

void func()
{
ASSERT(sizeof(AES256_KEY) - 1==32);
ASSERT(sizeof(AES256_IV) - 1==16);
STATIC_ASSERT(sizeof(AES256_IV) - 1==16);
}

2884bafc-4d44-11ef-b8af-92fbcf53809c.png

这样 STATIC_ASSERT 可以在编译阶段就可以判断这个字符串的长度是否符合要求,多一个、少一个字符都不行。

这个坑你们遇到过吗?

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • 字符串
    +关注

    关注

    1

    文章

    578

    浏览量

    20505
  • 编译器
    +关注

    关注

    1

    文章

    1623

    浏览量

    49102
  • 编译
    +关注

    关注

    0

    文章

    656

    浏览量

    32847

原文标题:被断言罢了一道

文章出处:【微信号:emOsprey,微信公众号:鱼鹰谈单片机】欢迎添加关注!文章转载请注明出处。

收藏 人收藏

    评论

    相关推荐

    请问各位大神一段只读乱序字符串能否排序输出吗

    请问各位大神一段只读乱序字符串能否排序输出吗
    发表于 05-14 12:45

    Labview之字符串长度函数

    Labview之字符串长度函数,很好的Labview资料,快来下载学习吧。
    发表于 04-19 10:43 0次下载

    清华集训2017模拟之字符串

    一个字符串的权值是这个包含的不同字符个数。 给定长度为n的字符串,把它分为k个连续非空字段
    发表于 11-28 16:33 1393次阅读

    字符串移位包含的问题解决方案

    问题:给定字符串s和t,判断是否字符串t能通过将s移位后的字符串所包含。 方法 最简单的方法就是将s进行循环移位,再
    发表于 11-29 10:05 1043次阅读

    教你7个Python判断字符串是否包含子的方法

    教你7个Python判断字符串是否包含子的方法
    的头像 发表于 08-17 10:52 5084次阅读
    教你7个Python<b class='flag-5'>判断</b><b class='flag-5'>字符串</b>是否包含子<b class='flag-5'>串</b>的方法

    什么是复制字符串?Python如何复制字符串

    连续几篇文章都在写 Python 字符串,这出乎我的意料了。但是,有的问题,不写不行,特别是那种灵机动想到的问题,最后你发现,很多人根本不懂却又误以为自己懂了。那就继续刨根问底,探究个明白吧
    发表于 11-25 10:32 3009次阅读

    C语言总结_字符串全方位练习

    C语言字符串全方位练习,涉及知识点:字符串解析、大小写判断字符串插入、字符串删除、字符串排序、
    的头像 发表于 08-14 09:41 1474次阅读

    文详解JavaScript字符串

    JavaScript字符串是原始值。此外,字符串是不可变的。这意味着如果你修改一个字符串,你总是会得到个新的字符串。原始
    的头像 发表于 12-08 16:36 1183次阅读

    字符串的格式化输入和输出

    字符串是内存中一段连续的char空间,以’\0’(数字0)结尾。
    的头像 发表于 02-24 14:34 1403次阅读
    <b class='flag-5'>字符串</b>的格式化输入和输出

    字符串的相关知识

    TCL 中的数据类型只有种:字符串。这些字符串可以是字母、数字、布尔值、标点符号等特殊字符的组合。在某些特殊命令的作用下,字符串可以向其他
    的头像 发表于 03-29 11:41 1129次阅读

    Python 如何判断字符串是否包含子

    方法 使用 字符串 对象的 find 方法,如果有找到子,就可以返回指定子字符串中的出现位置,如果没有找到,就返回 -1 >> > "hello, python" . find
    的头像 发表于 11-02 10:55 483次阅读

    mysql字符串包含某个字符串

    MySQL是种开源的关系型数据库管理系统,被广泛用于构建Web应用程序和其他大型数据驱动的应用。在进行MySQL数据库查询时,经常需要使用字符串包含操作,即判断一个字符串是否包含另
    的头像 发表于 11-16 14:52 3775次阅读

    python输出固定长度字符串

    Python 是种强大而灵活的编程语言,具有许多用于处理字符串的功能。在 Python 中,有多种方法可以输出固定长度字符串。下面将详细介绍这些方法。 方法
    的头像 发表于 11-22 10:41 3268次阅读

    oracle判断字符串包含某个字符

    字符串操作是任何编程语言中都非常重要的部分,Oracle数据库作为目前最常用的关系型数据库之,也提供了丰富的字符串操作函数和方法。在本文中,我们将详细解析如何在Oracle中
    的头像 发表于 12-06 09:53 1.5w次阅读

    labview中常用的字符串函数有哪些?

    在LabVIEW中,常用的字符串函数广泛覆盖了对字符串的各种操作,包括但不限于格式化、搜索、替换、连接、计算长度等。以下是些常用的字符串
    的头像 发表于 09-04 15:43 646次阅读