C语言第十二课---------操作符的介绍与使用(下)

简介: C语言第十二课---------操作符的介绍与使用(下)

插播小知识

1.%u 十进制无符号整数

%d把对应的整数按有符号十进制输出,%u把对应的整数按无符号十进制输出,比如

printf("%d,%u\n",-123,-123);,输出则是-123,4294967173——因为-123的补码是11111111111111111111111110000101,在%u控制下把它当正数输出了。

条件操作符(三目操作符)

exp1 ? exp2: exp3

exp1为真的话返回exp2,否则返回exp3

#include <stdio.h>
int main()
{
  int a = 10;
  int b = 2;
  int m = 0;
  /*if (a > b)
    m = a;
  else
    m = b;*/
  m = (a > b ? a : b);
  printf("%d", m);
  return 0;
}

逗号表达式

exp1, exp2, exp3, …expN

逗号表达式,就是用逗号隔开的多个表达式。

逗号表达式,从左向右依次执行。整个表达式的结果是最后一个表达式的结果。

#include <stdio.h>
int main()
{
  int a = 1;
  int b = 2;
  int c = (a = 2 + b, b = a + b);
  printf("%d %d %d", a, b, c);
  return 0;
}

从左到右执行下去,直到最后一个表达式

下标引用、函数调用和结构成员

[ ] 下标引用操作符

操作数:一个数组名+ 一个索引值

#include <stdio.h>
int main()
{
  int arr[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9 };
  printf("%d", arr[2]);
  return 0;
}

[]的操作数是arr 和2

( ) 函数调用操作符

#include <stdio.h>
int Add(int a, int b)
{
  return a + b;
}
int main()
{
  int a = 0;
  int b = 2;
  Add(a, b);//()函数调用操作符
  return 0;
}

访问一个结构的成员

.结构体.成员名

->结构体指针->成员名

#include <stdio.h>
struct book
{
  char name[20];
  int price;
};
int  main()
{
  struct book b = { "明解C语言", 55 };
  printf("%s\n", b.name);
  struct book* pb = &b;
  printf("%s\n", pb -> name);
  printf("%s\n", (*pb).name);
  return 0;
}

表达式求值

表达式求值的顺序一部分是由操作符的优先级和结合性决定。

同样,有些表达式的操作数在求值的过程中可能需要转换为其他类型。

隐式类型转换

1.整形提升(运用于小于一个int 大小的数值)

表达式中的字符和短整型操作数在使用之前被转换为普通整型,这种转换称为整型

提升 。

整型提升的意义: 表达式中各种长度可能小于 int 长度的整型值,都必须先转 换为 int 或 unsigned int ,然后才能送入 CPU 去执行运算

如何进行整体提升呢?

整形提升是按照变量的数据类型的符号位来提升的

在int中有signed和unsigend, 所有char也分有符号和无符号,因为C语言没有规定,所以取决于编译器

/ 负数的整形提升

char c1 = - 1 ;

变量 c1 的二进制位 ( 补码 ) 中只有 8 个比特位:

1111111

因为 char 为有符号的 char

所以整形提升的时候,高位补充符号位,即为 1

提升之后的结果是:

11111111111111111111111111111111

// 正数的整形提升

char c2 = 1 ;

变量 c2 的二进制位 ( 补码 ) 中只有 8 个比特位:

00000001

因为 char 为有符号的 char

所以整形提升的时候,高位补充符号位,即为 0

提升之后的结果是:

00000000000000000000000000000001

// 无符号整形提升,高位补 0

注意一下,对char进行提升要先写出8个bit来确定符号位,然后根据符号位进行整体提升,计算机就是这样计算大小小于int的数值

int main()
{
 char a = 0xb6;
 short b = 0xb600;
 int c = 0xb6000000;
 if(a==0xb6)
 printf("a");
 if(b==0xb600)
 printf("b");
 if(c==0xb6000000)
 printf("c");
 return 0;
}

a,b 要进行整形提升 , 但是 c 不需要整形提升

a,b 整形提升之后 , 变成了负数 , 所以表达式 a==0xb6 , b==0xb600 的结果是假 , 但是 c 不发生整形提升 , 则表 达式 c==0xb6000000 的结果是真 .

我们只需要知道小于int大小的数值要整形提升

