C语言杂谈:从Hello world说起 #include| main| printf| return

#include<stdio.h>

int main()
{
	printf("Hellow world");
	return 0;
}

        打印出“Hello world”的这个程序相信每个人都是见过的,这段代码非常的简单,没有调用函数,没有使用指针,没有各种杂七杂八的东西,但我相信,第一次看见这个代码的朋友一定会有很多疑问。

        #include<stdio.h>是什么,它凭什么要第一个写,main函数又是什么,printf函数又是怎么打印的,return 为什么要return 0,如果return 1又会怎样,今天我就接着这个简单的程序来说说这些问题。

        预处理指令#include

        在学习Hello 程序时,大家都会听到一句“使用printf函数打印出Hello world”,既然printf是个函数,那么他的函数原型,定义又在哪里呢

我们框选printf,右键点击转到定义,发现跳转到了stido.h这个头文件页面

        也就是说,printf是在stdio.h这个头文件里面定义的,而stdio.h便是我们刚才在#include之后的内容。

这也就说明了,使用#include可以将一写常用的函数或者声明直接拿来使用。

具体的底层是在程序进行预处理时,就会将头文件的内容复制到我们的代码文件中,以便我们进行

函数,变量的调用。编译器看到#include就知道,这是预处理,我要把后面的东西复制进来了。

而对于#include除了可以使用<>,还可以使用“ ”

        使用尖括号< >,编译器会到系统路径下查找头文件;

        而使用双引号" ",编译器首先在当前目录下查找头文件,如果没有找到,再到系统路径下找。

        我们通常使用尖括号包含标准库中的头文件,因为标准头文件是在系统路径下的;而对于我

们自己创建的头文件,由于其在当前目录下,因此需要使用双引号。

        main函数

再往下面的main函数也值得说说,我们都知道函数可以传递参数,main函数也不例外,只不过在

初期学习的时候我们很少用到主函数的参数,所以我们通常是

int main(void)

实际上main可以传三个参数,

int main(int argc,char *argv[],char * envp[])

argc:表明命令行参数的个数

argv:表明命令行参数数组

envp:表面环境变量

#include<stdio.h>

int main(int argc,char *argv[],char * envp[])
{
	printf("参数个数是:%d\n", argc);
	printf("参数内容是:");
	for (int i = 0; i < argc; i++)
	{
		printf("%s\n", argv[i]);
	}
	printf("环境变量是:");
	for (int c = 0; envp[c] != NULL; c++)
	{
		printf("%s\n", envp[c]);
	}
	return 0;
}

这段代码,我们将打印主函数的参数个数是多少,函数的参数内容是什么,以及环境变量的内容

下面是运行结果:

printf函数

printf函数是我们使用频率非常高的一个函数,但是它也并不像表面那样的简单,

printf()是C语言标准库函数,用于将格式化后的字符串输出到标准输出。标准输出,即标准输出文

件,对应终端的屏幕。printf()申明于头文件stdio.h。

函数定义:

函数原型:

既然是个函数,就会有返回值,printf前面是int,说明会返回一个整形,正确返回输出的字符总

数,错误返回负值,与此同时,输入输出流错误标志将被置值,可由指示器ferror来检查输入输出

流的错误标志。

printf的调用格式:

printf()函数的调用格式为:printf("格式化字符串",输出列表)

格式化字符串包含下面三种情况:

1,字符串常量

2,格式控制字符串

3,转义字符

字符串常量原样输出,在显示中起提示作用。输出表列中给出了各个输出项,要求格式控制字符串和各输出项在数量和类型上应该一一对应。其中格式控制字符串是以%开头的字符串,在%后面跟有各种格式控制符,以说明输出数据的类型、宽度、精度等。

printf的格式控制字符串组成如下:%[flags][width][.prec][length]type

分别为:

%[标志][最小宽度][.精度][类型长度]类型。

除此之外还有一些其他的标志:

printf("%5d\n",1000);               //默认右对齐,左边补空格
printf("%-5d\n",1000);              //左对齐,右边补空格
 
printf("%+d %+d\n",1000,-1000);     //输出正负号
 
printf("% d % d\n",1000,-1000);     //正号用空格替代,负号输出
 
printf("%x %#x\n",1000,1000);       //输出0x
 
printf("%.0f %#.0f\n",1000.0,1000.0)//当小数点后不输出值时依然输出小数点
 
printf("%g %#g\n",1000.0,1000.0);   //保留小数点后后的0
 
