操作符学习篇下
5.单目操作符
? ? ? ? 单目操作符,即后面为一个参数的操作符,即 "!a" 、"-a" 这里面 ”-“ 为负号,这类后面跟一个参数进行运算的为单目操作符;对应的如果是双目操作符则为 a -?b 此时中间的 "-" 为减号,这类同时作用需要两个参数进行运算的为双目操作符。
单目操作符
! --> 逻辑反操作
- --> 负值
+ --> 正值
& --> 取地址操作符
sizeof --> 操作数的类型长度(以字节为单位 Byte(字节)不是bit(比特))
~ --> 对一个数的二进制按位取反
-- --> 前置、后置--
++ --> 前置、后置++
* --> 间接访问操作符(解引用符)
(类型) --> 强制类型转换
其中 !- + 为平常所见的
& 为取地址符,在进行scanf()函数调用时,我们时常把输入的值储存到对应参数的地址里头;
int a = 0; --> 定义一个参数为a,并开辟内存地址,初始化为0;
scanf("%d\n",&a); --> 表示的就是将输入的值储存到a的地址下;
?sizeof():计算操作数的类型长度;
// sizeof()函数表示的操作数的类型长度(以字节为单位)
int main()
{
int a = 12;
char b = 'r';
char* p = &b;
int arr[10] = { 0 };
//sizeof是取类型长度跟变量无关
printf("%d\n", sizeof a ); //sizeof取变量长度时可以不要括号,但是如果是类型就不行
printf("%d\n", sizeof(a)); // 4
printf("%d\n", sizeof(int)); // 4
printf("%d\n", sizeof(b)); // 1
printf("%d\n", sizeof(char));// 1
printf("%d\n", sizeof(p)); // 8
printf("%d\n", sizeof(char*));// 8
printf("%d\n", sizeof(arr)); // 40
printf("%d\n", sizeof(int[10]));// 40
}
计算字符串长度的函数:sizeof和strlen
区别:
sizeof:1.操作数类型长度操作符
2.计算的是整个字符串开辟的空间
strlen:1.计算字符串函数,需要头文件的引用
2.计算字符串中 ‘\0 ’之前的字符个数
注:strlen只针对字符串的字符数,而sizeof可以对所有变量进行计算空间;
例:
arr[] = 'abc\0' 对于字符串最后一位计算机会默认给\0的标志符,表示结束
sizeof(arr) = 4 sizeof的计算结果算进了\0这一位,所以有4位
strlen(arr) = 3 strlen计算\0之前的字符数,所以是3位
//"~":取反符号
//实例:将一个二级制中的某个 0 变为1
int main()
{
int a = 11;
//a = 11 --> 00001011
//如果要1011变成1111则只需要与上一个0100
//则为0001 向左移两位 --> 0100 <-- 1<<2
a = a | (1 << 2);
//也就是如果要改变二进制中的某个“1”或者“0”,则相对应与上一个数就行了
//如果要把 1111 变回 1011 则需要与上一个1011即可
//“与” --> 1111
// 1011 --> 1011
//而 1011 --> 0100 按位取反即可
a = a & (~(1 << 2));
// ~ 按二进制位取反
// 以八位来计算
// a --> 00000000 -- 原码
// ~a --> 11111111 -- 补码 计算机识别码
// ~a --> 11111110 -- 反码
// ~a --> 10000001 -- 原码
printf("%d\n", a);
return 0;
}
// -- 和 ++ 的实例
int main()
{
// ++ --
int a = 10;
printf("1.a++ = %d\n", a++); //先进行打印再 ++
printf("a = %d\n", a); //打印 ++ 后的结果
printf("2.++a = %d\n", ++a); //打印是 ++ 后的结果
printf("a = %d\n", a); //结果跟上面一样
return 0;
}
//
// * 解地址符,其定义在指针方面有很大的作用
// 定义一个指针: int* p = &a; 则*p = a;
//对p进行解地址就会得到地址内存放的a的值
//
//
// (类型) 此为强制转换符,就是将某个类型的参数强制转换为另一个类型
//例如: (int)float a;表示就是将a 本来为float的类型强制转换成int类型
//
6.关系操作符
? ? ? ? 关系操作符就是在判断语句中的符号,有以下常见操作符。
关系操作符: > 大于
>= 大于等于
< 小于
<= 小于等于
!= 不等于
== 等于
7.逻辑操作符
? ? ? ? 逻辑操作符为&& (逻辑与)、||(逻辑或)。逻辑与(&&)判断前后两个语句是否为真,如遇到前面一个语句为假,则判断整个语句都为假,多个语句进行与时,遇到第一个为假的语句便会判断整个语句为假,不会再往后进行后面的语句;逻辑或,则遇到第一个为真时,不会再往后运行语句;实例如下:
int main()
{
int i = 0, a = 0, b = 2, c = 3, d = 4;
//i = a++ && ++b && d++; //语句1:若为假,则不往后算
i = a++ || ++b || d++; //语句2:若为真,则不往后算
printf("%d %d %d %d", a, b, c, d);
return 0;
}
//结果:语句1,因为判断a为假,则a++完,后面的语句不运行,结果为:1 2 3 4
// 语句2:判断a为假a++,++b为真,则后面不进行,结果为:1 3 3 4
8.条件操作符
? ? ? ? 常见形式: exp ? exp1 : exp2,表示的意思时exp条件,如果为真则结果返回exp1,如果为假则返回exp2;代码解释:
int main()
{
int a = 0;
int b = 0;
if (a > 5)
b = 3;
else
b = -3;
//上面if()else表示的就是 b = (a > 5 ? 3 : -3);
printf("%d", b);
return 0;
}
9. 下标引用、函数调用和结构成员
?????????下标引用符:数组的a[10]这里面的 “[]” 就是下标引用符 --> 操作数就是a和[]中的下标数。 ?????????函数调用符:int max = get_max()中调用函数的时候, "()"? 就是函数调用符 ,--> ?操作数就是get_max和 "()" 中的表达式或者参数; ?操作数最少就是一个(没有传参的时候),函数调用符是在其他函数里头的,而定义函数时的 "()" 是定义函数的部分并不是函数调用符。
结构成员,也就是结构体,结构体里面存放着多中属性的参数,统一为一个结构体属性,通常使用在一组数据同时含有多个属性的时候。比如定义学生参数,通常一个学生带有多种属性。
//学生结构体
//创建了一个结构体-struct Stu
struct Stu
{
char name[20];
int age;
char id[20];
};
//结构体相当于图纸,还没函数调用定义时,不分配内存
int main()
{
int a = 10;
//使用了struct Stu这个类型创建了一个学生对象s1,并初始化
//当进行创建的时候,就进行 了分配内存,并进行了储存
struct Stu s1 = {"张三",20,"20221010"};
struct Stu* ps = &s1; //struct Stu --> 类型; *p --> 指针类型的定义; &取地址符
//结构体指针操作符(->):结构体指针 -> 成员名 --> ps->id
printf("%s\n", ps->id);//指针的取内容:ps --> id 表示直接取到某一元素的内容 相当于 *(ps).id --> *(ps)表示取 ps所指的元素 即 s1
/*printf("%s\n", s1.name);
printf("%s\n", s1.id);
printf("%d\n", s1.age);*/
//结构体变量.成员名 --> s1.age
return 0;
}
表达式求值
? ? 顺序是由操作符的优先级和结合性决定,而有些表达式的操作数在求值的过程中可能需要转换为其他类型隐式类型转换。 ? ? ?C语言整型的算数运算总是至少以缺省整型类型的精度来进行的,为了获取精度,表达式中的字符和短整型操作数在使用之前转换为普通整型,称为整型提升。 整型提升的意义 ? ? 表达式运算要在计算机CPU的运算器原件中进行,CPU内整型运算器(ALU)的操作数的字节长度一般就是int长度,同时也是CPU的通用寄存器的长度,因此即使两个char类型相加,在CPU执行时实际上也要先转换成整型操作数的标准长度,在进行运算。因此在小于int类型长度的其他值时,默认转换成int或unsigned int类型再进行相加减,加减完截取低位的类型位,在输出时再以默认将符号位补齐转换成int类型输出。下面两段小的代码来解释:
//整型提升
int main()
{
char a = 3, b = 3, c = 127;
//b = 3 则八位二进制 --> 00000011
//c = 127,则八位二进制 --> 01111111
//相加的时候将b跟c偷偷转换为了int类型后在进行相加得结果
// 整型提升是根据符号位补齐高位为int类型的数量,所得结果截断低八位为结果
//a = b + c = 130, 八位二进制里头有第一位为符号位,则130 --> 10000010 补码
// 负数的补码转换成原码为:11111110 --> -126
// 若c = 255
//011111111 --> 255
//000000011 --> 3
//1 00000010 -->则char在截断后面八位,则结果为0000010 --> 2
//
a = b + c;
printf("%d", a);
return 0;
}
//进行整型提升后的地址值与原来类型的地址
int main()
{
char a = 0xb6;
short b = 0xb600;
int c = 0xb6000000;
if (a == 0xb6) //进行整型提升后,a为int类型,则不再是8位了,而是补符号位的32位
printf("a\n");
if (b == 0xb600) //进行整型提升后,b为int类型,则不再是16位了,而是补符号位的32位
printf("b\n");
if (c == 0xb6000000) //进行整型提升后,c为int类型,而原本也为int类型,因此相等
printf("c\n");
return 0;
}
//进行运算的过程中就会进行整型提升,由下面实例可以看出
int main()
{
char c = 4;
// %u 为打印字节数
printf("%u\n", sizeof(c)); // 1 char类型为 1 个字节
printf("%u\n", sizeof(+c));// 4 进行了表达式运算则转为int类型即为 4 个字节
printf("%u\n", sizeof(!c));// 1 未进行表达运算,即为 1 个字节
return 0;
}
算数转换和操作符属性
算数转换:
long double
double
float
unsigned long int
long int
unsigned int
int
短的会先转换成长的在进行计算
操作符的属性:
1.操作符优先级 + - * / 邻操作符优先级高的先计算
2.操作符的结合性
3.是否控制求值顺序
注:操作符的优先级,如果进行同个优先级计算是会出现结果不一样,解决方法就是对表达式进行简化,减少有歧义的两个优先级:例如
int main()
{
int c = 1;
//c = c + --c;
c = (++c) + (++c) + (++c); //这里的++c都是同个优先级的
printf("%d", c);
return 0;
}
?linux上c语言编译的结果
vs上C语言编译的结果
?优先级列表:
C语言运算符优先级和结合性一览表 (biancheng.net)http://c.biancheng.net/view/161.html
操作符的学习到此就结束了,分为两个部分写了
|