#include <stdio.h>
int main()
{
  char a = 1;//    00000000000000000000000000000001  补码   ---a存储的只有00000001
  char b = 30;//   00000000000000000000000000011110 补码  ----b存储的只有00011110
  char c = a + b;// 参与了运算
          //a整形提升为 00000000000000000000000000000001
          //b整形提升为 00000000000000000000000000011110
          //  结果    00000000000000000000000000011111
          //00011111  -char c存储的8个bit
          //c整形提升   00000000000000000000000000011111   --->补码
          //最终原码为  00000000000000000000000000011111 
  printf("%d", c);
  return 0;
}

所以我们可以理解为当字符或者其他小于int长度的,在参与运算或者判断又或者配合某些操作符就会发生整形提升,提升到4个字节,否则原来是多少字节就是多少字节

2.算术转换(用于大小大于或者等于int 大小的数组)

如果某个操作符的各个操作数属于不同的类型,那么除非其中一个操作数的转换为另一个操作数的类 型,否则操作就无法进行

如果某个操作数的类型在上面这个列表中排名较低,那么首先要转换为另外一个操作数的类型后执行运算。

操作符的属性

复杂表达式的求值有三个影响的因素。

1. 操作符的优先级

2. 操作符的结合性

3. 是否控制求值顺序。

#include <stdio.h>
int main()
{
  int a = 0;
  int b = 2;
  //优先级
  b = 9 + 5 * 6;
  //结合性
  b = 6 + 5 + 3;
  return 0;
}

在相邻操作符不一样的时候,先考虑优先级

相邻操作符相同时,考虑结合性

结合性就是计算方向

#include <stdio.h>
int main()
{
 int i = 1;
 int ret = (++i) + (++i) + (++i);
 printf("%d\n", ret);
 printf("%d\n", i);
 return 0;
}

这个代码在不同编译器结果不一样,所以这个代码的写法不行,我们可以看看vs编译器是怎样运行的,我们看看反汇编

mov :是把后面的值存放到前面去, 把1存放到dword ptr[i]


add:增加


eax、ecx、都是寄存器


总结 :我们写出的表达式如果不能通过操作符的属性确定唯一的计算路径,那这个表达式就是存在问题 的。


相关文章
|
3月前
|
存储 C语言 索引
【C语言篇】操作符详解(下篇)
如果某个操作数的类型在上⾯这个列表中排名靠后,那么⾸先要转换为另外⼀个操作数的类型后执⾏运算。
72 0
|
3月前
|
程序员 编译器 C语言
【C语言篇】操作符详解(上篇)
这是合法表达式,不会报错,但是通常达不到想要的结果, 即不是保证变量 j 的值在 i 和 k 之间。因为关系运算符是从左到右计算,所以实际执⾏的是下⾯的表达式。
247 0
|
20天前
|
存储 缓存 C语言
【c语言】简单的算术操作符、输入输出函数
本文介绍了C语言中的算术操作符、赋值操作符、单目操作符以及输入输出函数 `printf` 和 `scanf` 的基本用法。算术操作符包括加、减、乘、除和求余,其中除法和求余运算有特殊规则。赋值操作符用于给变量赋值,并支持复合赋值。单目操作符包括自增自减、正负号和强制类型转换。输入输出函数 `printf` 和 `scanf` 用于格式化输入和输出,支持多种占位符和格式控制。通过示例代码详细解释了这些操作符和函数的使用方法。
33 10
|
1月前
|
存储 编译器 C语言
【C语言】简单介绍进制和操作符
【C语言】简单介绍进制和操作符
157 1
|
1月前
|
存储 编译器 C语言
初识C语言5——操作符详解
初识C语言5——操作符详解
164 0
|
3月前
|
C语言
C语言操作符(补充+面试)
C语言操作符(补充+面试)
45 6
|
3月前
|
存储 编译器 C语言
十一:《初学C语言》— 操作符详解(上)
【8月更文挑战第12天】本篇文章讲解了二进制与非二进制的转换;原码反码和补码;移位操作符及位操作符,并附上多个教学代码及代码练习示例
56 0
十一:《初学C语言》—  操作符详解(上)
|
4月前
|
C语言
五:《初学C语言》— 操作符
本篇文章主要讲解了关系操作符和逻辑操作符并附上了多个代码示例
43 1
五:《初学C语言》—  操作符
|
5月前
|
C语言
C语言逻辑操作符的短路问题
C语言逻辑操作符的短路问题
|
5月前
|
编译器 C语言
【C语言】:中移位操作符,位操作符详运算规则详解
【C语言】:中移位操作符,位操作符详运算规则详解
41 1