printf("%05d\n",1000);              //前面补0

其他输出示例不再经行演示

转义字符:

了解了printf三种打印类型后,我们还应该知道缓冲区,在printf的实现中,

在调用write之前先写入IO缓冲区,这是一个用户空间的缓冲。系统调用是软中断,频繁调用,需要频繁陷入内核态,这样的效率不是很高,而printf实际是向用户空间的IO缓冲写,在满足条件的情况下才会调用write系统调用,减少IO次数,提高效率。

printf在glibc中默认为行缓冲,遇到以下几种情况会刷新缓冲区,输出内容: 
(1)缓冲区填满; 
(2)写入的字符中有换行符\n或回车符\r; 
(3)调用fflush手动刷新缓冲区; 
(4)调用scanf要从输入缓冲区中读取数据时,也会将输出缓冲区内的数据刷新。

可使用setbuf(stdout,NULL)关闭行缓冲,或者setbuf(stdout,uBuff)设置新的缓冲区,uBuff为自己指定的缓冲区。也可以使用setvbuf(stdout,NULL,_IOFBF,0);来改变标准输出为全缓冲。全缓冲与行缓冲的区别在于遇到换行符不刷新缓冲区。

return 

1) 求值表达式,终止当前函数,并返回表达式的结果给调用方(该返回值成为函数调用表达式的值)。仅对函数返回类型非 void 的情形合法。

int add(int a,int b)
{
    return a+b;
}

2) 终止当前函数。仅对函数返回类型为 void 的情形合法。

void test(int &a)
{
    a++;
    return ;
}

既然return可以终止当前函数,那我们就比较一下return,break,continue

break:

function myBreak() {
 
for(var i = 0; i < 5; i++) {
 
if(i == 3) {
 
break;
 
}
 
console.log(i);
 
}
 
}
 
myBreak();
 

break: 直接跳出当前的循环,从当前循环外面开始执行,忽略循环体中任何其他语句和循环条件测

试。它只能跳出一层循环,如果你的循环是嵌套循环,那么你需要按照你嵌套的层次,逐步使用

break来跳出。

continue:


function myContinue() {
 
for(var i = 0; i < 5; i++) {
 
if(i == 3) {
 
continue;
 
}
 
console.log(i);
 
}
 
}
 
myContinue();

continue: 终止当前的一次循环过程,其 不 跳出循环,而是继续往下判断循环条件执行语句。

只能结束循环中的一次过程,但不能终止循环继续进行。

在编写代码时,应当尽量减少continue的使用,因为很容易会造成死循环。

return

function myReturn() {
 
for(var i = 0; i < 5; i++) {
 
if(i == 3) {
 
return i;
 
}
 
console.log(i);
 
}
 
}
 
var s = myReturn();
 
console.log("s: " + s);
 

return: 从当前的方法中退出,返回到该调用的方法的语句处,继续执行。

总结
1、return语句的作用

(1) return 从当前的方法中退出,返回到该调用的方法的语句处,继续执行

(2) return 返回一个值给调用该方法的语句,返回值的数据类型必须与方法的声明中的返回值的类型一致,可以使用强制类型转换来是数据类型一致

(3) return 当方法说明中用void声明返回类型为空时,应使用这种格式,不返回任何值。

2、break语句的作用

(1) 只能在循环体内和switch语句体内使用break语句。

(2) 当break出现在循环体中的switch语句体内时,其作用只是跳出该switch语句体。

(3) 当break出现在循环体中,但并不在switch语句体内时,则在执行break后,跳出本层循环体。

(4) 在循环结构中,应用break语句使流程跳出本层循环体,从而提前结束本层循环

3、continue语句作用

(1) continue语句的一般形式为:continue;

(2) 其作用是结束本次循环,即跳过本次循环体中余下尚未执行的语句,接着再一次进行循环的条件判定。

(3) 注意:执行continue语句并没有使整个循环终止。在while和do-while循环中,continue语句使得流程直接跳到循环控制条件的测试部分 ,然后决定循环是否继续进行。

(4) 在for 循环中,遇到continue后,跳过循环体中余下的语句,而去对for语句中的“表达式3”求值,然后进行“表达式2”的条件测试,

最后根据“表达式2”的值来决定for循环是否执行。在循环体内,不论continue是作为何种语句中的语句成分,都将按上述功能执行,这点与break有所不同

wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==
  • 42
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值