C语言笔记(一)

一、第一个程序

1.1编译型语言和解释型语言区别

在这里插入图片描述
C 语言是编译型语言,源代码最终编译成机器语言,也就是我们所说的可执行文件,从此 CPU 就可以直接执行。
除了编译型语言,时下很流行的还有解释型语言,像 JAVA,Python,Ruby 这类都是解释型语言。解释型语言不直接编译成机器码,而是将源码转换成中间代码,然后发送给解释器,由解释器逐句翻译给 CPU 来执行。这样做的一个好处就是可以实现跨平台的特性,而缺点就是效率相对要低一些,因为每执行一次都要翻译一次。

二、打印

使用 GCC 编译程序:gcc 源代码 -o 可执行文件

2.1、printf 是格式化输出函数

C 语言为我们提供了很多基本函数,它们用于实现不同的功能,比如 printf 函数,就是实现格式化输出的功能。没有它,我们压根儿不可能仅用六行代码,就将文本打印到屏幕上。

2.2、转义字符

转义字符一般是表示特殊含义的非可见字符,以反斜杠开头:
在这里插入图片描述

2.3、反斜杠使用细节

反斜杠如果后边不带任何字符(直接换行),表示我们希望 C 语言将该行以及下一行看做是一个整体。

#in\
clude \
<stdio.h>

int ma\
in()
{
        print\
f("Hello World!\n");
        return \
0;
}

这个方法主要用在当你的字符串或语句太长(一行不足以存放,或严重影响阅读),那么你可以通过反斜杠(\)进行“断行”。

2.4、Vim使用技巧

在 VIM 的普通模式下,点(.)操作表示重复上一次的修改。:

1、先输入大写字母 A 在行尾进行插入模式
2、然后输入 \n\,点击 Esc 回到普通模式
3、点击字母 j 将光标移动到下一行
4、按一下点(.),VIM 将自动实现上方 1 和 2 的操作(即在行尾插入 \n\)
5、接下来我只需要重复点击字母 j + 点(.)即可

三、变量

3.1、C 语言变量命名需要遵守的规范

  • C语言变量名只能是英文字母(A-Z,a-z)和数字(0-9)或者下划线(_)组成,其他特殊字母不行。下横线通常用于连接一个比较长的变量名,比如i_love_fishC
  • 第一个字母必须是由英文字母或者下划线开头,也就是不能用数字开头。
  • 变量名区分大小写。因为C语言是大小写敏感的编程语言,也就是大写的FISHC跟小写的fishc会被认为是不同的两个名字。在传统的命名习惯中,我们用小写字母来命名变量,用大写字母来表示符号常量名。
  • 不能使用关键字来命名变量。

3.2、关键字

关键字就是 C 语言内部使用的名字,这些名字都具有特殊的含义
在这里插入图片描述

3.3、C 语言常用的基本数据类型

  • char —— 字符型,占用一个字节
  • int —— 整型,通常反映了所用机器中整数的最自然长度
  • float —— 单精度浮点型
  • double —— 双精度浮点型

3.4、C 语言声明变量的语法

  • int a; // 在内存中找到一个整型大小的位置,然后霸占起来,并给它命名叫 a
  • char b; //在内存中找到一个字节大小的位置,然后霸占起来,并给它命名叫 b
  • float c; //在内存中找到一个单精度浮点型数据大小的位置,然后霸占起来,并给它命名叫 c
  • double d; //在内存中找到一个双精度浮点型数据大小的位置,然后霸占起来,并给它命名叫 d

3.5、编译并运行程序

gcc test.c -o test && ./test
在这里插入图片描述
11代表数据总占宽度

四、常量和宏定义

4.1、C语言常见的常量

  • 整型常量:520, 1314, 123
  • 实型常量:3.14, 5.12, 8.97-
  • 字符常量
    • 普通字符:‘L’, ‘o’, ‘v’, ‘e’
    • 转义字符:‘\n’, ‘\t’, ‘\b’
  • 字符串常量:“FishC”
  • 符号常量:使用之前必须先定义

