c库函数strncat出现乱字符
时间:2022-05-14
本文章向大家介绍c库函数strncat出现乱字符,主要内容包括其使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。
25 Nov 2016 c库函数strncat出现乱字符
最近项目接近尾声,基本都是在fix bug,今天说说一个bug,是由于strncat函数使用不当导致命令行输出有乱字符。虽说只是一个很简单的小问题,但是不弄明白就是大问题。
1 strncat声明
char *strncat(char *dest, const char *src, size_t n)
- dest: 目标字符串,需保证其容量能容纳连接后字符串
- src: 源字符串
- n: 追加的字符数,如果超过src大小,只拷贝src所有字符
这个函数的主要功能是将src指向的字符串追加到dest指向的字符串,最多追加n个字符,包括最后一个字符串结尾符NUL,最后返回指向dest字符串的指针。
2 strncat误用
引起bug的代码大致如下,主要功能是将一个字符串拷贝到一个空的字符数组中。
#include <stdio.h>
#include <string.h>
int main ()
{
char dest[10];
strncat(dest, "Hello World!", 100);
printf("Final destination string: %sn", dest);
return (0);
}
3 代码输出
root@leo:demo# crun strncat.c
Final destination string: Hello World!
root@leo:demo# crun strncat.c
Final destination string: τ:Hello World!
root@leo:demo# crun strncat.c
Final destination string: ᰷Hello World!
如果从第一次运行结果来看,看似没有什么问题。但是再运行2次,发现结果有乱字符。
广告时间: 这里使用的crun是我封装的一个命令,只是为了在终端运行c代码时方便,如果你觉得实用的话拷贝到你的bash配置文件,命令定义如下:
crun(){
gcc $1 -g;
if [ $? -ne 0 ]; then
echo "failed build $1"
else
./a.out
rm -rf ./a.out
fi
}
4 出现乱字符的原因
输出有乱字符,是因为dest声明后,没有初始化,其内存空间是一些随机数据。不是一个合法的字符串,所以没有字符串结束符NUL,但是strncat函数在追加字符串时需要知道目的字符串dest的结尾,因为找不到字符串结束符NUL,所以出现未定义行为。
5 strncat正确使用
所以正确使用方式是给dest第一个字符赋值为NUL,即字符 。
#include <stdio.h>
#include <string.h>
int main ()
{
char dest[10];
dest[0] = ' ';
strncat(dest, "Hello World!", 100);
printf("Final destination string: %sn", dest);
return (0);
}
6 总结
在c语言中,如果忽略了字符串结束符,会导致很多依赖字符串结束符的函数发生未定义行为。比如以下函数:
- strlen
- strcat
- strcpy
- strncpy
再强调下c字符串定义:
字符串是以ASCII字符NUL结尾的字符序列,ASCII字符NUL表示为 。
所以不要把字符数组和字符串混淆,字符串是一个字符数组,但是该字符数组最后一个字符必须是 ,但是字符数组不一定是字符串。上面说到的bug就是因为混淆了字符数组和字符串定义导致。
本次荐书:代码的未来
LEo at 22:09
- Mysql-15-mysql分布式应用
- 基于Spring Mvc实现的Excel文件上传下载
- Java程序员的日常—— Arrays工具类的使用
- Mysql-14-mysql的日志管理
- ERROR 1045 (28000): Access denied for user 'root'@'localhost' (using password: NO)
- Java程序员的日常 —— static的用法讲解实践
- WSAEventSelect模型 ---应用实例,重写TCP服务器实例
- Mysql-13mysql的复制
- 蓝牙门禁系统
- Java程序员的日常 —— 工作一天的收获
- Mysql-12-mysql的备份和恢复
- WSAEventSelect模型
- 事件分发机制学习
- Java程序员的日常—— 《编程思想》关于类的使用常识
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- 【一天一大 lee】子集 (难度:中等)-Day20200920
- 用了这个jupyter插件,我已经半个月没打开过excel了
- Webpack学习笔记
- 正则表达式学习笔记
- R 可视化 | 华夫饼图
- 绝了!Python定时爬取微博热搜+pyecharts动态图展示
- 实战 | Python爬取B站柯南弹幕+Gephi梳理主线剧情
- 别再问我 Python 怎么识别数字验证码了!
- Python自动化办公 | 同事要我帮忙补写178份Word日报!别闹!
- Excel多区间判断,其实很简单
- 外观模式
- cp命令
- java基本数据类型及相互间的转换(转)
- 【java设计模式系列】1. 工厂方法模式(Factory Method)
- 为什么 Java 中 1000==1000 为 false ?