前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >C语言竟支持这些操作:C语言神奇程序分享

C语言竟支持这些操作:C语言神奇程序分享

作者头像
小嗷犬
发布2022-11-15 15:26:19
2.2K0
发布2022-11-15 15:26:19
举报
文章被收录于专栏:小嗷犬的CSDN文章

✅作者简介:人工智能专业本科在读,喜欢计算机与编程,写博客记录自己的学习历程。 🍎个人主页:小嗷犬的博客 🍊个人信条:为天地立心,为生民立命,为往圣继绝学,为万世开太平。 🥭本文内容:C语言竟支持这些操作:C语言神奇程序分享


C语言神奇程序分享


近期在网上冲浪的时候发现几个十分有趣的C语言程序,它们运行之后会产生一些看似不是很合理,但其实是十分合理的结果,让我们一起来看看吧!

1.神奇的死循环

下面这段程序运行之后可能会造成死循环:

代码语言:javascript
复制
#include<stdio.h>

int main()
{
	int a[10], i;
	for (i = 0; i <= 10; i++)
	{
		a[i] = 0;
	}
	return 0;
}

初学C语言的小伙伴可能死活也想不出为什么会有死循环,这个结构隐藏在平时的作业中,让我们的初学者不停挠头。

产生错误的原因首先是因为数组的访问越界,大小为10的数组只能访问0-9,毕竟咱们程序员数数是从零开始的。

循环中从0访问到10,就造成了访问越界,这在C语言中是可以编译通过的,因为在C语言中,数组名其实是一个地址,编译器不会知道这个地址管到了多少位,它只会把访问的索引看作偏移量进行访问。

然后是因为内存地址的问题,在这个程序中,我们先定义了数组a,然后又定义了整型变量i,此时绝大多数编译器都会先为数组a分配内存地址,然后紧挨着数组a再为整型变量i分配内存地址。

这就造成了:当我们在访问a[10]时,其实是在访问变量i,循环最后会将a[10]设置为0,即将变量i设置为0,循环就无法满足退出条件,于是产生了死循环。


2.神奇的隐式转换

在某些弱类型语言中,隐式转换是十分常见的,如在JavaScript中,用一个数字去减去一个形如数字的字符串,JavaScript会将字符串隐式转换为数字,再进行数字之间的减法运算。

下面的C语言程序似乎也出现了隐式转换的现象:

代码语言:javascript
复制
#include<stdio.h>

int main()
{
	puts("-0.5" + 1);
	// 输出:0.5
	return 0;
}

这段程序竟然会输出0.5,似乎就是将字符串"-0.5"隐式转换成了浮点数-0.5,再与数字1进行加法运算的。

难道我们的C语言也支持类似JavaScript那种隐式转换吗?

C语言当然是不支持这样的隐式转换的,那程序为什么会输出0.5呢?

其实输出的0.5并不是一个数字,其实它是以一个字符串的身份输出的。

这就要从C语言的字符串说起了,在C语言中,没有字符串类型,字符串其实都是用以'\0'结尾的字符数组储存的,而数组名则表示字符串的首地址。

字符串常量也是类似,程序中的字符串"-0.5"其实也是表示储存了"-0.5"中的各个字符和字符'\0'的字符数组的首地址。

而其后的+1则并不是表示数学运算上的加一,而是表示地址向后偏移一个单位的地址,即原来字符串第二个字符的地址。

这样就能让puts()函数跳过第一个字符'-'负号来输出字符串,自然输出的结果就是0.5了。

所以其实上面那个程序就等价于以下程序:

代码语言:javascript
复制
#include<stdio.h>

int main()
{
	char* p = "-0.5";
	puts(&p[1]);
	// 输出:0.5
	return 0;
}

3.神奇的**指数运算

在Python中,我们可以使用**运算符来表示数学上的指数运算,而在C语言中通常是用pow()函数。

下面的程序似乎显示,C语言也可以使用**运算符来进行指数运算:

代码语言:javascript
复制
#include<stdio.h>

int main()
{
	printf("%d\n", 50 ** "2");
	// 输出:2500
	return 0;
}

但细看就可以发现一部分问题,首先那个"2"是字符串,如果真的能够进行**指数运算,那也一定是两个数字之间的。

也许字符串"2"被编译器隐式转换成数字2了呢?

在上一节我们提到,C语言中的字符串是用字符数组存的,也就是说字符串"2"其实是一个字符数组,其中包含两个字符:'2''\0',将一个包含两个字符的字符数组转换成一个数字,这显然是做不到的。

在Python中,有字符串类型,通过强转型函数可以将字符串转换为其他类型,但是即便是Python,也不支持上述那种隐式转换,即无法将一个数组与一个字符串进行**指数运算。

排除了隐式转换,让我们来分析一下原因。

首先,在C语言中没有**这种运算,所以两个星号*应该是拆开来理解。

我们知道,在C语言中,星号*不止可以用来进行乘法运算,还可以连接地址用来表示取值运算,这也能够解释为什么后面的"2"是字符串了,上节我们说过,字符串常量在C中也是一个地址,于是正确的运算结合顺序就出来了:

代码语言:javascript
复制
#include<stdio.h>

int main()
{
	printf("%d\n", 50 * (*"2"));
	// 输出:2500
	return 0;
}

"2"表示一个含有两个字符('2''\0')的字符数组的首地址,那么*"2"就等价于"2"[0],即等价于字符'2'

我们又知道,C语言中的char类型其实是整数到ASCII表的一组映射,其值为它的ASCII码值,刚好字符'2'的ASCII码的十进制值为50

所以我们最终可以得到以下等价关系:

代码语言:javascript
复制
	50 ** "2"
=>	50 * (*"2")
=>	50 * "2"[0]
=>	50 * '2'
=>	50 * 50

所以上面的程序也可以写成这样:

代码语言:javascript
复制
#include<stdio.h>

int main()
{
	printf("%d\n", 50 * 50);
	// 输出:2500
	return 0;
}

这样程序运行自然就会输出2500了,是不是觉得很合情合理呢?

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2022-11-08,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • C语言神奇程序分享
  • 1.神奇的死循环
  • 2.神奇的隐式转换
  • 3.神奇的**指数运算
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档