C语言基础1
基础书籍
操作系统:操作系统之哲学原理(从哲学层次入手)
计算机网络:谢希仁版的计算机网络
微机原理:清华大学出版的微机原理
C语言程序设计:谭浩强写得
软件工程的书
深入理解计算机系统
- 重点是要有自学能力以及做软件要有工程化的思维
基本类型
类型分为:
- 强类型语言:需要对变量先定义再赋值,一旦变量的类型确定那么变量的类型将不在改变。(强制转换和隐式转换都只是转换值,而不是类型)
int a = 10;
short b = 12;
a = (int)b;
注意:这里的b不会被转变类型,只是改变了值,类型是无法被改变的。给a赋值的是临时空间中b的值
- 弱类型语言:类型
基本数据类型(可以进入到混合运算中)
(1byte = 8bit)
(1存储单元 = 1byte)byte即字节
char—1个字节
short—2个字节
int—4个字节
long—4个字节
long int—4个字节
long long—8个字节
float—个字节
double—8个字节
long double—8个字节
bool----1个字节
PS:
sizeof():计算某种类型所占的字节个数。
sizeof(char):1(相当于1 byte int;mini int )
sizeof(short):2
进制
- 进制转换可以使用 贪心算法
- 2进制 8进制 10进制 16进制
10进制 (119)
=>> ( 01110111 ) 2进制
=>> ( 167 ) 8进制
=>> ( 77 ) 16进制
int main()
{
int a = 12; //十进制
int b = 012; //八进制
int c = 0x12; //十六进制
printf("%d %d %d\n",a,b,c); //十进制 12,10,18
printf("%o %o %o\n",a,b,c);//八进制 14,12,22
printf("%x %x %x\n",a,b,c);//十六进制 C,A,12
return 0;
}
源码,反码,补码
- 正数:原码 = 反码 = 源码
- 负数: 原码取反 = 反码,反码 + 1 = 补码
- 计算机中存放都用补码的形式(因为可以把减法变成加法,从硬件上来说更简单了)
1.源码:2进制的编码;
2.反码:对源码取反;
3.补码:在反码的基础上加1;
举例:
- 正数:
char a = 5;
a = 5
// 0000 0101 =>>5; 整数的源码、反码、补码都是一样的。 - 负数:
char b = -5;
b = -5
// 1000 0101 =>> -5 源码
// 1111 1010 =>> 反码
// 1111 1011 =>> 补码 // 0xfb 存放
所以可以理解的是计算机表示数据时用补码,要想到的是用二进制表示。
扩充空间字节
在数据进行运算的时候必然会有数据的扩充或者截断。例如:
char a = 10; //char占一个字节
char b = -20; //而int占4个字节
int x = a;
int y = b;
- 扩充方法:
扩充时和目标无关,和自身有关。
1.自身有符号:
符号位是 0 则全扩展为 0;
符号位是 1 则全扩充为 1;
2.自身无符号:
全扩展为 0。
扩充时自身有符号
对于上例:
char a = 10; //char占一个字节
char b = -20; //而int占4个字节
int x = a;
int y = b;
有如下解决方法:
对于 a = 10
二进制:0000 0000 0000 0000 0000 0000 0000 1010
十六进制:0x00 00 00 0A 即为x
对于 b = -20
二进制:1111 1111 1111 1111 1111 1111 1110 1100
十六进制: 0xff ffff EC 即为y
扩充时自身无符号
int main()
{
char c = 128;
unsigned char uc = 128; //定义的是无符号的char
unsigned short us = 0;
us = c+uc;
//char c:1000 0000补位1得==> 1111 1111 1000 0000
//unsigned char c:1000 0000补位0得==> 0000 0000 1000 0000
//其实这里也可以补到32位,但是本题16位就够了,因为short型是16位的。
//上面两个相加得:1 0000 0000 0000 0000
printf("%x \n",us);//输出为0,因为us是16位,截断下来是0.
us = ( unsigned )c+uc;
//unsigned c:1000 0000补位0得==>0000 0000 1000 0000
//uc: 1000 0000补位0得==>0000 0000 1000 0000
//上面两个相加得:0000 0001 0000 0000
printf("%x \n",us);//输出为0x100,因为us是16位,截断下来.
us = c+(char)uc;
//char c:1000 0000补位1得==> 1111 1111 1000 0000
//char uc:1000 0000补位1得==>1111 1111 1000 0000
//1111 1111 0000 0000
printf("%x \n",us);//输出0xff00
return 0;
}
内存的存放形式
1.小端存放
在计算机中存放的时候是根据 小端存放 存放,即高位存放高地址,低位存放低地址。
2.大端存放
数据的高字节,保存在内存的低地址中,而数据的低字节,保存在内存的高地址中,这样的存储模式有点儿类似于把数据当作字符串顺序处理:地址由小向大增加,而数据从高位往低位放。
运算符
-
取余 % 和 取整 /
a%5 -->取余的范围在0,1,2,3,4(在循环链表可用)
取余 % 只取决于被除数的正负;
取整的正负取决于除数和被除数的正负,有一个是负的输出就是负的。5%3=5-(5/3)*3=5-3=2
5%(-3)=5-(5/(-3))3=5-(-1)(-3)=2
-5%3=-5-(-5/3)*3=-5-(-1)*3=-2 -
a++和++a
a++ 是先取a的值给b,再给a+1 ;
++a 是先对a+1再把运算后的结果取出来给b。
int a = 5;
int b = 3;
++a = b;
printf("a= %d",a);
//a= 3
a++ = b;
//编译错误
a++ = b;产生编译错误,因为先将a取出来放在临时空间内,当b赋值的时候又是将b的值给了临时空间,由于临时空间只读不可取,所以产生编译错误。
- && || ! (与或非)
选择语句
if语句
if(条件语句){}: 条件语句非真即假,只要为零就是假其余都是真。
int a = 10;
int b = -1;
if (b) //这里只要非零就是真
{
++a;
}
else
{
--a;
}
printf("%\n", a);
例如:将 a b c 按从大到小排列
//思路是不停地把最大的往后移
int a,b,c;
int tmp;
scanf("%d %d %d",&a,&b,&c);
//输入5,3,4
if (a > b)
{
tmp = a;
a = b;
b = tmp;
}
if (b > c)
{
tmp = b;
b = c;
c = tmp;
}
if (a > b)
{
tmp = a;
a = b;
b = tmp;
}
printf("a,b,c %d %d %d", a, b, c);
//输出3,4,5
Tips:在不引入第三个变量的时候进行两个值的交换。
//不引入第三个变量
int a = 2;
int b = 8;
a = a + b;
b = a - b;
a = a - b;
printf("a,b,c %d,%d", a, b);
//a,b 8,2
练习题
1.猜数字并输出共猜了多少次
int inputnum = 0;
int randnum = 0;//随机数
int count = 0;
bool RoN = true;
srand(time(NULL));
//根据时间随机产生一个随机数,有这个函数能使得rand每次产生不一样的随机数,因为rand函数本来是一个伪随机函数,他每次打出来的随机值都是一个。
randnum = rand() % 100;
//rand产生的数字是0~1,取余100则结果为0~100
printf("num = %d", randnum);
while (RoN)
{
printf("\n请输入数字: ");
scanf_s("%d", &inputnum);
count += 1;
printf("\n");
if (inputnum == randnum) {
printf("太聪明啦!第 %d 次就猜出来了", count);
RoN = false;
}
if (inputnum > randnum) {
printf("哈哈哈哈哈哈哈愚蠢的人类猜大了!");
}
if (inputnum < randnum) {
printf("哈哈哈哈哈哈哈愚蠢的人类猜小了!");
}
}
2.判断是否是闰年
int message = 0;
printf("请输入年份: ");
scanf_s("%d", &message);//vs中不知为何scanf运行总是出错,提醒改成_s
if(message % 4 == 0 && message % 100 != 0 || message %400 ==0)
{
printf("您所查询的年份%d是闰年 ",message);
}
else {
printf("您所查询的年份%d不是闰年 ",message);
}
3. 判断某一年某一月某一日是当年的第几天
int year = 0;
int month = 0;
int day = 0;
int sum = 0;
printf("\n请输入 年 月 日:");
scanf_s("%d %d %d", &year, &month, &day);
for (int i = 0; i < month; i++) {
if (i == 1 || i == 3 || i == 5 || i == 7 || i == 8 || i == 10 || i == 12)
{
sum += 31;
}
if (i == 4 || i == 6 || i == 9 || i == 10)
{
sum += 30;
}
if (i == 2)
{
sum += 28;
}
}
sum = sum + day;
if (year % 4 == 0 && year % 100 != 0 || year % 400 == 0)
{
if (month>2) {
sum += 1;
}
}
printf("%d年%d月%d日,是当年的第%d天.", year, month, day, sum);