4.2、定义符号常量

符号常量的定义格式是:

#define 标识符 常量

其中这个 #define 是一条预处理命令(预处理命令都以"#"开头),我们也称为宏定义命令。它的功能就是把程序中所有出现的标识符都替换为随后的常量。

#include <stdio.h>

#define URL "http://www.fishc.com"
#define NAME "鱼C工作室"
#define BOSS "小甲鱼"
#define YEAR 2010
#define MONTH 5
#define DAY 20

int main()
{
        printf("%s成立于%d年%d月%d日\n", NAME, YEAR, MONTH, DAY);
        printf("%s是%s创立的……\n", NAME, BOSS);
        printf("%s的域名是%s\n", NAME, URL);

        return 0;
}

4.3、标识符

在 C 语言中,标识符指的就是一切的名字。比如刚刚的符号常量名是标识符,变量名也是一个标识符。以及我们即将学到的函数、数组、自定义类型这些的名字都称之为标识符。

4.4、字符串常量

C 语言用一个特殊的转义字符来表示字符串的结束位置。这样当操作系统读取到这个转移字符的时候,就知道该字符串到此为止了。

这个转义字符就是空字符:‘\0’

五、数据类型

5.1、数据类型

在 C 语言里,所谓的数据类型就是坑的大小。我们说变量就是在内存里边挖一个坑,然后给这个坑命名。那么数据类型指的就是这个坑的尺寸。C 语言允许使用的类型如下:
在这里插入图片描述

5.2、short 和 long

我们可以为这些基本数据类型加上一些限定符,比如表示长度的 short 和 long。比如 int 经过限定符修饰之后,可以是 short int,long int,还可以是 long long int(这个是 C99 新增加的)。
在这里插入图片描述
这里 C 语言并没有限制 int 的坑具体要挖多大,short int 或 long int 的坑又要挖多大。标准只是要求:short int <= int <= long int <= long long int。

5.3、sizeof 运算符

sizeof用于获得数据类型或表达式的长度,它有三种使用方式:

  • sizeof(type_name); //sizeof(类型);
  • sizeof(object); //sizeof(对象);
  • sizeof object; //sizeof 对象;

5.4、signed 和 unsigned

signed 和 unsigned,它们用于限定 char 类型和任何整型变量的取值范围。
signed 表示该变量是带符号位的,而 unsigned 表示该变量是不带符号位的。带符号位的变量可以表示负数,而不带符号位的变量只能表示正数,它的存储空间也就相应扩大一倍,unsigned整型变量能存储的最大值为signed整型变量能够存储的最大正数的两倍。默认所有的整型变量都是 signed 的,也就是带符号位的。
因此加上 signed 和 unsigned 限定符,四种整型就变成了八种:

  • [signed] short [int]
  • unsigned short [int]
  • [signed] int
  • unsigned int
  • [signed] long [int]
  • unsigned long [int]
  • [signed] long long [int]
  • unsigned long long [int]

六、取值范围

6.1、比特位和字节

CPU 能读懂的最小单位(只能存放0和1)——比特位,bit,b

内存机构的最小寻址单位——字节,Byte,B

关系:1Byte == 8bit
在这里插入图片描述
因此,一个字节可以表示最大的数是:11111111

6.2、二进制、十进制和十六进制

在这里插入图片描述

6.2.1、进制转换

不难发现,它们之间是有规律可循的。
比如 11(2)== 2^2 - 1(10);111(2)== 2^3 - 1(10);1111(2)== 2^4 - 1(10);1111 1111(2)== 2^8 - 1(10)

又比如 1111(2)== F(16),1111 1111(2)== FF(16)

注1:小括号中的数字表示进制数,即(2)是二进制的意思。

注2:脱字符( ^ )表示幂(次方)的意思,3^2 即 3 的 2 次幂(方)。

比如你看到二进制数 111111,立刻就知道对应的十进制数是 2^6-1,即 2 * 2 * 2 * 2 * 2 * 2 - 1 == 63

