①易于学习
②结构化语言
③产生高效率的程序
④可以处理底层的活动
⑤可以在多种计算机平台上编译
C语言给编写者的权限大
// 头文件
# include
// 主函数
int main()
{
//输出语句 调用printf库函数
printf("hello world!");
return 0;
}
解释:
① 第一行就是一个注释语句,可以使用多行注释/* */
②第二行就是一个预处理指令,头文件
③第四行开始到最后一行是一个标准函数,也叫主函数,C语言只能有一个main函数
④第六行是一个这输出语句使用printf函数
头文件里有我们编写程序需要的一些基本函数,如输入scanf输出printf,这些函数已经有人帮我们写好,所以只需要引入头文件来使用库函数
① 语法:
使用#include指令,头文件的引入是预处理语句
#include
#include"xxx.h"
②常用的头文件
头文件 | 变描述 |
---|---|
#include |
标准的输出头文件 |
#include |
数函数 |
#include |
字符串函数 |
#include |
时间函数 |
#include |
工具函数 |
注意:
头文件详情
①scanf 的声明
int scanf(const char *format,…)
②括号里的参数
(“<格式化字符串>”,<参量表>);
(“%d”,&a);
解释:
%d表示输入类型是一个int,还有==%c、%lf、%lld==标准化输出格式
① printf的声明
int printf(const char *format,…)
②参数
(“<格式化字符串>”,<参量表>);
(“%d\n”,&a);
解释:
\是转义符
例题1:如果有⼀个题⽬是这样的,要求你输⼊⼀个 name+(数字),然后把数字输出出来,如果学过字符串处理的同学,应该就会觉得那直接⼀个正则,或者把name去掉,然后输出,如果数字不大,我们使用scanf格式化输出
//头文件
#include
//主函数
int main() {
//定义一个a变量
int a;
//输入函数
scanf("name%d",&a);
//输出函数
printf("%d\n",a);
return 0;
}
例题2:输出一个时间08:01,有前置0,通过字符串的输出要麻烦得多,通过格式化输出
#include
//主函数
int main(){
//输出函数
printf("%02d:%02d",8,1);
return 0;
}
类型 | 存储大小 | 值的范围 |
---|---|---|
char(默认就是signed) | 1字节 | -128 ~ 127或者0 ~ 255 |
usigned char | 1字节 | 0 ~ 255 |
signed char | 1字节 | -128 ~ 127 |
int | 2或4字节 | -32768到32767或-2147483648到2147483647 |
usigned int | 2或4字节 | 0 ~ 65535 或者 0 ~ 42949967295 |
short | 2字节 | -32768 ~ 32767 |
unsigned short | 2字节 | 0 ~ 65535 |
long | 4字节 | -2147483648 ~ 2147483647 |
usigend long | 4字节 | 0 ~ 2147483647 |
long long | 8字节 | -9223372036854775808 ~ 9223372036854775807 |
类型 | 存储大小 | 值范围 | 精度 |
---|---|---|---|
float | 4字节 | 1.2E-38 ~ 3.4E+38 | 6位有效位 |
double | 8字节 | 2.3E-308 ~1.7E+308 | 15位有效位 |
long double | 16字节 | 3.4E-4932 ~1.1E+4932 | 19位有效位 |
注意:
使用sizeof 来获得一个类型或变量的大小
//头文件
#include
//主函数
int main(){
printf("%d\n",sizeof(char));
printf("%d\n",sizeof(int));
printf("%d\n",sizeof(long));
printf("%d\n",sizeof(double));
return 0;
}
①变量必须是以字母或下划线开头,不能是数字
②变量名区分大小写
③不能使用C语言关键字
④变量名中不能有空格
⑤可以使用拼音 ,但是最好不用,
实例:
//定义一个int数据类型的变量temp
int temp;
//定义一个char数据类型的数据变量str
char str;
//定义一个double数据类型的数据变量num
double num;
注意:
变量的定义就是告诉编辑器在何处创建变量的存储,以及入额创建变量的存储,变量指定一个数据类型,并包含该类型的一个或多个变量列表
//定义变量a、b、c、d四个变量都是整形
int a,b,c,d;
int e=10;
①使用关键字修饰
extern int a; //表示的其他文件以及定义过a这个变量,我们这里直接拿来使用
②函数声明
//没有返回类型的函数声明
void f(int a);
注意:
声明和定义最主要的区别就是:定义创建了对象并为此对象分配了内存,而声明并未分配内存
程序中 字节长度较高变量对字节长度较低的变量有一定的兼容性,相反则不是,因此很可能造成数据的溢出,或者是不同数据类型之间float和int,得到一个float值,想保存int值,这时候需要强制转换
#include
int main(){
float a = 1.2223;
int b = (int)a;
printf("a=%f\tb = %d\n",a,b);
return 0;
}
①左值(lvalue):指向内存位置的表达式,左值可以出现在赋值号的左边或者右边
②右值(rvalue):指的是存储在内存某些地址的数值。右值是不能对其进行赋值的表达式,也就是说,右值可以出现在赋值号的右边,但不能出现赋值好的左边
说明:
变量是左值,可以出现赋值号的左边。数值型的字面是右值,因此不能被赋值,不能出现在赋值号的左变
int a = 10;
//a就是一个指向内存的变量也就是是左值,10是存储在内存的某个地址的数值
int a = 0;
a = a + 1;
printf("%d\n",a)
程序说明:
声明一个int类型的变量a,然后再声明的时候给赋予了初值0,然后第二句让a = a +1,此时左边的a是一个变量(lvalue)右边a的值加1,也就是右边整个构成(rvalue)
注意此数值常量非彼数值,我们此处所说的常量是单纯的一个值,如3是一个整形常量,0.3就是一个浮点常量,'c’字符常量 ,"ccc"字符串常量,一般数值常量用来初始化,这种常量不易维护。,⽐如说我们在⼀个程序
的很多地⽅都⽤了同⼀个常量那么如果你想修改这个常量的值,可能会⼀个⼀个的替换,有的同学可能想到了直接⽂件全局替换,但是这样做是有⻛险的,⽐如我的常量为1,我想把它替换为2,但是我可能有⼀些其他的常量是1开头的,⽐如12,那么就会造成数据紊乱,甚⾄有些变量⾥⾯也包含了1那么可能会导致编译出错,再退⼀步讲,编译没问题,程序的运⾏结果也不会和预期⼀样
//xxx都会被替换为yyy
#define xxx yyy
//x表示一个常量,它值为value是10
#define x 10
#define max(a,b) (a>b?a:b)
//定义一个常量,a值为10
const int a = 10;
const int *a=10;//内容不可变
int a=10;
int* const b = &a;
解释:
此时const修饰的是指针,那么指针指向的地址不可变,也就是b指向的地址不能变,但是*b可变
int a = 10;
const int* const b = &a;
范围局部,一般不用管
生命周期是整个程序从开始到结束,但是它的作用域只是局部
#include
void f() {
static int a = 0;
a++;
printf("%d\n",a);
}
int main()
{
for(int i = 0;i < 5; ++i) {
f();
}
return 0;
}
以上代码使用gcc编译会报错:error: ‘for’ loop initial declarations are only allowed in C99 mode
note: use option -std=c99 or -std=gnu99 to compile your code
正确代码:
#include
void fun(){
static int a=0;
a++;
printf("%d\n",a);
}
int main()
{
int i;
for( i = 0;i < 5; i++){
fun();
}
return 0;
}
**用来定义存储在寄存器中而不是RAM中的局部变量。这意味着最大尺寸等于寄存器的大小(通常是一个词),且能对它应用一元的“&”运算符(因为它没有内存位置)
用于提供一个全局变量的引用,全局变量对所有的程序文件都可见的当使用extern时,对于无法初始化的变量,会把变量名指向一个之前定义过的存储位置
当您有多个⽂件且定义了⼀个可以在其他⽂件中使⽤的全局变量或函数时,可以在其他⽂件中使⽤ extern 来得到已定义的变量或函数的引⽤。可以这么理解,extern 是⽤来在另⼀个⽂件中声明⼀个全局变量或函数。
总结⼀句话extern就是为了在多⽂件编程的时候直接取另外
⼀个⽂件的变量
关于extern,其实初学
运算符 | 描述 | 实例 |
---|---|---|
+ | 对两个数进行相加 | a=1+2 =>3 |
- | 相减 | a=2-1 =>1 |
* | 相乘 | a=2*2 =>4 |
/ | 相除 | a=10/2 |
% | 趋于 | a= 10%3 |
++ | 变量自增1 | a=0;++a =>1 |
- - | 变量自减 | a=0;- -a =>a = -1 |
运算符 | 描述 |
---|---|
== | 检查两个操作数的值相等,相等为真 |
!= | 检查两个操作数是否相等,不相等为真 |
> | 左操作数大于右操作数,为真 |
< | 左操作数小于右操作数,为真 |
>= | 左操作数大于等于右操作数,为真 |
<= | 左操作小于等于右操作数,为真 |
运算符 | 描述 |
---|---|
&& | 如果两个操作数都非零,为真 |
“双竖线” | 两个操作数任意一个非零,为真 |
! | 非运算符,取反 |
以下的运算都是将数转化为二进制在计算,然后再转化为相应的进制
运算符 | 描述 | 实例 |
---|---|---|
& | 与运算,全一则一,否则为零 | 3 & 6 = 2 |
“单竖线” | 或运算,有一则一,否则为零 | 3 & 6 = 7 |
^ | 异或运算,不同唯一,相同为零 | 3 ^ 4 = 7 |
~ | 取反运算,零一颠倒 | ~4 = 3 |
<< | 左移运算,效果等价十进制中乘2的n次方 | 5<<1 = 10 |
>> | 右移运算,效果等价十进制中除2的n次方 | 5>>1 = 2 |
运算符 | 描述 | 实例 |
---|---|---|
sizeof | 变量的大小 | sizeof(a)将返回4,其中a为整数 |
& | 返回变量的地址 | &a;将给出变量的实际地址 |
* | 指向一个变量 | *a;将指向一个变量 |
?: | 条件表达式 | 如果条件为真?则值为x:否则值为y |
类别 | 运算符 | 结合性 |
---|---|---|
后缀 | ()、[ ]、-> 、++ 、- - | 从左到右 |
一元 | +、-、!、++、 - -、(type)*、&、sizeof | 从右到左 |
乘除 | *、/ 、% | 从左到右 |
加减 | +、- | 从左到右 |
移位 | <<、>> | 从左到右 |
关系 | <、<=、>、>=、 | 从左到右 |
相等 | == 、!= | 从左到右 |
位与and | & | 从左到右 |
位异或XOR | ^ | 从左到右 |
位或or | 竖线 | 从左到右 |
逻辑与and | && | 从左到右 |
逻辑或or | 双竖线 | 从左到右 |
条件 | ?: | 从左到右 |
赋值 | =、+=、-=、*=、/=、%=>>=、<<= 、&=、^=、\竖线= | 从左到右 |
逗号 | , | 从左到右 |
#include
int main(){
int a=10;
if(a > 10){
printf("yes");
}
else{
printf("no");
}
return 0;
}
多条件:
if(xxx) {
}
else if(xxx) {
}
else {
}
action ? ans1:and2;
用if实现
if(action){
ans1;
}
else {
ans2;
}
解释:
action表示逻辑判断值,ans1就表示判断为真执行的操作,ans2判断为假执行的操作
①for循环的组成
初始化,条件判断,迭代更新,逻辑操作语句
②语法结构
for(初始化语句;条件判断;迭代更新){
逻辑操作语句;
}
代码实例:
#include
int main(){
int a=1;
int i,n;
scanf("%d",&n);
for(i = 0;i<n;i++){
if (a%2 == 1){
a++;
}
else {
a=a;
}
}
printf("%d\n",a);
return 0;
}
while(条件判断){
逻辑判断语句;
}
代码实例:
int i = 0;
while(++i<10){
//pass
}
解释:
当条件不满足时跳出循环,判断为真继续循环,条件判断为假就跳出循环
do……while在结构上也只有条件判断和逻辑操作
①语法结构
do{
逻辑判断语句;
}while(条件判断)
解释:
先进行一次操作,然后再判断是否继续循环
例子:
在一个文件中读取数据的时候,什么时候才算读完呢?一般的话文件会有一个结束符(EOF),那么使用do……while结构,先读,读完后判断是否是文件结束符,如果不是的话就继续循环
①循环嵌套
二层循环简单举例:
#incude<stdio.h>
int main(){
int n;
int i,j
for(i=0;i<n;++i){
for(j=0;j<n;++i){
//op
}
}
return 0;
}
②死循环
根据需求设置循环,大部分情况下我们应该避免死循环,出现死循环我们应该好好检查循环处的代码
③break和continue
两者都是跳出循环,break跳出整个剩下的循环,而continue只跳出当前循环,也就是说后面的循环,继续执行操作
④goto(一般不用)
#include
int main(){
int i,j,k;
for(i = 0;i < 10; ++i) {
for(j = 0;j < 10; ++j) {
for( k = 0;k < 10; ++k) {
if(i + j + k == 12) {
goto out;//我们找到我们想要的第一个答案就直接goto跳出三层循环,这个out只是一个代名词,随意更改,不过要和下面对应上
}
}
}
}
out://跳出的地方
printf("YES");
return 0;
}
数组就是存储一个固定大小的相同类型元素的顺序集合,注意这个集合里面的元素类型都是一样的,我们可以通过数组名+下标的方式访问我们存储的数据
####(1)声明数组
①语法:数组类型+数组名+数组大小
②代码
int a[10];
解释:
声明一个10个int数据大小的数组,一个int 4个字节,那么这个数组要占40个字节,其他类型char、double或者结构体类型都可以这样声明
int a[3]={0,1,2};
int b[3]={0};
解释:
a数组的三个位置初始化0、1、2,b数组全部舒适化为0,如果定义的是全局数组,那么它会自动给你初始化为0,但是局部,不初始化们就会给你一个随机值
//函数的声明
void *memset(void *str,int c,size_t n)
解释:
第一个传的参数是一个void类型指针,也就是任何数据类型都可以,第二个是int类型的,也就是初始化的值,第三个参数是长度,也就是要初始化的字节数
举例:
#include
#include
int a[10];
int main(){
memset(a,-1,sizeof a);
printf("%d\n",a[0]);
printf("%d\n",-1);
return 0;
}
②循环初始化
#include
#include
int a[10];
int main(){
int i;
for(i=0;i<10;++i){
a[i]=i;
}
printf("%d\n",a[1]);
return 0;
}
定义变量,我们一般是写在main的大括号里,当main函数运行完成后就会失效,一般来说体会不是很明显,因此我们就只使用main函数。
函数是完成程序中一部分小功能的子程序,或者说将一段完成一个任务的语句的一个整合
(modified_type) return_type
function_name(paramter list){
//function action
}
解释:
satic修饰函数表示只在本文件访问,被其修饰的函数也成为内部函数,extern修饰的函数可以在别的文件中调用,被其修饰的函数成为外部函数,inline表示内敛函数,内联拓展是用来消除函数调用时的时间开销。通常用于频繁执行的函数,对于小内存空间的函数非常受益
注意:
①递归函数不能定义为内联函数
②内联函数一般适合于不存在while和switch等复杂的结构且只有1~5条语句的小函数上,否则编译系统将该函数视为普通函数。
③内联函数只能先定义后使用,否则编译系统会把它认为是普通函数
④对于内联函数不能进行异常的接口声明
int function(int a,int b);
int function(int ,int);
上面两种声明是等价的,我们在声明的时候其实没必要给出形参的名字,我们只需要明确给出数据类型以及函数的返回类型即可。
举例:
#include
int function(int a, int b) {
int c = a + b;
printf("%d\n", c);
return c;
}
int main() {
function(12, 3);
return 0;
}
以上是有返回值的情况,如果不需要返回值那么定义viod类型即可
简单来说就是存储地址的变量或常量
数据类型 * 指针名
//举例
//指针类型为int * 指针指向的类型是int
int *a;
//指针类型为char * 指针指向的类型是char
char *b;
// 指针类型为float * 指针指向的类型是float
float *c;
注意:
指针类型和指针指向的类型是不同的
代码举例:
#include
void MySwap(int a, int b) {
int temp = b;
b = a;
a = temp;
printf("%d %d\n", a, b);
}
int main() {
int a = 0, b = 10;
printf("%d %d\n", a, b);
MySwap(a, b);
printf("%d %d\n", a, b);
return 0;
}
#include
void MySwap(int *a, int *b) {
int temp = *b;
*b = *a;
*a = temp;
//printf("%d %d\n", a, b);
}
int main() {
int a = 0, b = 10;
printf("%d %d\n", a, b);
MySwap(&a, &b);
printf("%d %d\n", a, b);
return 0;
}
①函数的声明
②样例
③注意