本周我们学习的内容如下:
类型转换
-
隐式转化:系统按照隐式规则自动进行的转换
-
强制转换:用户强行将某类型的数据转换为另一种类型,此过程可能丢失精度
总结:不管是隐式转换还是强制转换,变换的都是操作数在运算过程中的类型,是临时的,操作数本身的类型是不会改变的,也无法改变。
-
#include <stdio.h>
int main(int argc, char const *argv[])
{
int b = 65;
char a = (char)b; //强制类型转换将b转为字符
printf("%c\n", a);
//隐式类型转换
char a = 'a';
int b = 100;
float c = 3.14;
char d = a + b + c;//内存越界
int c = a + b + c;//丢精度
float f = a + b + c;//正确
printf("%f\n", f);
return 0;
}
整型数据尺寸
-
short不可比int长
-
long不可比int短
-
long型数据长度等于系统字长
long型数据长度等于系统字长(32位操作系统(2^32)long是占用4字节,64位操作系统(2^64)long占用8字节。
可移植性整型
概念:不管放到什么系统,尺寸保持不变的整型数据,称为可移植性整型(数据类型重新划分)
#include <stdio.h>
//给变量取别名称为可移植数据类型
typedef char int8_t;
typedef unsigned char uint8_t;
typedef short int16_t;
typedef unsigned short uint16_t;
typedef int int32_t;
typedef unsigned int uint32_t;int main(int argc, char const *argv[])
{
int8_t a = 'p';
printf("%c\n", a);
return 0;
}
问:有时候我们需要使用int32_t类型变量代替int类型变量的原因是什么?
答:int是系统基本数据类型,其长度在不同平台下的大小尺寸是有区别的,为了使同一份代码能够在不同的操作系统下 面运行,并且尺寸不发生改变,一般使用类似于int32_t这样的可移植类型来定义数据,这些类型是不同平台下对基本数据类型的封装,然后统一发布,这些移植的数据类型一般是放在头文件中,比如/user/include/stdin.h
取余的运用场景
#include <stdio.h>
#include <stdlib.h>
#include <time.h>int main(int argc, char const *argv[])
{ //通过时间产生随机因子
srand(time(NULL));//产生一个随机数
int ret = rand() % 10;//把随机数范围控制在0-9
printf("%d\n",ret);
return 0;
}
单目运算符(目:目标操作数)
#include <stdio.h>
int main(int argc, char const *argv[])
{
int a = 10;
int b = 20;
int c = ++a;//a先自加再赋值给c
int d = b++;//b先赋值给d再自加
printf("%d,%d,%d,%d\n",a,b,c,d);
//打印当前行号
printf("LINE : %d\n",__LINE__);
int b1 = 2;
int y = (b1++)+(++b1);//(错误的)
printf("b1:%d,y:%d\n",b1,y);
return 0;
}
双目运算(目:目标操作数)
#include <stdio.h>
int main(int argc, char const *argv[])
{ int a = 10;
int b = 20;
int o = b * a;
printf("sum = %d\n", o);int f = b / a;//除
printf("sum = %d\n", f);int g = b % a;//取余,在限制一个范围内使用的场景较多
printf("sum = %d\n", g);
return 0;
}
关系运算符(只有两种结果:0/1)
逻辑运算符
-
!:逻辑反(将逻辑真 、假翻转,即真变假,假变真
-
&&:逻辑与(将两个关系表达式串联起来,当且仅当左右两个表达式都为真时,结果为真。
-
||:逻辑或 (将两个关系表达式并联起来,当且仅当左右两个表达式都为假时,结果为假。
位运算符(对整个变量的某一位操作)
~:按位取反---单目运算符,数据将每一个 bit位取反,1变0,0变1
-
%u以补码的方式存放
-
%d以补码还原成原码方式显示
&:按位与,两个都为1,结果才为1
1 & 1 == 1
1 & 0 == 0
0 & 0 == 0
0 & 1 == 0
| :按位或,两个都为1,结果才为1
1 | 1 == 1
1 | 0 == 1
0 | 1 == 1
0 | 0 == 0
^:按位异或--不同为1,相同为0
1^0==1
0^1==1
0^0==0
1^1==0
无符号左移 (规律:只要不越界,满足a*2^n)
有符号左移
无符号右移(规律:a/2^n)
有符号右移
特殊运算符
条件运算符
sizeof运算符
return运算符
逗号表达式
二路分支
-
if语句:表达一种 如果-则的条件执行关系
-
if-else语句:表达一种 如果-否则 的互斥分支关系
多路分支
-
switch(n)语句中的n必须是一个整型表达式。
#include <stdio.h>
int main(int argc, char const *argv[])
{
switch(4)
{
case 1:
printf("one\n");
break;
case 2:
printf("two\n");
break;
case 3:
printf("three\n");
break;
default ://上面的条件不满足则执行此语句
printf("other\n");
}
return 0;
}
for循环
-
逻辑:与 while 循环类似,但更加紧凑,for 循环将控制循环的变量集中在一行
for嵌套循环(外循环+内循环)
goto语句:goto语句常被用在错误语句处理
数组
#include <stdio.h>
int main(int argc, char const *argv[])
{ //申请4块ch空间存放"ABC\0"
char ch[4] = "ABC";
printf("%c\n",ch[0]);//将ch第0块空间的内容输出
printf("%c\n",ch[1]);//将ch第1块空间的内容输出
printf("%c\n",ch[2]);//将ch第2块空间的内容输出char c = ch[2];//将数组ch的第二块内存的数据给c
printf("%c\n",c);
char buf[5];
//%p为输出地址
printf("buf addr : %p\n",buf);
buf[0] = 'r';
buf[1] = 'o';
buf[2] = 's';
buf[3] = 'e';
buf[4] = '\0';
//%s是输出字符串
printf("%s\n",buf);
return 0;
}
buf是buf[0]的地址,是整个数组的基地址,buf[0]是一块基地址的空间,里面存了‘r’
buf==&buf[0]
总结:数组名相当于整个数组的一个首地址。
#include <stdio.h>
int main(int argc, char const *argv[])
{
char c1[5] = "jack";
printf("%d\n",sizeof(c1));//数组名是这个数组的首元素地址
printf("c1 addr %p\n",c1);
printf("c1[0] addr %p\n",&c1[0]);
printf("c1[1] addr %p\n",&c1[1]);
printf("c1[2] addr %p\n",&c1[2]);
//*表示获取地址里面的内容,*表示解引用
printf("%c\n",*(c1+0));//c1[0]==c1+0-->c1[0]==*(c1+0)
printf("%c\n",*(c1+1));//c1[1]==c1+1-->c1[1]==*(c1+1)
printf("%c\n",*(c1+2));//c1[2]==c1+2-->c1[2]==*(c1+2)
printf("%c\n",*(c1+3));//c1[3]==c1+3-->c1[3]==*(c1+3)
return 0;
}