用puts函数出现的奇妙景象(顺便擦点pwn的边)

本文探讨了C语言中使用puts函数输出二维字符数组的怪异现象,解析了puts函数的行为,并通过对比printf函数揭示了字符串终止符的重要性。文章还意外地触及了pwn领域的知识,展示了如何利用puts函数进行内存信息泄露。

事情的起因是这样的。
我在写从题目入门指针和动态一二维数组的历程(萌新入门可参考)(下篇)的时候想试试二维数组输出a[i]会不会输出一行
然后写个代码

#include<stdio.h>
int main()
{	int i,j; 
	char a[10][10];
	for(i=0;i<10;i++)
	 	{for(j=0;j<10;j++)
	 	a[i][j]='z';} 
	for(i=0;i<10;i++)
	  puts(a[i]);
	return 0;
} 

猜猜运行后的结果
是不是和我一开始想的一样,会输出10*10的zzzzz矩阵呢

结果输出来是这样的
在这里插入图片描述
迷了,然后试着把输出改成两层循环,不用puts()

	for(i=0;i<10;i++)
	  {
	  	for(j=0;j<10;j++)
	  	printf("%c",a[i][j]);
	  	printf("\n");
	  } 

在这里插入图片描述这回输出的是正常的
那应该是puts函数的问题
再试试改成单层循环的printf

	  	printf("%s\n",a[i]);

在这里插入图片描述呦呵,见鬼了。
听说puts只能输出一行内容,那把它改成11行是不是就写不下了?
把代码改成11行
ctrl+f替换
在这里插入图片描述在这里插入图片描述pu,puts()输出了两行?
大白天见鬼的我转身把鬼丢给了精通pwn的师兄
对没错还是这只
在这里插入图片描述
然后我:在这里插入图片描述

自己的思考是字符串结尾都有个\0的,我没有\0,所以它会一直沿着地址把后面的都输出来,而数组在内存里是连续的。所以第一行不但输出了自己的,还输出了后面9行,一共1010一百个,第二行的地址是从第一行后面往后移动十个开始的,所以是910为90个,一直到最后为10个,数了下果真如此。
然后百度下puts的/x00截断是什么东西
在这里插入图片描述

pwn???
然后大概搜出来有意思的有这么些个东西
利用puts函数泄露libc内存信息

puts和libc内存关系

大致是讲如何利用puts函数来完成pwn
在这里插入图片描述
看来还要补补libc的知识
在这里插入图片描述看来好像是入门教程五
i春秋上好像有全套教程,先放这里慢慢学
https://bbs.ichunqiu.com/article-1797-1.html

总结:话说我就做c语言第五章的一道课后习题怎么转向学pwn了
见鬼了。

# 题目重述 问题是关于 C 语言中 `puts` 函数的使用方法。 要求解释其功能、语法、特以及常见用法示例。 --- # 详解 `puts` 是 C 语言标准库 `<stdio.h>` 中的一个函数,用于**输出字符串到控制台(终端)**,并在输出后**自动添加换行符 `\n`**。 ### 📌 基本语法: ```c int puts(const char *str); ``` - 参数:一个指向字符串的指针(即字符数组名或字符串常量)。 - 返回值:成功时返回非负值;失败时返回 `EOF`。 ### ✅ 功能特: 1. **自动换行**:`puts` 会在输出完整个字符串后自动追加一个换行符 `\n`。 2. **只能输出字符串**:不能像 `printf` 那样格式化输出整数、浮数等。 3. **要求字符串以 `\0` 结束**:和所有 C 字符串处理函数一样,`puts` 依赖空字符标记结束。 4. **性能略高于 `printf`**:对于纯字符串输出,`puts` 更快更简洁。 --- ### 🌰 使用示例 ```c #include <stdio.h> int main() { char str[] = "Hello, World!"; puts(str); // 输出: Hello, World! 换行 puts("你好,C语言"); // 输出: 你好,C语言 换行 puts(""); // 输出空行 puts("This is on a new line."); return 0; } ``` **输出结果:** ``` Hello, World! 你好,C语言 This is on a new line. ``` --- ### ⚠️ 注意事项 | 对比项 | `puts(str)` | `printf("%s", str)` | |--------|-------------|----------------------| | 是否自动换行 | ✔️ 是 | ❌ 否 | | 格式化能力 | ❌ 仅限字符串 | ✔️ 支持多种类型 | | 输出空字符串 | 输出一个换行 | 不输出任何内容(除非加 `\n`) | 📌 所以: ```c puts("Hello"); // 等价于 printf("Hello\n"); ``` --- ### ❗ 特殊情况:不希望换行怎么办? 如果你不想换行,就**不要用 `puts`**,改用: ```c printf("%s", str); // 不会自动换行 ``` --- # 知识(列出该代码中遇到的知识) - **字符串输出函数**:`puts` 专用于输出以 `\0` 结尾的字符串,简化换行操作。 - **自动换行机制**:相比 `printf`,`puts` 自动添加 `\n`,减少代码量。 - **函数参数限制**:只能传入字符串,无法进行格式化输出,适用场景较单一。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值