一、sscanf语句
先(最一般的情况)代码展示:
char arry[100];
int main(){
sscanf("abcdeff","%*c%3s",arry);
printf("%s",arry);
return 0;
}
其输出结果是:bcd
第一个" "中存储目标字符串,最后结果字符串只与这个有关。
第二个" "负责控制格式和特殊要求,其中 第一个%*表示忽略一个*所占位置的字符,也就是从b开始读写。第二个%3s表示按照字符串格式,长度是3。
变式一下: sscanf("abcdeff","%2[a-c]s",arry);
其输出结果为: ab
其中2 [a-c]表示 只要a,b,c三个字符,也要符合长度为2。
但是要注意,sscanf是从左到右依次进行读写操作,一旦读到的目标字符串的某一个字符不符合特殊要求,那就会立刻停止。
比如: sscanf("ddddeff","%2[a-c]s",arry); 其输出结果为 : (什么也没有)前2位没有abc
再比如: sscanf("ddedeff","%5[a-d]s",arry); 其输出结果为 :dd 读到第三个时,e不属于abcd中,不符合要求,立刻停止读写。
二、printf语句
printf的返回值是输出的字符个数
Part A:
测试代码实现:
int main() {
int a=43;
printf("%d",printf("%d",printf("%d",a)));
return 0;
}
其运行结果为: 4321
能说明什么问题呢?
①printf这个函数,是要先执行后面部分的,所以先打印了43,后打印2再是1。
②printf的返回值是输出的字符个数 也就是""里面除了格式控制部分的字符个数,为什么强调是粗体呢?
比如这个: printf("%d|",printf("%d|",printf("%d",a))); // 本来想用分隔符来看看那部分先跑来着,结果弄巧成拙发现了这个小坑
其输出结果为 :432|2| 为什么最后一个数不是1呢,因为上一个printf 不仅打印了2这个数 还打印了'|',这是两个符号,所以是2 不是1。
三、宏定义进阶
测试代码如下:
#include
#define f(a,b) a##b#
define g(a) #a#
define h(a) g(a)
int main(){
printf("%s\n",h(f(1,2)));printf("%s\n",g(f(1,2)));
return 0;
}
其运算结果是:12 f(1,2)
先来解释一下运算符号:
#a :是把a变成字符串,比如#1 就是把整型的1变成‘1’。不仅如此,是把#后面的所有全部变成字符型,无条件转换,哪怕是函数,也变成一串字符。
a##b:是把ab连接到一起
然后解释宏定义:
#define f(a,b) a##b
#define g(a) #a 这两个都是运算的宏定义
#define h(a) g(a) 这是函数的宏定义,其运算规律是:需要先把参数替换,再把函数替换
准确的说是h(a)这个函数的宏定义
现在解释运算结果:
12:1和2先变成12(是整型的十二,可以通过printf("%d",f(1,2)-2);验证,发现是10)带入的是g(a) 变成两个字符12之后打印出来。//注意运算规律 因为他的外函数是个宏定义函数
f(1,2): 外函数是g(a) 运算的宏定义,直接运行g(a) 也就是把f(a,b)变成字符型打印出来。
四、一个程序的运行步骤
一个main.c文件先经过预处理器进行预处理,预处理过程包括:头文件的附加,宏定义的替换。(没有语法检查!!)变成main.i文件,然后通过编译器编译变成main.s文件,期间进行优化和语法检查功能,然后通过汇编器汇编生成main.o文件,(生成机器代码),最后通过链接器,链接完成后跑出代码,链接过程包括把头文件联系到一起等等。
穿插一个
测试代码实现:
int main(){
int i=10;
printf("%d\n",sizeof(i++)); //sizeof 是单目运算符不是函数。所以这个地方也可以不加括号 但是必须有空格隔开
printf("%d\n",sizeof i++ );
printf("%d",i);
return 0;
}
其运行结果为: 4 10(忽略\n)
分析:printf是在链接完成后才开始运行,也就是运行阶段才运行,但是sizeof在编译阶段就完成了,也就是编译完后语句变成了printf("%d\n",4); 根本没有进行i++的操作,所以printf出来的i 还是10。