目录
一、编程语言
编程语言(programming language)可以简单的理解为一种计算机和人都能识别的语言,从而达到人与机器之间的交流和沟通。计算机最终能识别的一定只能是二进制的数据,而计算机编程语言主要包括汇编语言、机器语言以及高级语言。
同时高级语言又分为 编译型语言 和 解释型语言。
编译型语言:在程序执行之前需要有一个专门的编译过程,将我们人类能识别的语言编译成计算机能识别的二进制语言,会根据源文件生成可执行文件。例如:C C++
优点:执行之前已经完成了编译,在执行的过程中无需每次重新翻译,执行效率相对较高。
缺点:依赖于编译器,跨平台性相对较差。
解释型语言(脚本):在程序执行之前没有一个专门的编译过程,而是在程序执行的过程中,由解释器来逐条的进行翻译。例如:shell python
优点:跨平台性相对较好。
缺点:每次执行都需要解释器逐条翻译,相对来说执行效率较低。
二、C语言简介
1.C语言发展历史
C 语言是一种通用的高级语言,最初是由丹尼斯·里奇在贝尔实验室为开发 UNIX 操作系统而设计的。C 语言最开始是于 1972 年在 DEC PDP-11 计算机上被首次实现。
在 1978 年,布莱恩·柯林汉(Brian Kernighan)和丹尼斯·里奇(Dennis Ritchie)制作了 C 的第一个公开可用的描述,现在被称为 K&R 标准。
C 语言最初是用于系统开发工作,特别是组成操作系统的程序。由于 C 语言所产生的代码运行速度与汇编语言编写的代码运行速度几乎一样,所以采用 C 语言作为系统开发语言。
当今最流行的 Linux 操作系统和 RDBMS(Relational Database Management System:关系数据库管理系统) MySQL 都是使用 C 语言编写的。
由于各种原因,C 语言现在已经成为一种广泛使用的专业语言。
2.特点
(1)易于学习
(2)结构化语言
(3)它产生高效率的程序
(4)它可以处理底层的活动
(5)它可以在多种计算机平台上编译
3.C11
C11(也被称为C1X)指ISO标准ISO/IEC 9899:2011。在它之前的C语言标准为C99。----简单了解即可
三、gcc编译器
GCC(GNU Compiler Collection,GNU 编译器套装),是一套由 GNU 开发的编程语言编译器编译器就是将一种语言(一般是高级语言)翻译成另一种语言(一般是低级语言)的一个程序。
GCC 原名为 GNU C 语言编译器,因为它原本只能处理 C语言。GCC 快速演进,变得可处理 C++、Fortran、Pascal、Objective-C、Java 以及 Ada 等他语言。
我们Linux中C语言的编译器使用的是gcc。
四、编译方法
1.简单直观
gcc xxx.c 这种编译方式,会在当前路径下生成一个名字叫做 a.out 的可执行文件
使用 ./a.out 就可以执行了
2.自定义可执行文件名
gcc xxx.c -o diy //diy是我们自定义的可执行文件名,叫什么都可以
//这种方式会在当前路径下生成 我们自定义名字的可执行文件
3.根据编译步骤,分步编译
编译分为4步:预编译处理(.c) --> 编译、优化程序(.s、.asm)--> 汇编程序(.obj、.o、.a、.ko) --> 链接程序(.exe、.elf、.axf等)。
这种编译方式实际中,没有人使用,讲他的原因是想让大家知道每一步都干了什么事儿
3.1预处理
用于将头文件的展开、宏定义的替换、注释的删除(将所有的#include头文件以及宏定义替换成其真正的内容,预处理之后得到的仍然是文本文件,但文件体积会大很多,将 .c 文件转换为 .i 文件)
命令:gcc -E hello.c -o hello.i
3.2编译
用于词法分析、语法分析,是用来查错的,如果无误,会生成对应的汇编文件(对程序进行查错,若无错则将预处理之后的程序转换为特定的汇编代码 )
命令:gcc -S hello.i -o hello.s
3.3汇编
用于将汇编文件生成计算机能识别的二进制文件(汇编过程将上一步的汇编代码转成机器码,这一步产生的文件叫目标文件 ,是二进制格式。此步骤会为每一个源文件产生一个目标文件。)
命令:gcc -c hello.s -o hello.o
3.4链接
用于链接库文件,生成对应的可执行文件(链接过程将多个目标文件以及所需的库文件( .so 等)链接成最终可执行文件,将 .o 文件转换为 可执行程序。)
命令:gcc hello.o -o hq
五、hello world 程序说明
//双斜杠表示单行注释
/*
多行
注释
*/
#if 0
多行
注释
#endif
#include <stdio.h>
//#include 表示要包含头文件
//<stdio.h> 标准输入输出的头文件 printf scanf 等都是包含在 stdio.h 中的
//int 函数的返回值类型 ----先不用管
//main 主函数,是程序的入口 每个程序有且只能有一个
//()里面是main函数的参数 先不用管 不写也可以 但是 ()必须要写
//{}里面是函数体,是要执行的内容
int main(int argc, const char *argv[])
{
//printf 是标准C库中的函数 功能 是将内容输出到终端
//输出的内容要用 "" 引起来
// \n 表示换行
//C语言中每条指令结束要加一个 ;
printf("hello world\n");
//函数的返回值 先不用管
return 0;
}
六、计算机中数据的存储
计算机中数据的存储,分为 数值型数据的存储 和 非数值型数据的存储。
1.数值型数据的存储
1.1十进制
就是我们平时接触的最多的数据,写数据时不加任何前导符的默认都是十进制的。
逢10 进 1 :每一位上数据的范围 0 ~ 9
例如:176 520 1314
1.2二进制
前导符 0b
逢2 进 1:每一位上数据的范围 0 ~ 1
例如: 0b10101111 0b1101
二进制转十进制:
0b1101 = 1*2^0 + 0*2^1 + 1*2^2 + 1*2^3 = 1+0+4+8 = 13
注意:任意进制转十进制都可以采用这种方式,
只需要将底数换成对应进制的数即可
十进制转二进制:
采用除2取余法:将原数据除以2,得到商和余数,用商再除以2,
再得到新的商和余数,依次类推,知道商为0,
最后,将得到的余数按照倒序取出,就是转换成的二进制数据。
1.3八进制
前导符 0
逢8 进 1:每一位上数据的范围 0 ~ 7
例如: 0520 01314
八进制转十进制:
0521 = 1*8^0 + 2*8^1 + 5*8^2 = 1 + 16 + 320 = 337
八进制转二进制:
1.八转十 然后 十转二
2.每1位八进制数对应3位二进制数
0521 = 101010001
二进制转八进制:
从右向左,每3位二进制数对应1位八进制数,(高位不足,就补0)
0b001001101 = 115
1.4十六进制
前导符 0x
逢16 进 1:每一位上数据的范围 0 ~ 15
0 1 2 3 4 5 6 7 8 9 a b c d e f
例如: 0x32 0x5f 0xabcd
十六进制转二进制:
1111 -- 8421
1.十六转十 然后 十转二
2.每1位十六进制数对应4位二进制数
0xa8 = 10101000
二进制转十六进制:
从右向左,每4位二进制数对应1位十六进制数,(高位不足,就补0)
0b01001101 = 0x4d
注意:不管几进制的数据,计算机最终都会把它转换成二进制来处理!!!
2.示例
#include <stdio.h>
int main(int argc, const char *argv[])
{
//定义一个变量 用来存储十进制数
int a = 520;
printf("a = %d\n", a);//按照十进制输出a的值
printf("a = %#o\n", a);//按照八进制输出a的值 #表示输出前导符
printf("a = %#x\n", a);//按照十六进制输出a的值
//printf函数无法直接输出 二进制
printf("-------------------------------------------\n");
//定义一个变量 用来存储二进制数
int b = 0b11011001;
printf("b = %d\n", b);//按照十进制输出b的值
printf("b = %#o\n", b);//按照八进制输出b的值 #表示输出前导符
printf("b = %#x\n", b);//按照十六进制输出b的值
printf("-------------------------------------------\n");
//定义一个变量 用来存储八进制数
int c = 01010;
printf("c = %d\n", c);//按照十进制输出c的值
printf("c = %#o\n", c);//按照八进制输出c的值 #表示输出前导符
printf("c = %#x\n", c);//按照十六进制输出c的值
printf("-------------------------------------------\n");
//定义一个变量 用来存储八进制数
int d = 0x5F;
printf("d = %d\n", d);//按照十进制输出d的值
printf("d = %#o\n", d);//按照八进制输出d的值 #表示输出前导符
printf("d = %#x\n", d);//按照十六进制输出d的值
return 0;
}
运行结果:
3.非数值型数据的存储
计算机中只能处理二进制的数据,也就是数值型数据,但是在编程的过程中,经常会用到
那个非数值型的数据,如人名 、 性别、 企业名,所以,科学家们就发明了一种叫做ascii码
的东西,专门用来处理非数值型数据。
可以使用命令 man ascii 来查看ascii码
在C语言中,遇到任何被双引号或者单引号引起来的,都是非数值型数据
"www.4399.com" 'M' '7'
常见的字符对应的ascii码
A~Z --> 65~90
a~z --> 97~122
0~9 --> 48~57
\n --> 10
\t --> 9
\0 --> 0
转义字符:
在C语言中任意一个字符都可以用 \+一个数字(一般是八进制数) 来表示
同时,C语言中定义了一些 \+字符 来表示那些不可显示的字符
如 \n \t \0 \a 等
这些字符称之为转义字符,因为\后面的字符已经不是他本身的含义了
七、词法符号
1.关键字
char short int float double long struct union enum signed unsigned void 12
const static register volatile extern auto 6
sizeof 1
typedef 1
if else switch case default for while do goto break continue return 12
C语言是严格区分大小写的,关键字都是小写的
2.标识符
所谓的标识符,就是我们自己起的名字,如变量名、函数名等。
使用标识符时要遵循标识符的命名规范:
1.由数字、字母、下划线组成
2.不能以数字开头
3.不能和C语言的关键字冲突
4.变量名或者函数名尽量要起的有意义一些----这条是我自己加的。
八、数据类型
1.C语言的本质
操作内存。
2.内存和硬盘的区别
1.内存上的数据掉电丢失,硬盘上的数据掉电不丢失
2.内存处理数据的速度要远远高于硬盘
3.内存大小的表示
C语言中内存分配的最小单位是 字节 B
C语言编程中的最小单位是 位 bit
系统对内存的识别是以Byte(字节)为单位,每个字节由8位二进制数组成,即8bit(比特,也称“位”)。
按照计算机的二进制方式,1Byte=8bit;1KB=1024Byte;1MB=1024KB;1GB=1024MB;1TB=1024GB。
4.数据类型的作用
数据类型相当于一个模子,他能规定用他来定义的变量对应的内存空间的大小。
5.数据类型的分类
5.1基本类型
字符类型 char
整型 short int long long long
实型(小数) float double
枚举类型 enum
5.2构造类型
数组
结构体 struct
共用体 union
5.3指针类型
int *p;
char *q;
5.4空类型
void
void *
6.不同的整型能存储的数据范围
数据的存储又分为有符号(signed)的,和无符号(unsigned)的
如果不加 unsigned 特殊强调,默认都是有符号的
对于有符号数 最高位为 0 正数 最高位为 1 负数
6.1char
占用的内存空间 1字节 8bit
无符号的,存储的数据范围:0 ~ 255 : 2^8 -1
有符号的,存储的数据范围:-128 ~ 127 : - 2^7 ~ 2^7 - 1
为了解决 -0 的问题,存储是涉及到了原码、反码、补码,后面再讲
规定 10000000 是 -128
6.2short
占用的内存空间 2字节 16bit
无符号的,存储的数据范围:0 ~ 2^16-1
有符号的,存储的数据范围:- 2^15 ~ 2^15 - 1
6.3int
占用的内存空间 4字节 32bit
无符号的,存储的数据范围:0 ~ 2^32-1
有符号的,存储的数据范围:- 2^31 ~ 2^31 - 1
6.4long(long int)
在32位系统中,long和int是一样的 都是 4字节
在64位系统中,long和long long 是一样的,都是8字节
我们现在用的是64位系统
6.5long long(long long int)
占用的内存空间 8字节 64bit
无符号的,存储的数据范围:0 ~ 2^64-1
有符号的,存储的数据范围:- 2^63 ~ 2^63 - 1
7.数值型型数据的存储涉及原码反码补码的问题
原码:是给人类看的,就是原来的值
反码:用来做原码和补码转换的
补码:是给计算机看的,计算机中最终存储的都是数据的补码
对于无符号数:原码、反码、补码 都是一样的
对于有符号的整数:原码、反码、补码 都是一样的
对于有符号的负数:
反码 = 原码 符号位不变,其他位按位取反 (1变0 0变1)
补码 = 反码 + 1
例如: int a = -1;
原码:1000 0001
反码:1111 1110
补码:1111 1111
方法:存储时看符号(正负) 取出时看类型(signed unsignede)
#include <stdio.h>
int main(int argc, const char *argv[])
{
unsigned char v1 = 10;
//存储时
//原码:0000 1010
//反码:0000 1010
//补码:0000 1010
//取出时
//补码:0000 1010
//反码:0000 1010
//原码:0000 1010 -->10
printf("v1 = %d\n", v1);//10
signed char v2 = -10;
//存储时
//原码:1000 1010
//反码:1111 0101
//补码:1111 0110
//取出时
//补码:1111 0110
//反码:1111 0101
//原码:1000 1010 --> -10
printf("v2 = %d\n", v2);//-10
signed char v3 = 129;
//存储时
//原码:1000 0001
//反码:1000 0001
//补码:1000 0001
//取出时
//补码:1000 0001
//反码:1000 0000
//原码:1111 1111 --> -127
printf("v3 = %d\n", v3); //-127
unsigned char v4 = -1;
//存储时
//原码:1000 0001
//反码:1111 1110
//补码:1111 1111
//取出时
//补码:1111 1111
//反码:1111 1111
//原码:1111 1111 --> 255
printf("v4 = %d\n", v4); //255
signed char v5 = 135;
//存储时
//原码:1000 0111
//反码:1000 0111
//补码:1000 0111
//取出时
//补码:1000 0111
//反码:1000 0110
//原码:1111 1001 --> -121
printf("v5 = %d\n", v5); //-121
return 0;
}