调试程序的时候调试器总会将内存中的二进制数转换为十六进制 —— 因为恰好 8 位二进制数(一个字节)用 2 位十六进制数即可表示,非常节约空间。

6.2.2、二进制数和十进制数之间的相互转换

二进制 -> 十进制

从二进制数转换到十进制数,我们使用“按权相加”的方法。
所谓“权”,即“位权”!
比如说一个八位的二进制数 0010 1010,从右往左(←),每个位的“位权”依次是 01234567,如下图所示:
在这里插入图片描述

  • 公式
    十进制数 == 依次将每个二进制位的值 * 2的位权次方再相加
    上边的二进制数 0010 1010 转换成十进制数就是:
    0 * 2^7 + 0 * 2^6 + 1 * 2^5 + 0 * 2^4 + 1 * 2^3 + 0 * 2^2 + 1 * 2^1 + 0 * 2 ^0
    == 0 * 128 + 0 * 64 + 1 * 32 + 0 * 16 + 1 * 8 + 0 * 4 + 1 * 2 + 0 * 1
    == 42

二进制(补码)-> 十进制

上边的转换是对于无符号数来说的,如果万一摊上一有符号数,就比较麻烦。

对于有符号数(补码)来说:

如果符号位为 0,表示该数为正数,转换跟无符号数没什么两样。

如果符号位为 1,表示该数为负数,此时符号位的位权不变,但该位的权值应该乘以 -1 得到。

将有符号数 0011 1100 转换成十进制数:
0 * 2^7 + 0 * 2^6 + 1 * 2^5 + 1 * 2^4 + 1 * 2^3 + 1 * 2^2 + 0 * 2^1 + 0 * 2^0

== 32 + 16 + 8 + 4

== 60
然后如果符号位为 1,表示这是一个负数,比如 1011 1100,那么符号位的权值就应该乘以 -1 得到:
-1 * 2^7 + 0 * 2^6 + 1 * 2^5 + 1 * 2^4 + 1 * 2^3 + 1 * 2^2 + 0 * 2^1 + 0 * 2^0

== -128 + 32 + 16 + 8 + 4

== -68

十进制 -> 二进制
从十进制数转换到二进制数,我们使用“辗转相除”的方法。不过我们这里不是要求最大公约数,而是取其余数。
即将待转换的十进制数不断地除以 2,直到商为 0,将每次除得的余数倒序拼凑起来,便是对应的二进制数
在这里插入图片描述

6.2.3、二进制数和十六进制数之间的相互转换

二进制和十六进制之间有着密不可分的暧昧关系,你只需要记住下边这个表格即可:
在这里插入图片描述
一旦遇到很多二进制数,你就从右往左,每四个为一组,查上表,就是把每个十六进制数拆解成 4 位二进制数。

6.3、符号位

存放 signed 类型的存储单元中,左边第一位表示符号位。如果该位为 0,表示该整数是一个正数;如果该位为 1,表示该整数是一个负数。

一个 32 位的整型变量,除去左边第一位符号位,剩下表示值的只有 31 个比特位。

6.4、补码

计算机是用补码的形式来存放整数的值。

正数的补码是该数的二进制形式。

  • 负数的补码需要通过以下几步获得:
    1、先取得该数的绝对值的二进制形式
    2、再将第1步的值按位取反
    3、最后将第2步的值加1
    在这里插入图片描述

6.5、二进制表示最大值和最小值

在这里插入图片描述

6.6、基本数据类型的取值范围

在这里插入图片描述
在这里插入图片描述

七、字符和字符串

7.1、字符类型事实上是一个特殊的整数类型

字符类型事实上是一个特殊的整型,因此它也有取值范围,signed char 的取值范围是 -128 ~ 127;unsigned char 的取值范围是 0 ~ 255。

7.2、字符类型与普通整数类型的不同之处

C 标准规定普通整数类型默认使用 signed 修饰符,但没有规定 char 的默认修饰符。因此,使用 signed 或 unsigned 修饰符,是由编译系统自行决定。

