C语言学习(类型)

基础书籍

操作系统:操作系统之哲学原理(从哲学层次入手)
计算机网络:谢希仁版的计算机网络
微机原理:清华大学出版的微机原理
C语言程序设计:谭浩强写得
软件工程的书
深入理解计算机系统

  • 重点是要有自学能力以及做软件要有工程化的思维

基本类型

类型分为:

  1. 强类型语言:需要对变量先定义再赋值,一旦变量的类型确定那么变量的类型将不在改变。(强制转换和隐式转换都只是转换值,而不是类型)
int a = 10;
short b = 12;
a = (int)b;    

注意:这里的b不会被转变类型,只是改变了值,类型是无法被改变的。给a赋值的是临时空间中b的值
  1. 弱类型语言:类型

基本数据类型(可以进入到混合运算中)

(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.大端存放
数据的高字节,保存在内存的低地址中,而数据的低字节,保存在内存的高地址中,这样的存储模式有点儿类似于把数据当作字符串顺序处理:地址由小向大增加,而数据从高位往低位放。
在这里插入图片描述

运算符

  1. 取余 % 和 取整 /

    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

  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的值给了临时空间,由于临时空间只读不可取,所以产生编译错误。

  1. && || ! (与或非)

选择语句

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);

猜你喜欢

转载自blog.csdn.net/sunshine612/article/details/83858456