C语言基础(1)

前言

C语言特点

  1. 基础性的语言
  2. 语法简洁、紧凑、方便、灵活
  3. 运算符丰富,数据结构丰富
  4. 结构化、模块化编程
  5. 移植性号,执行效率高
  6. 允许直接对硬件操作

C语言学习要点:

  • 概念的正确性
  • 动手能力
  • 阅读优秀的程序段
  • 大量练习,面试题

C语言讲解流程

  1. 基本概念
  2. 数据类型,运算符和表达式
  3. 输入输出专题
  4. 流程控制
  5. 数组
  6. 指针
  7. 函数
  8. 构造类型
  9. 动态内存管理
  10. 调试工具和调试技巧(gdb,make)
  11. 常用库函数(提前封装好的工具函数)

使用平台

64位Redhat6、编辑器vim、编译器gcc(make)

gcc、vim

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
//头文件的包含
#include <stdio.h>//printf在stdio库当中
#include <stdlib.h>//exit在stdlib库当中

/*
void main(void)//不传参
void main(int argc,char **argv)//char *argv[]
int main(int argc,char **argv)
*/

int main()
{
/*\n表示换行,也表示刷新缓冲区*/
printf("hello world!\n");
exit(0);
}

C源文件处理过程

C源文件→预处理→编译→汇编→链接→可执行文件

编译工具:gcc

编写程序思路要求

  1. 头文件正确的重要性
  2. 以函数位单位来进行程序编写

第一个c程序

1
2
3
4
5
6
7
#include <stdio.h>

int main()
{
printf("hello world!\n");
return 0;
}

输出:

​ hello world!

Linux下C程序执行过程

在Linux下使用gcc命令来对.c文件进行编译,如果不对编译生成的文件重命名,默认会编译生成a.out文件,这个时候使用./就可以运行编译后的文件。

C语言数据类型

C语言包含的数据类型如下图:

C语言数据类型

基本数据类型

基本数据类型

有符号和无符号看这里>>>>>>>>>>>>

整型

对于整型数据类型有三种形式:十进制八进制十六进制,从名称上我们可以看出各个进制的区别,十进制和八进制比较明显,十六进制是从0~9后再从A~F。我们需要了解进制间的相互转换

反码和补码知识补充

字符类型——ASCII表

img

简单归纳:

ASCII码使用指定的7位或8位二进制数组合来表示128或256种字符。标准的或说基础的ASCII表是由7位二进制数组合而成的(剩下一位为0),表示符号0~127。

后128位为扩展ASCII码,不同编码方式中,0~127表示的符号是一样的,128~255表示的符号不一样。比如:130在法语编码中代表了é,在希伯来语编码中却代表了字母Gimel (ג)。

0~31及127(共33个)是控制字符或通信专用字符,为控制码。

需要对于典型的ASCII码敏感

  • 32为空格码。
  • 33~126(共94个)为形象码。
  • 48~57为0到9十个阿拉伯数字。
  • 65~90为26个大写英文字母。
  • 97~122为26个小写英文字母。

原文链接:https://blog.csdn.net/ARTisboom/article/details/122694847

其中0代表NULL,我们后面会用到空洞文件,文件中一部分充斥着ASCII码为0的空字符。字符串最后有尾0做为特殊标记,其中尾0就是ASCII为0的特殊字符。

特殊类型

bool类型在上面类型图上没有显示,false为0,true为1。

float类型的特殊性

1
2
3
4
5
6
7
8
9
int func(float f)
{
if(f < 0)
return -1;
else if(f == 0) #错误
return 0;
else
return 1;
}

由于由于计算机二进制表示浮点数有精度的问题,0形式的浮点数实际上不是0,而是非常接近零的小数,所以float f == 0是永远不会成立的。

如果我们需要在程序中使用,可以通过float类型精确到小数点后六位的特性,通过`if(fabs(f - 0) <= 1e-6)`来判断是否为0

不同形式的0值

0 代表 数字0, 若把 数字0 赋值给 某个字符,对应ASCII码值为 0x00(也就是十进制0)

'0' 代表 字符0 ,对应ASCII码值为 0x30 (也就是十进制 48)

"0" 代表 一个字符串, 字符串中含有 2个字符,分别是 ‘0’ 和 ‘\0’

'\0' 代表 空字符(转义字符)【输出为空】, 对应ASCII码值为 0x00(也就是十进制 0), 用作字符串结束符

注意:数据类型和后续代码中所使用的输入输出相匹配防止自相矛盾

常量与变量

常量:在程序执行过程中值不会发生变化的量,分为整型常量、实型常量、字符常量、字符串常量、标识常量

  • 整型常量:就是整数。
  • 实型常量:又称实数或浮点数。
  • 字符常量:由单引号引起的单个字符或转义字符。

  • 字符串常量:由双引号引起的一个或多个字符组成的序列。""特殊情况代表没有有效字符只有一个尾0,占一个字符
  • 标识常量:#define

#define

看这里>>>>>>>>>

在C语言程序中,如果有一个值我们需要反复用到,还需要根据我们的需求产生变化,还希望它能够一改全改,我们就可以使用标识常量#define实现。