7.3、存放在字符类型中的变量,都可以被解释为 ASCII 字符表中的对应字符

在这里插入图片描述
标准 ASCII 字符表使用7位二进制数来表示所有的大写和小写字母,数字 0 到 9、标点符号, 以及在美式英语中使用的特殊控制字符。
其中,ASCII 字符表上的数字 0 ~ 31 以及 127(共 33 个)分配给了控制字符,用于控制像打印机等一些外围设备。这些是看不到的。数字 32 ~ 126 分配给了能在键盘上找到的字符,这些是所见即所得的。

7.3、字符串

C 语言没有专门为存储字符串设计一个单独的类型,因为没必要。我们之前已经说过,字符串事实上就是一串字符。所以只需要在内存中找一块空间,然后存放一串字符类型的变量即可。
声明字符串的语法:
char 变量名[数量];

对其进行赋值,事实上就是对这一块空间里边的每一个字符变量进行赋值。我们通过索引号来获得每个字符变量的空间。
变量名[索引号] = 字符;

char name[6];

name[0] = 'F';
name[1] = 'i';
name[2] = 's';
name[3] = 'h';
name[4] = 'C',
name[5] = '\0';
char name[6] = {'F', 'i', 's', 'h', 'C', '\0'};

中括号([])里边的数量可以不写,编译器会自动帮你计算的。

char a[] = {'F', 'i', 's', 'h', 'C', '\0'};

可以直接在大括号写上字符串常量,字符串常量双引号括起来
使用字符串常量有个好处,那就是你不必亲自在末尾添加 ‘\0’,它会自动帮你加上。

char a[] = {"FishC"};

最后,如果使用字符串常量的话,这个大括号也是可以省掉的:

char a[] = "FishC";

八、算术运算符

8.1、算术运算符

C 语言通过提供大量的运算符来支持我们对数据进行处理,前边我们将一个值存放到变量中,使用的是赋值运算符,就是等于号(=),上节课对字符串中的某个字符进行索引,使用方括号([ ])作为下标运算符实现。
在这里插入图片描述

  • 注意几点
    • 因为键盘上没有乘号和除号两个按键,所以用星号(*)和斜杠(/)代替,这几乎是潜规则了。
    • 对于整数间的除法是采取直接舍弃小数部分的方式,而不是什么四舍五入噢。
    • 对于浮点数间的除法则能获得一个相对逼近结果的值(如果除不尽或位数特别多的话)。
    • 百分号(%)在这里是表示求余数的意思,但求余运算符要求两边的操作数都要是整数,其结果也是整数。

8.2、何谓“目”?

大家可能看到有些运算符后边写双目,有些写单目,那么什么是目呢?
我们把被运算符作用的运算对象称之为操作数,比如 1 + 2,那么 1 和 2 就是被加法运算符(+)作用的两个操作数。我们说一个运算符是双目运算符还是单目运算符,就是看它有多少个操作数。

8.3、表达式

用运算符和括号将操作数连接起来的式子,我们称之为表达式。

  • 1 + 1
  • ‘a’ + ‘b’
  • a + b
  • a + ‘b’ + pow(a, b) * 3 / 4 + 5

8.4、运算符的优先级和结合性

  • 优先级相同的运算符,运算次序由结合性决定。
    • 比如 3 * 4 / 5 % 6,其中乘号、除号和求余运算符在同一优先级,结合性是“左到右”,因此先计算 3 * 4,再计算 / 5,最后计算 % 6
    • 再如 -i++,符号和自增运算符在同一优先级,结合性是“右到左”,因此 -i++ 相当于 -(i++)
  • *目运算符是指操作数的个数,比如单目运算符只有一个操作数,双目运算符有两个操作数,而三目运算符则有三个操作数。
  • 通过使用小括号可以提升表达式的优先级至最高。
    • 比如 (1 + 2) * (3 - 4),其中加号、减号运算符的优先级本身是要低于乘号运算符的,但由于使用了小括号,且结合性均是“左到右”,所以先计算 (1 + 2),再计算 (3 - 4),最后才将前两者的结果相乘。
      在这里插入图片描述
      在这里插入图片描述

