c语言中printf错误,C语言中几个容易踩的“坑”!

原标题:C语言中几个容易踩的“坑”!

0a520937fbfe8fb677a839d00a41ebf7.png

今天给大家分享几个C语言中的坑。

一、带参数的宏展开顺序#include

#define f(a,b) a##b

#define g(a) #a

#define h(a) g(a)

intmain(void)

{

printf( "%sn",h(f( 1, 2)));

printf( "%sn",g(f( 1, 2)));

return0;

}

运行结果:

12

f(1,2)

浅析:

本题中的#运算符可以利用宏参数创建字符串。##运算符和#运算符一样也可以用于类函数宏的替换部分。另外,##还可以用于类对象宏的替换部分,这个运算符可以把两个语言符号组合成单个语言符号,所以该运算符也被成为“预处理粘合剂”。类参数宏展开遵循一定的顺序,先从外层开始探寻如果遇到#即刻结束探寻,从遇到#处开始一步一步向外层展开,如果没有遇到#探寻到最里层结束探寻,然后一步一步向外层展开。

所以printf("%sn",h(f(1,2)));这条语句的展开顺序为:h(f(1,2))(没有#) --->> f(1,2)(到达最里层依然没有#) ---->> h(12) ---->> 12。

然而printf("%sn",g(f(1,2)));这条语句的展开顺序是:g(f(1,2))(碰到#即刻结束探寻,开始展开) ----->>f(1,2)。

二、类型转换# include

intmain( void)

{

inta = -10;

unsignedb = 1;

if(a+b > 0)

printf( "a + b > 0n");

elseif(a + b < 0)

printf( "a + b < 0n");

else

printf( "a + b = 0n");

return0;

}

运行结果 :

a+ b > 0

浅析:

三、溢出问题

程序一 :

unsignedi;

for(i = 110; i >= 0; i--)

printf( "%un",i);

运行结果:

死循环

浅析:

该题的坑就在于没有注意到unsigned int 的存储范围,当小于零溢出时又会从unsigned int 的最大值开始递减,这就仿佛进入了一个圆环,永远都没有办法找到跳出圆环形跑道的缺口。

程序二:

# include

# include

intmain( void)

{

chara[ 1000];

inti;

for(i = 0; i < 1000; i++)

a[i] = -1- i;

printf( "%dn", strlen(a));

return0;

}

运行结果:

255

浅析:

这道题看上去很简单但是却暗藏杀机,很少有人能够答对,当i从0开始自增,自增到127时-1 - 127 = -128,而这个数正好是char型变量所能表示的最小数字,i再自增一次就会溢出,变成char所能表示的最大数字,这样又进入了上一题的那个“环”,当i增加到255时-1 - i = 0,此时第一次出现了0,而strlen函数碰到'0'就结束(不包括),因此输出结果为255。

四、strcpy函数voidtest

{

charstr[ 10],str1[ 10];

inti;

for(i = 0; i < 10; i++)

{

str1[i] = 'a'+ i;

}

strcpy(str,str1);

}

浅析:

这段代码第一眼看过去是没问题的,但是再看一眼就能够很轻松找到错误了,strcpy函数是拷贝字符串的函数,它是以'0'为结尾的,因此当程序运行strcpy这一行时会发生内存非法访问导致程序崩溃。

责任编辑:

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值