写在开头:
前一天给大家梳理了咱们十天之内要学习的内容并列出了大纲,有人疑惑学习C语言为什么要学习Linux呢?首先C 语言是一种非常流行的编程语言,被广泛用于系统编程和操作系统开发。而Linux 是一种自由、开放源代码的操作系统,它与 C 语言密切相关。原因有一下几点
- 系统编程:Linux 与 C 语言密切相关,因此学习 Linux 可以帮助 C 语言程序员更好地了解系统编程,了解如何与操作系统交互。Linux 内核是用 C 语言编写的,因此学习 Linux 可以帮助程序员更深入地了解 C 语言的工作原理和使用方法。
- 开发工具:Linux 提供了很多优秀的开发工具和开发环境,例如 GCC 编译器、GDB 调试器、Make 工具等,这些工具都是 C 语言程序员必备的工具。学习 Linux 可以帮助程序员更好地掌握这些工具的使用方法和技巧。
- 开源社区:Linux 是一个庞大的开源社区,这个社区中有很多活跃的 C 语言程序员,他们会分享自己的经验、知识和技巧,这对 C 语言程序员来说非常有价值。
- 面向未来:Linux 是一个非常流行的操作系统,被广泛应用于服务器、嵌入式设备、移动设备等领域。学习 Linux 可以帮助 C 语言程序员更好地适应未来的发展趋势,提高自己的竞争力和市场价值。
- 总之,学习 Linux 对 C 语言程序员来说非常重要,可以帮助他们更好地理解系统编程和 C 语言的工作原理,提高开发效率和代码质量,同时也可以拓展职业发展方向和市场竞争力。
好,废话不多说,马上开始第二天的学习!
目录
一、计算及数据表示形式
1.1数值型数据
什么是数据类型?
简单来说,计算机编程语言是用来控制计算机的行为及操作,协助人们解决现实中的问题,其能表达的数据类型也是从实际中提取并抽象出来形成的数据结构描述。
例如:数学中数的基础分类有正整数、负整数、小数等类别,数学中所有关于数的运算都是在基础分类上进行的。计算机出现之前,数学家们用稿纸进行大量的数学运算以求证数学问题和科学计算,这耗费了数学家们太多的精力。随着计算机科技的发展,大量复杂的数学运算交给计算机来执行,极大提高了计算效率,也让数学家们从复杂地数学运算中摆脱出来。
数学运算包含大量的计算表达式,计算机程序需要有连续处理算式和计算数据的能力,下面是一个简单的四则运算算式:
15.8+20*31.5-30
计算机程序要处理上述算式,就需要具备存储小数、整数、运算符的能力。C语言提供了存储小数、整数、运算符的基本数据类型。下图是算式中数据类型到C数据类型的映射图。
在C语言中,数值型数据主要包括整数型和浮点型。整数型主要包括:char
、int
、short
、long
、long long
(C99起)等。浮点型主要包括:float
、double
。
1.2基本数据类型
1.整数型数据
char是一般引用ASCII表字符,每一个字符都有对应的数值。可以在Linux终端中利用man命令进行查看,下为ASCII表
char c = 100; // 定义一个char类型变量c,并赋值为100
int i = 10000; // 定义一个int类型变量i,并赋值为10000
short s = 1000; // 定义一个short类型变量s,并赋值为1000
long l = 100000; // 定义一个long类型变量l,并赋值为100000
long long ll = 1000000; // 定义一个long long类型变量ll,并赋值为1000000 (C99及以后的版本支持)
char 字符(小整型), 1B
short int 或short 短整型 2B
int 整型 4B
long int 或long 长整型, (32位机)4B/8B
2.浮点型数据
float f = 1.1; // 定义一个float类型变量f,并赋值为1.1
double d = 1.11; // 定义一个double类型变量d,并赋值为1.11
3.类型转换
C语言中,不同的数值型数据间可以相互转换。例如,可以将一个float
类型的数据赋值给一个int
类型的变量,但这样会造成精度的损失,因为int
类型的变量只保存整数部分。
int i = 1.1; // i的值为1,因为只取了1.1的整数部分
同样,较小的数据类型不能直接赋值给较大的数据类型,除非显式进行类型转换。
float f = 1.1;
double d = f; // 正确,隐式类型转换
int i = 1;
float f = i; // 错误,不同的数据类型
float f = (float)i; // 正确,显式类型转换
大家都知道,计算机存储用的是二进制,现实中还有其他进制如十进制、八进制、十六进制
十进制
十进制的基数为10,数码由0-9组成,计数规律逢十进一
十进制(Decimal System):这是人类最常用的进制系统,因为它与我们的日常技术习惯相符。再十进制系统中,每一位上的数组都有固定的权值,从右往左分别是10^0、10^1、10^2等。十进制系统用字母D表示
二进制
二进制着重说一下
二进制有两个特点:它由两个数码0,1组成,二进制数运算规律是逢二进一
为区别于其它进制,二进制数的书写通常在数的右下方注上基数2,或在后面加B表示,其中B是英文二进制Binary的首字母。
例如:二进制数10110011可以写成(10110011)2,或写成10110011B。对于十进制数可以不加标注,或加后缀D,其中D是英文十进制Decimal的首字母D。
计算机领域我们之所以采用二进制进行计数,是因为二进制具有以下优点:
二进制数中只有两个数码0和1,可用具有两个不同稳定状态的元器件来表示一位数码。例如,电路中某一通路的电流的有无,某一节点电压的高低,晶体管的导通和截止等。
二进制数运算简单,大大简化了计算中运算部件的结构。
二进制数的加法和乘法基本运算法则各有四条,如下:
0+0=0,0+1=1,1+0=1,1+1=10
0×0=0,0×1=0,1×0=0,1×1=1
3.二进制天然兼容逻辑运算
但是,二进制计数在日常使用上有个不便之处,就是位数往往很长,读写不便
如:把十进制的100000D写成二进制就是11000011010100000B,所以计算机领域我们实际采用的是十六进制。二进制数转换为十六进制数时,长度缩减为原先的约四分之一,把十进制的100000写成八进制就是303240。十六进制的一个数位可代表二进制的四个数位。这样,十进制的100000写成十六进制就是186A0。
八进制
八进制(Octal System):八进制系统使用0到7这八个数字,逢八进一。八进制系统在计算机科学中也有应用,尤其是在表示大数时,它可以作为一种中间表示形式,将较大的数字转换为较短的八进制数,从而简化处理过程。八进制系统用字母O表示。
十六进制
十六进制(Hexadecimal System):十六进制系统使用0到9和A到F这十六个数字,逢十六进一。十六进制系统在计算机科学中广泛使用,因为它可以方便地将二进制数转换为较短的十六进制数,同时保持数值不变。十六进制系统用字母H表示。
这些进制类型各有其特点和用途,但它们都是基于进位计数制的原理,即每一位上的数运算时都是逢X进一位,其中X代表该进制系统的基数。
3.1进制转换
总结上文
十进制:以0-9这九个数字组成。
二进制:由0和1两个数字组成。
八进制:由0-7数字组成,不存在8和9。
十六进制:由0-9和A-F组成。A-F对应的是10-15。
一、十进制转二进制
1.十进制转二进制:一直除以2知道商为0,再反向取余数
例:13(十进制)转1101(二进制)
2.二进制转十进制:最后一位数开始是2^0,然后一直按照指数递增的方式进行加法运算
例:10110(二进制)转22(十进制)
二、十进制八进制
1.十进制转八进制:一直除以8直到商为0,再反向取余数。
例:135(十进制)转207(八进制)
2.八进制转十进制:最后一位数开始是8^0,然后一直按照指数递增的方式进行加法运算。
例:634(八进制)转412(十进制)
三、十进制十六进制
1.十进制转十六进制:一直除以16直到商为0,再反向取余数。
例:946(十进制)转3B2(十六进制)
2.十六进制转十进制:最后一位数开始是16^0,然后一直按照指数递增的方式进行加法运算
例:2C1(十六进制)转705(十进制)
四、二进制八进制
1.二进制转八进制:最后一位数开始取三合一,不够3位前面补0,参照下方顺序排列取得八进制数。
二进制 | 000 | 001 | 010 | 011 | 100 | 101 | 110 | 111 |
八进制 | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 |
例:10111011(二进制)转273(八进制)
2.八进制转二进制:操作反过来,取一分三。将1个八进制数分为3个二进制数,参照下方顺序排列取得二进制数。
二进制 | 000 | 001 | 010 | 011 | 100 | 101 | 110 | 111 |
八进制 | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 |
例:316(八进制)转11001110(二进制)
五、二进制十六进制
1.二进制转十六进制:最后一位数开始取四合一,不够4位前面补0。再用8421码的方法顺序排列取得十六进制数。
例:10010110110(二进制)转4B6(十六进制)
2.十六进制转二进制:所有数拆分成1位,再用8421码的方法顺序排列取得二进制数。高位为0可省略。
例:38D(十六进制)转1110001101(二进制)
二、词法符号
2.1关键字
存储类型:auto static extern register
数据类型:int char float short long double signed unsigned
构造数据类型:struct enum union
分支:if else switch case default for do while go to break continue
其他:void const sizeof volatile return typedef
2.2标识符
标识符命名规则:
- 由数字、字符、下划线(_)组成
- 开头不能是数字
- 不能和关键字重名
- 见名知意
练习:x y sum a100 _A7b_3x 3’a x*y @ b.8 while
2.3运算符
算术运算符 逻辑运算符 位运算符 关系运算符 三目运算符 赋值运算符
2.3.1算数运算符
+ - * / % ++ --
/整数相除,向下取整
int a=9/2;
printf("%d\n",a);//4
float a=9/2;
printf("%f\n",a);//4.000000 //默认打印小数点后六位 %.1f
注意:
float a=4;
printf("%f\n",a);//4.000000
float a=9.0/2;
printf("%f\n",a);//4.500000
强制转换
int b=9;
float a=(float)b/2; //强制转换只在当前这一行生效
printf("%f\n",a);//4.500000
%取余 只能用于整数运算
++
a++; // a=a+1;
1)独立成句
int b=9;
1)++b; //b=b+1;
printf("%d\n",b); //10
2)b++; printf("%d\n",b); //10
2)赋值语句
int b=9;
1、int c=++b; //+ =
printf("%d %d\n",b,c);//10 10
2、int c=b++; //= +
printf("%d %d\n",b,c);//10 9
补充:
int b=9;
int c=(b++); //= +
printf("%d %d\n",b,c);//10 9
3)打印语句
int b=9;
1、printf("%d\n",++b);//10
printf("%d\n",b);//10
2、printf("%d\n",b++);//9
printf("%d\n",b);//10
练习
1、以下程序输出结果是
#include <stdio.h>
int main(int argc, char *argv[])
{
int a = 10;
int b = ++a; //a=11 b=11
int c = a + (b++); //c=11+11=22 b=12
int d = b+c; //d=12+22=34
printf("%d\n",d);
return 0;
} [单选题] *
A. d = 31
B. d = 32
C. d = 33
D.d = 34
2、#include <stdio.h>
int main(int argc, char *argv[])
{
int a = 10;
int b = a--; //b=10 a=9
int c = a + b + 2; //c=21
int d = (b--) + (++c); //d=10+22=32
printf("%d\n",d);
} [单选题] *
A. d = 31
B. d = 32
C. d = 33
D.d = 34
答案:D B
2.3.2逻辑运算符
&& || !
&&逻辑与:全真则真,一假则假
||逻辑或: 一真则真,全假则假
!逻辑非:非真则假,非假则真
printf("%d\n",2>3); //0
printf("%d\n",12>3); //1
int age=20; //age>0&&age<18
printf("%d\n",age>0&&age<18); //0
0假 非0为真
printf("%d\n",!(12>3)); //!1==0
截断法则
逻辑与运算中,前边表达式为假,后边表达式不再执行,直接返回假
逻辑或运算中,前边表达式为真,后边表达式不再执行,直接返回真
练习
#include <stdio.h>
int main()
{
int a=5,b=6,c=7,d=8,m=2,n=2;
(m=a>b)&&(n=c>d);
printf("%d %d",m,n); //0 2
}
2.3.3位运算符
& | ^ ~ << >>
&位与:全一则一,有零则零
|位或:有一则一,全零则零
^异或:相同为0,不同为1
~取反:1-->0 0--->1
int a=12,b=10;
int c=a&b;
//12:1100
//10:1010
//& :1000---->8
printf("%d\n",c);//8
==========================
int a=12,b=10;
int c=a|b;
//12:1100
//10:1010
//| :1110
printf("%d\n",c);//14
两个值交换
#include<stdio.h>
int main(int argc, char const *argv[])
{
int a=12,b=10;
//方法一:
// int temp=0;
// temp=a;
// a=b;
// b=temp;
//方法二:
a=a^b; //1100 ^ 1010 == 110==a
b=a^b; //110 ^ 1010 == 1100==b=12
a=a^b; //110 ^ 1100 == 1010==a=10
printf("%d %d\n",a,b);//10 12
return 0;
}
原码、反码、补码
计算机整数以补码的形式存在
原码 | 反码 | 补码 | |
正数 | 相同 | 相同 | 相同 |
负数 | 相同 | 原码除符号位,其他按位取反 | 反码+1 |
int 4字节 1字节=8位 32位 最左边是符号位,0正数 1负数
-10:1000 0000 0000 0000 0000 0000 0000 1010
int a = 12, b = -10;int c = a & b;
printf("%d\n", c); // 4
12补码:
0000 0000 0000 0000 0000 0000 0000 1100
-10原码:
1000 0000 0000 0000 0000 0000 0000 1010
-10反码:
1111 1111 1111 1111 1111 1111 1111 0101
-10补码:
1111 1111 1111 1111 1111 1111 1111 0110
12补码 & -10补码
0000 0000 0000 0000 0000 0000 0000 1100
1111 1111 1111 1111 1111 1111 1111 0110
0000 0000 0000 0000 0000 0000 0000 0100 补码==4
int b = 10;
int c = ~b;
printf("%d\n", c); // -11
10补码:
0000 0000 0000 0000 0000 0000 0000 1010
~:补码
1111 1111 1111 1111 1111 1111 1111 0101
反码:
1111 1111 1111 1111 1111 1111 1111 0100
原码:
1000 0000 0000 0000 0000 0000 0000 1011----》-11
<<
左移几位,右边补几个0
6<<2==24
110<<2 11000
公式:6*2^2=24-6<<2
-6*2^2=-24
>>
右移几位,右边舍弃几位
110>>2=1 111>>2==1 100>>2==1
6/2^2=1
-6/2^2=-2
1110001
0000100 1<<2
1110101
置一公式:a|(1<<n)
置零公式:a&(~(1<<n))
练习
1、设int b=2;表达式 (b>>2)/(b>>1)的值是()A.0 B.2 C.4 D.8
2、变量x和y的值相等,且为非零值,则以下选项中,结果为0的表达式是()
A.x||y B.x|y C.x&y D.x^y
3、以下程序升输出结果是()。
int main()
{
char x=040; //1 000 000
printf("%o\n",x<<1);
return 0;
}
A.100 B.80 C.64 D.32
答案:A D A
2.3.4关系运算符
> > = < <= == !=
0-18 x>0&&x<18
==等于 =赋值
2.3.5三目运算符 条件运算符
表达式1?表达式2:表达式3运算顺序:
若<表达式1>的值为真,则执行<表达式2>
若<表达式1>的值为假,则执行<表达式3>
int a=6,b=8;
int c=a>b?a:b;
printf("%d\n", c); //8
2.3.6赋值运算符
= += -= *= /= %=
a-=5; // a=a-5;
2.3.7运算符优先级
单算移关与 异或逻条赋单目运算符:++ -- ! ~
算术运算符:* / % + -
移位运算符:<< >>
关系运算符:> >= < <= == !=
位与运算符:&
异或运算符:^
位或运算符:|
逻辑运算符:&& ||
条件运算符:?:
赋值运算符:= += -= *= /= %=
练习:
1.设有以下语句,则c的二进制值是____
char a = 3,b = 6,c;
c = a^b<<2;a.00011011
b.00010100
c.00011100
d.00011000
2.int x = 2,y = 3,z = 4;则表达式x + (y > !z)的值为()
答案:A 3