8.5、类型转换

当一个运算符的几个操作数类型不同时,编译器需要将它们转换为共同的某种数据类型,才能进行运算。

通常情况下,编译器会将占用坑位比较小的操作数,先转换为与坑位较大的操作数的相同类型,然后再进行运算。这样做的目的就是为了确保计算的精确度。

除了编译器帮你自动转换不同类型的操作数之外,C 语言还允许你强制转换操作数的数据类型。做法就是在操作数的前边用小括号将目标数据类型括起来。

九、关系运算符和逻辑运算符

9.1、关系运算符

在 C 语言中,使用关系运算符来比较两个数的大小关系。
在这里插入图片描述
关系运算符都是双目运算符,其结合性均为左到右。另外,关系运算符的优先级低于算术运算符,高于赋值运算符。

9.2、关系表达式

用关系运算符将两边的变量、数据或表达式连接起来,称之为关系表达式:

  • 1 < 2
  • a > b
  • a <= 1 + b
  • ‘a’ + ‘b’ <= ‘c’
  • (a = 3) > (b = 5)
    关系表达式得到的值是一个逻辑值,即判断结果为“真”或“假”,如果结果为“真”,关系表达式的值为 1,如果为“假”,关系表达式的值则为 0。

9.3、逻辑运算符

C 语言总共提供了三种逻辑运算符:
在这里插入图片描述

9.4、逻辑表达式

用逻辑运算符将两边的变量、数据或表达式连接起来,称之为逻辑表达式:

  • 3 > 1 && 1 < 2
  • 3 + 1 || 2 == 0
  • !(a + b)
  • !0 + 1 < 1 || !(3 + 4)
  • ‘a’ - ‘b’ && ‘c’

注:关系表达式和逻辑表达式得到的值都是一个逻辑值,也就是表示真的 1 和表示假的 0。但是用于判断一个值是否为真时,以 0 表示假,以任何非 0 的数表示真。一个是编译系统告诉我们的结果,一个是我们让编译系统去判断的,两者方向不同。

9.5、短路求值

短路求值又称最小化求值,是一种逻辑运算符的求值策略。只有当第一个运算数的值无法确定逻辑运算的结果时,才对第二个运算数进行求值。

C 语言对于逻辑与和逻辑或采用短路求值的方式。

#include <stdio.h>

int main()
{
        int a = 3, b = 3;

        (a = 0) && (b = 5);
        printf("a = %d, b = %d\n", a, b);

        (a = 1) || (b = 5);
        printf("a = %d, b = %d\n", a, b);

        return 0;
}

十、if语句

10.1、分支结构

if 语句几种形式

  • 第一种
…… // 其它语句
if (表达式)
{
    …… // 逻辑值为真所执行的语句、程序块
}
…… // 其它语句

第一种是最简单的,if 后边小括号内填写返回逻辑值的表达式,当然你可以直接填入一个逻辑值,当你填入这个值为非 0 的时候,编译系统就会认为这个逻辑值是真;只有当你填入 0 的时候,才被认为是假的。

  • 第二种
…… // 其它语句
if (表达式)
{
    …… // 表达式的逻辑值为真所执行的语句、程序块
}
else
{
    …… // 表达式的逻辑值为假所执行的语句、程序块
}
…… // 其它语句
  • 第三种
…… // 其它语句
if (表达式1) 
{
    …… // 表达式 1 的逻辑值为真所执行的语句、程序块
}
else if (表达式2)
{
    …… // 表达式 2 的逻辑值为真所执行的语句、程序块
}
else if (表达式3)
{
    …… // 表达式 3 的逻辑值为真所执行的语句、程序块
}
  .
  .
  .
else if (表达式n)
{
    …… // 表达式 n 的逻辑值为真所执行的语句、程序块
}
else
{
    …… // 上面所有表达式的逻辑值均为假所执行的语句、程序块
}
…… // 其它语句

p2-p11

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值