除了可以用 #define 定义一个标识符来表示一个常量,还可以用 #define 定义函数,例如:

1
2
3
4
5
6
7
8
//定义常量
#define MAX_VALUE 100 //定义整型变量MAX_VALUE值为100
#define USER_NAME "huge" //定义字符串变量USER_NAME值为"huge"
#define PI 3.1415926 //定义浮点数变量PI值为3.1415926

//定义函数
#define MAX(a,b) (a>b)?a:b //取两个数最大值
#define MIN(a,b) (a<b)?a:b //取两个数最小值

define定义函数

define定义不带参数的函数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define RESULT (x*x-1)


int main()
{

int x;
printf("Plase input num x = ");
scanf("%d",&x);
printf("%d\n",x);
printf("%d\n",RESULT);

return 0;

}

输出:

Plase input num x = 10 11
10
99

define定义带参数的函数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
#include <stdio.h>
#include <stdlib.h>
#include <string.h>


#define MAX(a,b) (a>b)?a:b
#define MIN(a,b) (a<b)?a:b

int main()
{

double a,b;
printf("Plase input two num:");
scanf("%lf%lf",&a,&b);
printf("Max value:%lf\n",(a,b));
printf("Min value:%lf\n",(a,b));

return 0;

}

输出:

Plase input two num:18 22
Max value:22.000000
Min value:22.000000

define定义函数陷阱

1
2
3
4
5
6
7
8
9
10
11
12
#include <stdio.h>
#include <stdlib.h>
#include <string>

#define RESULT(x) x*x

int main()
{
printf("RESULT是:%d\n",RESULT(2));
printf("RESULT是:%d\n",RESULT(2+1));
return 0;
}

输出:

RESULT是:4
RESULT是:5

这里在标识常量定义函数为x*x的情况下,我们认为正常的输出应该为:4和9。这就要在编写标识常量函数时候注意,x*x在程序中会转换为2*1+2*1,遵循算数的正常顺序。我们想要程序正常输出的话,需要标识常量#define在程序中的确使用,应该改为(x)*(x)或者使用sqrt函数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>

//#define RESULT(x) x*x
//#define RESULT(x) (x)*(x)
#define RESULT(x) pow((x),2)


int main()
{

int a = RESULT(2);
int b = RESULT(2+1);
printf("%d\n",a);
printf("%d\n",b);
// printf("%d\n",RESULT(2));
// printf("%d\n",RESULT(2+1));

return 0;

}
**对于宏定义,保险的做法是不仅应在参数两侧加括号,也应在整个字符串外加括号。**

#if注释

当想注释屏蔽掉大块代码段时,用/*…*/"做大段注释,需要防止被注释掉的代码段中有嵌套的/*…*/,一旦出现"/**/"嵌套"/**/"的情况,有可能会导致你注释掉的代码区域并不是想要的区域范围。因此用 #if 0 要比使用 /* */要方便不少。

情况一:如有一段不想要的代码,可以直接用 “ #if 0 … #endif “ 形式来注释,效果等同于”/ /“

1
2
3
4
5
#if 0

...code...

#endif

情况二:选择结构的条件编译。如果常量为真(非0),就执行程序段1,否则执行程序段2。

1
2
3
4
5
6
7
8
9
#if 常量

...code 1...

#else

...code 2...

#endif

情况三:嵌套情况。如果常量a为真(非0),就执行程序段1。当常量a为0且常量b为真时,执行程序段2;当常量a为0且常量b为0时,执行程序段3。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#if 常量a

   ...code 1...

#else

#if 常量b

   ...code 2...

#else

   ...code 3...

   #endif

#endif

变量

定义:[存储类型] 数据类型 标识符 = 值

在C语言中,所有变量必须先声明后使用。注意数据类型要和给的值类型匹配

存储类型

定义中的其他和Java没什么区别,对于存储类型有很大区别。分为四种 存储类型:auto、static、register、extern

  • auto:默认类型,自动分配空间,自动回收空间

  • register:寄存器类型,只能定义局部变量,不能定义全局变量

    只能定义局部变量,不能定义全局变量,只能定义32位大小的数据类型,如都变了就不可以,寄存器没有地址,所以寄存器变量无法打印出地址查看或使用。

    register的思想是,将register变量放在机器的寄存器中,这样可以使程序更小、执行速度更快。编译器可以忽略此选项。

  • static:静态型,自动初始化为0值或空值,static的值有继承性

  • extern:说明型,不能改变说明的值或类型

局部变量和全局变量

局部变量定义在函数内部的变量,局部变量的作用域仅限于函数内部。局部变量是在函数调用时产生,在函数执行完毕时消失。

全局变量必须定义在函数外部,且只能定义一次。在每个需要访问外部变量的函数中,必须声明相应的外部变量。

运算符

赋值运算符

赋值运算符

比较运算符

在这里插入图片描述

逻辑运算符

在这里插入图片描述

位运算符

注:左移运算符左移一位相当于乘二,其效率比乘以2的效率高。左移其右边自动补零,右移其左边补符号位

其他运算符

补充

  • 求字节数运算符:sizeof
  • 强制类型转换运算符:(类型)
  • 下标运算符:[ ]
  • 函数调用运算符:( )