C语言入门:HelloWorld程序详解
一. 第一个C程序
(1)、第一个C程序说明:hello world
配置部署好 vsCode 之后,就可以直接在上面写代码了,新建一个新的C程序文件,向屏幕输出一串字符 “Hello World!”
下面,从整体上来分析一下这个最简单的C语言程序,将这个最简程序的各个部分剖析清楚,明白我们写下的每一个字符的具体含义。
#include <stdio.h> // 头文件
int main(void) // 主函数
{
printf("Hello, World!\n"); // 标准库函数
return 0; // 关键字
}
注意:C语言程序中,任何符号(包括变量和函数)的使用,都是需要提前声明的。
/*
说明(必须三合一):
声明:告诉编译器函数定义和变量定义在哪里
定义:具体的函数或变量定义实现的地方
调用:跳到定义的地方,执行具体的函数或变量
流程:
遇到调用的函数,编译器先检查一下之前有没有这个声明,有的
话直接跳到那个函数的定义实现的地方执行
*/
#include <stdio.h> // stdio.h头文件官方: 在这个头文件中有printf等函数或变量的声明语句,编译器已经知晓
extern int funcA(void); // 自己写的函数或变量声明: funA这个函数,我们需要提前声明,否则编译器找不到
extern int funcB(void); // extern告诉编译器,需要对所有工程里面的文件进行扫描后,查看到底有没有这个函数或变量的定义,再运行
extern int num;
// 主函数
int main(void)
{
printf("hello world!\n"); // 函数调用1:stdio库提供的函数
funcA(); // 函数调用2:自己写的函数
num = 100; // 变量的引用
int ret = funcB(); // 获取funcB函数的返回值,得知这个函数的运行情况
printf("ret == %d\n", ret);
return 0;
}
int num = 100; // 变量定义
// 普通函数1
int funcA(void) // 函数定义(实现)
{
printf("hello funcA\n");
return 0;
}
// 普通函数2
int funcB(void)
{
printf("hello funcB\n");
return 0;
}
图解:
(2). 头文件
#include <stdio.h>
- 如果程序用到了系统库函数,那么就需要包含相应的系统头文件来进行声明。
- 上述代码中用到了库函数 printf ,而这个函数的声明在头文件 stdio.h 中,因此在该程序中需要包含此头文件。
声明:
- 概念:对源文件外定义的某个符号进行描述的过程,称为声明
- 作用:经过声明的符号,编译器才能正确识别和编译,否则编译器不认识,无法判定语法错误
- 符号:变量、函数等
- 示例:
// 声明一个变量符号num extern int num; // 声明一个函数符号funA extern int funA(void); // 注意:前面的extern的关键字是可以不写的,但是我建议初学者一定要加 // 缺少头文件报错提醒 implicit declaration 隐式声明 main.c: In function ‘main’: main.c:4:5: warning: implicit declaration of function ‘printf’ [-Wimplicit-function-declaration] printf("helloworld\n"); ^~~~~~ main.c:4:5: warning: incompatible implicit declaration of built-in function ‘printf’ main.c:4:5: note: include ‘<stdio.h>’ or provide a declaration of ‘printf’
(3). 主函数格式
- 主函数是必须有的,每一个C语言程序有且仅有一个main函数,哪怕是空的。
- 主函数的名字是固定的,叫 main ,这个函数名不可被挪作他用。
- 主函数是程序的入口,也就是程序开始运行的地方。
- 主函数分解如下:
// int: 返回值类型,代表主函数最终的执行结果是一个整型数据 // main(void): main是函数名,这个名字不能变 // void是函数参数列表,可以省略 int main(void) { }
-
在 Linux 环境下,主函数 main 根据程序最终是否需要接收外部命令行参数,实际上有两个版本:
// 不接收外部命令行参数的版本 (ubuntu终端的你敲的那些命令) int main(void) { ... } // 接收外部命令行参数的版本 int main(int argc, char const *argv[]) { ... }
(4)、printf函数(标准输出函数 --- 屏幕设备)
C语言被称为是一种面向过程的模块化语言,所谓的模块,指的是一个个功能明确,各司其职的封装函数,他们就像一块块积木,被合理有机地拼搭起来,形成复杂、健壮的程序。(面试题:什么是面向过程(唱歌、跳舞、吃饭、学习、玩游戏)、什么是面向对象(我唱歌、我跳舞、我吃饭、我学习、我玩游戏) ))
在这之中,系统标准C语言提供了非常多的"模块",printf函数就是其中之一,它的功能就是:向终端输出一段指定格式的数据
// 向终端输出一段字符串
printf("Hello World!\n");
- 示例:格式输出控制符
// 格式化输出函数
printf();
// 根据需要输出不同格式的数据
printf("%d\n", 100); // 输出1个整数
printf("%d, %d\n", 100, 200); // 输出2个整数
printf("%f\n", 3.14); // 输出浮点数
printf("%c\n", 'x'); // 输出字符
printf("%s\n", "abcd"); // 输出字符串
printf("string = %s\n", "abcd"); // 输出字符串
- 图解:
语法点:
- 类似 %d、%f 被称为格式控制符
- 一个格式控制符对应一个数据
- ‘\n’ 是一个字符,表示回车符,详细参阅 ASCII 码表。
gec@ubuntu:~$ man ascii
- 格式控制符:
a.十进制整数: %d
b.八进制整数: %o
c.十六进制整数: %x
d.字符: %c
e.字符串: %s
f.单精度浮点数: %f
g.双精度浮点数: %lf
h.长双精度浮点数: %Lf
i.地址: %p
- 示例代码:
#include <stdio.h>
int main(int argc, char const *argv[])
{
int num = 100; // 定义了一个整形类型的叫num的变量,并给其赋值为100这个数
char buf[128] = "shijienameda,woxiangqukankan"; // 定义了一个char型数组,该数组的空间内存为128个字节大小,里面存放了这些个字符
float f1 = 3.14; // 定义了一个float型的叫f1的变量,并给其赋值为3.14
// 1、没有格式控制符的函数
printf("hello world!\n");
// 2、打印十进制数
printf("十进制数 == %d\n", num); // 要求打印num这个变量的时候,使用十进制表示
// 3、打印八进制数
printf("八进制数 == %o\n", num); // 要求打印num这个变量的时候,使用八进制表示
// 4、打印十六进制数
printf("十六进制数 == %x\n", num); // 要求打印num这个变量的时候,使用十六进制表示
// 5、打印字符(本质上是一个整型数(1个字节))
printf("字符 == %c\n", num); // 要求打印num这个变量的时候,使用字符表示
/*
一开始计算机中没有固定的数据(0101 ....)来表示字符(abcdeef!@#$%^&*)
所以后面定了一个标准:ASCII表(这个表描述了相关的字符(128个字符),对应的数据就是(0-127))
*/
// 6、打印字符串
printf("字符串 == %s\n", buf); // 要求打印buf这个变量的时候,使用字符串表示
/*
问题:
如果以字符串形式打印num的值,printf("字符串 == %s\n", num);,会出现一下问题
warning: format ‘%s’ expects argument of type ‘char *’, but argument 2 has type ‘int’ [-Wformat=]
原因:
类型不匹配
*/
// 7、打印小数(浮点型)
printf("小数(浮点型) == %f\n", f1); // 要求打印f1这个变量的时候,使用浮点型来表示
// 8、打印地址
printf("num == %p\n", &num); // &:取地址符号,意思是获取num这个变量的地址
/*
printf("num == %p\n", num);
输出为:0x64(这个是值,不是地址,只不过以十六进制表示出来而已)
printf("num == %p\n", &num);
输出为:0x7fff27e25ce8(这个是地址,以十六进制表示)
*/
return 0;
}
(5). return语句
C语言中的关键字 return 的含义是结束一个函数,并返回某个数据(若有)。而具体到 main 函数中时,由于主函数 main 的结束同时也意味着整个程序的结束,因此在上述 Hello World 程序中 return 后整个程序就退出了
int main(void)
{
... ...
// 一般而言,函数正常退出返回0,非正常退出返回非0
return 0;
}
一般而言,程序正常退出时,main函数返回值是0;当程序异常退出时,main函数返回值是非0。
注意,main函数的返回值是给上一级进程的,因此理论上讲在当前的单进程程序中,main函数的返回值究竟是多少都无所谓,因为根本没有去使用这个返回值,除非在多进程程序中,进程间才需要使用main函数的返回值来传递信息。
二、代码风格规范(建议趋近于ST公司)
(1)、标识符命名规则(变量名、函数名、宏定义等)
1、只能包含数字、字母以及下划线,不能包含其他任何特殊字符
2、只能以字母或者下划线开头
3、不能跟系统已有的关键字重名,也不能够跟本命名空间(namespace)中具有相同作用域的其它标识符重名
4、尽量作用一望便知,做到顾名思义,避免使用无意义的字符
- 示例代码:
#include <stdio.h>
int main(int argc, char const *argv[])
{
// 一、标识符命名规则(变量名、函数名等)
// 1、只能包含数字、字母以及下划线,不能包含其他任何特殊字符
int _give_you_little_color_to_see_see_666 = 100; // 可以
// int aaa_111_&&&_**** = 200; // 不可以,有特殊字符
// 2、只能以字母或者下划线开头
int _______nihao = 100; // 可以
int shijie______ = 200; // 可以
// int 111____nihao = 300; // 不可以,数字开头了
// 3、不能跟系统已有的关键字重名,也不能够跟本命名空间(namespace)中具有相同作用域的其它标识符重名
// int extern = 100; // 不可以,跟系统已有的关键字重名了
int num = 200; // 可以
// int num = 300; // 不可以,不能够跟本命名空间(就是在同一层{}中)中具有相同作用域的其它标识符重名
int tmp = 400; // 可以(这个tmp变量的命名空间(作用域):main函数的花括号{}范围内)
{
int tmp = 500; // 凡是被花括号{}括起来的变量,其拥有了另外的命名空间
} // 可以,因为现在这个tmp变量的作用域和上面tmp变量的作用域不同(这个tmp变量的作用域范围在:20行到22行)
// 4、尽量作用一望便知,做到顾名思义,避免使用无意义的字符
int a; // 可以,但是不建议这么写,因为没有具体含义
int b;
// aaa();
int long_time_no_see; // 可以,只要能够让人望文生义即可(不管是不是正统英文)(推荐)
int fanggongnizhenshuai; // 方工的想法:方工你真帅; 别人的想法:方工的你真衰(拼音会容易出现歧义);
// 拼音的解决方法(科大讯飞);// fang(1)gong(1)ni(3)zhen(1)shuai(4)
// 推荐的命名方法(强烈推荐,模仿ST公司的命名)
// A、函数的命名方法:
// 1、驼峰命名法: FangHuiQing // 面向对象的开发的时候会比较多的去使用
// 2、下划线命名法:fang_hui_qing // 面向过程的开发的时候会比较多的去使用
// 3、二合一法: FANG_HuiQing // LED_OpenDev(); LED_CloseDev; LED_CtlDev(); // 前面的命名表示文件(led.c和led.h),后面的名字表示函数的功能作用
// B、变量名的命名方法:
// 下划线命名法(小写):int led_num; int led_flag; int led_count; // 前面的名字表示哪个文件或者哪个功能的,后面的名字就可以知道这个变量的作用
// C、宏定义
// 下划线命名法(大写):#define LED_ON 1 #define LED_OFF 1 // 前面的名字表示哪个文件或者哪个功能的,后面的名字就可以知道这个变量的作用
return 0;
}
(2)、缩进:凡是有代码块的地方都必须缩进,一个花括号{}就代表一个代码块
#include <stdio.h>
#define LED_ON 1
#define LED_OFF 0
// 普通函数
void LED_CtlDev(int led_status)
{
if(led_status == LED_ON)
printf("led_on........\n");
else
printf("led_off........\n");
}
// 主函数
int main(int argc, char const *argv[])
{
// 1、for循环
for (int i = 0; i < 100; i++)
{
/* code */ // 这里语句需要缩进
}
// 2、while循环
while (1)
{
/* code */ // 这里语句需要缩进
}
// 3、if判断的时候
int flag = 0;
if (flag == 0)
{
/* code */ // 这里语句需要缩进
}
// 4、函数
LED_CtlDev(LED_ON);
}
(3)、空格:标点符号后面,一般加空格
#include <stdio.h>
// 主函数
int main(int argc, char const *argv[])
{
int n1 = 100;
int n2 = 200;
int n3 = 300;
printf("n1 == %d, n2 == %d, n3 == %d\n", n1, n2 , n3);
}
(4)、排版
让代码整体往左移:选择代码块+shift键+tab键
让代码整体往右移:选择代码块+tab键
注释/解除注释:选择代码块+ctrl键+/键
注意:程序是写给人看的,一定要在写程序的时候添加必要的注释,养成良好的编程习惯(潜规则)
更多推荐
所有评论(0)