C语言操作符进阶教程(表达式求值隐式类型转换方法)

目录
  • 结构体
  • 表达式求值
  • 隐式类型转换
    • 意义:
  • 方法
  • 算术转换
  • 操作符属性

结构体

结构体变量的声明需要在主函数之上或者主函数中声明,如果在主函数之下则会报错,而且c语言中的结构体不能直接进行强制转换,只有结构体指针才能进行强制转换。

涉及结构体的操作符这里讲两个:
. (结构体访问操作符)
-> ()

首先写一段代码:

int main()
{
struct Stu s = {"me",19,60};
prinft("%s %d %lf",s.who,s.age,s.weight)
return 0;
}

这就是个结构体访问,这里的结构是:结构体变量 . 结构体成员,箭头怎么用呢?当我有一个结构体指针:

struct Stu * ps = &s;
printf("%s %d %lf\n"),(*ps).name,(*ps).age,(*ps).score);
return 0;

这里我是对 ps 解引用一下,找到他所指向的对象,其实和上面第一组代码的结果是一样的;但是,横看竖看都觉得有点啰嗦,我们把格局打开:

printf("%s %d %lf\n",ps->name,ps->age,ps->score);
return 0;

这样是不是看着要清爽许多?->操作符的基本语法是:结构体指针 -> 结构体成员

表达式求值

我们在接触那么多的操作符后,就可以应用来进行计算,表达式求值的顺序一部分是由操作符的优先级和综合性决定。同样,有些表达式的操作数在求值过程可能需要转换成其他类型。

隐式类型转换

C语言的整型算术运算总是至少以缺省整型类型的精度来进行的。为了获取这个精度,表达式中的字符和短整型操作数在使用之前被转换为普通整型,这种转换被称为整型提升

意义:

表达式的整型运算要在CPU的相应运算器件内执行,CPU内整型运算器(ALU)的操作数的字节长度一般就是int的字节长度,同时也是CPU的通用寄存器的长度。因此,即使两个char类型的相加,在CPU执行时实际上也要先转换为CPU内整型操作数的标准长度。通用CPU(general-purpose CPU)是难以直接实现两个8比特字节直接相加运算(虽然机器指令中可能有这种字节相加指令)。所以,表达式中各种长度可能小于int长度的整型值,都必须先转换为int或unsigned int,然后才能送入CPU去执行运算。

我们用一段代码代入一下:

int main()
{
char a = 5;
char b = 126;
char = a+b;
printf("%d\n",c);
return 0;
}

这里的一个表达式:a+b, 其中a和b的类型都是 char 类型,按照定义来看,也就是这段代码的运行远比我们想象的复杂 ,我们知道 sizeof(char),sizeof(short)的大小肯定是小于 int 类型的,所以我们计算时就要把char,short提升成 int(unsigned int)类型,再执行运算。

方法

整型提升是按照变量的数据类型的符号位来提升的,char x = -1 中,x的二进制位(补码)只有8个比特位,char为有符号的char所以整型提升时,高位补充符号位,即为1;无符号整型提升,高位补0。

就拿刚刚的代码进行剖析:

int main()
{
char a = 5;
//5 = 0000……0101(32位)
//char类型一个字节8个比特位,就只能从5的二进制数中获取8位
//即a=00000101
//这一步叫截断
char b = 126;
//126 = 0000……01111110(32位)
//b = 01111110
char = a+b;
//当a,b相加时整型提升
//111111111……0000011
//111111111……0000010
//100000000……1111101(符号位不变,其他位按位取反)=-125
printf("%d\n",c);//
return 0;

下面这个代码就可以证明整型提升的存在:

int main()
{
char c= 1;
printf("%u\n",sizeof(c));
printf("%u\n",sizeof(+c));
printf("%u\n",sizeof(-c));
return 0;
}

从运行结果来看,为什么会是 4 呢?其实就是因为他参与了运算,进行了整型提升,变成了int类型。

算术转换

我们在刚刚谈的是 char 和 short 的计算,那如果是int 和 long ,int 和long long,int 和 float 以及 double计算呢?他们发生的就是算术转换。总的来说就是4字节以下的属于整型提升,大于4的属于算术转换。

是指如果其中操作符的各个操作数为不同类型,除非其中一个转换成另一个类型,否则无法进行操作。下面层次的系统称为寻常算术转换

char
short
int
long
long long
float
double

short a = 10;
int b = 5;
prinft("%d\n",sizeof(a+b+1));

printf 结果是 2 ,是因为short只有两个字节大小,在表达式中 short a 当家做主,不管放什么进来都是short,但是,sizeof 内部多表达式其实不会真实计算,我们写文件通常是 test.c,要生成 .exe 的可执行文件三步走:编译,链接,运行。在表达式进去在编译的时候就变成 2 了,根本到不了运行。

如果某个数类型在上表中排名较低,那会首先转换到另一个操作数的类型后执行运算。
PS.算术转换要合理,不然会出现潜在问题。
比如把 float 类型变成 int 类型就会造成精度丢失。

操作符属性

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

1.操作符优先级

2.操作符结合性

3.是否控制求值顺序

首先优先级是在求值时,相邻两个操作符先执行哪个的问题,当优先级相同时,取决于他们的结合性。

什么是结合性?举个栗子: a = b = c;

b的左右两侧都为 = 号,而 = 具有右结合性,故应该由右向左计算,即:a = (b = c),诸如此类,有表如下(片段):

还有一些关于优先级的常见错误值得注意一下:

有了上面这些属性是不是任意给一个表达式就可以确定一个唯一的计算路径呢?答案是:NO!比如一些问题表达式:

a*b+c*d+e*f;
a + --a;

第一个可能第一感觉就是三个部分依次先乘后加给扒拉出来,这就想的太简单了,如果我把 abcdef 换成表达式,那就可能会相互影响,存在潜在问题。

第二个就不是计算顺序的问题了,是取值时机的问题,左右操作数相互关联时,计算路径可能不唯一。

诸君谨记,以上代码谁写谁特么就是猪队友,谨记!

以上就是C语言操作符进阶教程(表达式求值隐式类型转换方法)的详细内容,更多关于C语言操作符表达式求值隐式类型转换的资料请关注我们其它相关文章!

(0)

相关推荐

  • C语言运算符优先级列表(超详细)

    每当想找哪个运算符优先级高时,很多时候总是想找的就没有,真让人气愤!现在,终于有个我个人觉得非常全的,分享给大家,欢迎拍砖! C语言运算符优先级 优先级 运算符 名称或含义 使用形式 结合方向 说明 1 [] 数组下标 数组名[常量表达式] 左到右 -- () 圆括号 (表达式)/函数名(形参表) -- . 成员选择(对象) 对象.成员名 -- -> 成员选择(指针) 对象指针->成员名 -- 2 - 负号运算符 -表达式 右到左 单目运算符 ~ 按位取反运算符 ~表达式 ++ 自增运算符 +

  • C语言操作符基础知识图文详解

    目录 1.算术操作符 + - * / % 2.移位操作符 >> (右移操作符) <<(左移操作符) 左移操作符:<< 右移操作符:>> 3.位操作符 3.1 & 按位与 3.2 | 按位或 3.3 ^ 按位异或 3.4 ~ 按位取反 4.赋值操作符 = 5.逻辑操作符 5.1 ! 非 5.2 && 与 5.3 || 或 6.条件运算符 ? 7.单目操作符 7.1 ! 7.2 + 正值 7.3 - 负值 7.4 & 取地址 7.

  • C语言中各种操作符的详细介绍(纯干货!)

    目录 算术操作符 移位操作符 位操作符 赋值操作符 单目操作符 (类型)   强制类型转换 条件操作符 总结 算术操作符 主要是 ( +   -   *   /    %) 五种算数操作符. 1.除了 % 操作符之外,其他的几个操作符可以作用于整数和浮点数. 2. 对于 / 操作符如果两个操作数都为整数,执行整数除法.而只要有浮点数执行的就是浮点数除 法. 3..% 操作符的两个操作数必须为整数.返回的是整除之后的余数. 当除数为小数时,int类型只会截取整数部分. 移位操作符 << 左移操作

  • C语言操作符基础知识详解

    目录 一.单目操作符: 二.关系操作符 三.条件操作符 四.逗号表达式 五.逻辑操作符 总结 一.单目操作符: !:逻辑反操作符: -:负数操作符: +:整数操作符: &:取地址操作符: sizeof:操作数的类型长度操作符: sizeof(数组名)--数组名表示整个数组,sizeof(数组名)求的是整个数组的大小,单位是字节 例如: int a[10] = { 0 }; printf("%d\n",sizeof(a)); suzeof(a[0]);-->(4) 不同的表

  • C语言操作符进阶教程(表达式求值隐式类型转换方法)

    目录 结构体 表达式求值 隐式类型转换 意义: 方法 算术转换 操作符属性 结构体 结构体变量的声明需要在主函数之上或者主函数中声明,如果在主函数之下则会报错,而且c语言中的结构体不能直接进行强制转换,只有结构体指针才能进行强制转换. 涉及结构体的操作符这里讲两个:. (结构体访问操作符)-> () 首先写一段代码: int main() { struct Stu s = {"me",19,60}; prinft("%s %d %lf",s.who,s.age

  • C语言中栈和队列实现表达式求值的实例

    C语言中栈和队列实现表达式求值的实例 实现代码: #include<stdio.h> #include<stdlib.h> #define OK 1 #define ERROR 0 #define STACK_SIZE 20 #define STACK_INCREMENT 10 #define QUEUE_SIZE 20 typedef int Status; typedef char StackElemtype; typedef struct Stack{ StackElemty

  • 浅谈C/C++ 语言中的表达式求值

    经常可以在一些讨论组里看到下面的提问:"谁知道下面C语句给n赋什么值?" m = 1; n = m+++m++; 最近有位不相识的朋友发email给我,问为什么在某个C++系统里,下面表达式打印出两个4,而不是4和5: a = 4; cout << a++ << a; C++ 不是规定 << 操作左结合吗?是C++ 书上写错了,还是这个系统的实现有问题? 注:运行a = 4; cout << a++ << a; 如在Visua

  • Spring实战之使用Expression接口进行表达式求值操作示例

    本文实例讲述了Spring使用Expression接口进行表达式求值操作.分享给大家供大家参考,具体如下: 一 Bean package org.crazyit.app.domain; import java.util.Date; public class Person { private Integer id; private String name; private Date birth; // 无参数的构造器 public Person() { } // 初始化全部成员变量的构造器 pub

  • JavaScript数据结构中栈的应用之表达式求值问题详解

    本文实例讲述了JavaScript数据结构中栈的应用之表达式求值问题.分享给大家供大家参考,具体如下: 下面来谈一个比较经典的表达式求值问题,这个问题主要是设计到操作符的优先级.我们通常看到的表达式都是中缀表达式,存在很多优先级差别,而后缀表达式则没有这些优先级问题.下面先看看两种表达式的区别. 中缀表达式:a*b+c*d-e/f      后缀表达式:ab*cd*+ef/- 从中缀表达式转换到后缀表示式是很难实现的,我们这里可以通过栈的思想来实现.下面进行详细的介绍是什么样的思想: 在对一个中

  • JS实现可针对算术表达式求值的计算器功能示例

    本文实例讲述了JS实现可针对算术表达式求值的计算器功能.分享给大家供大家参考,具体如下: HTML部分: <div> <div id="in"> <input name="in" type="text" class="clsin" id="input" value="" readonly="readonly" /> <inpu

  • PHP实现基于栈的后缀表达式求值功能

    本文实例讲述了PHP实现基于栈的后缀表达式求值功能.分享给大家供大家参考,具体如下: 后缀表达式概述 后缀表达式,指的是不包含括号,运算符放在两个运算对象的后面,所有的计算按运算符出现的顺序,严格从左向右进行(不再考虑运算符的优先规则). 实现代码: <?php class Stack{ public $stack; public $stack_top; public function __construct(){ $this->stack=array(); $this->stack_t

  • Java栈的运用之中缀表达式求值详解

    目录 栈运用题:中缀表达式求值 题目详情 解题思路 实现代码 栈运用题:中缀表达式求值 题目详情 给定一个表达式,其中运算符仅包含 +,-,*,/(加 减 乘 整除),可能包含括号,请你求出表达式的最终值. 注意: 数据保证给定的表达式合法. 题目保证符号 - 只作为减号出现,不会作为负号出现,例如,-1+2,(2+2)*(-(1+1)+2) 之类表达式均不会出现. 题目保证表达式中所有数字均为正整数. 题目保证表达式在中间计算过程以及结果中,均不超过 231−1. 题目中的整除是指向 0 取整

  • C++利用链栈实现表达式求值

    本文实例为大家分享了C++利用链栈实现表达式求值的具体代码,供大家参考,具体内容如下 #include<iostream.h> typedef int Status; typedef char Cstack; #define OK 1 #define ERROR 0 typedef struct StackNode { Cstack data; struct StackNode *next; }StackNode,*LinkStack; Status InitStack(LinkStack &

  • java实现任意四则运算表达式求值算法

    本文实例讲述了java实现任意四则运算表达式求值算法.分享给大家供大家参考.具体分析如下: 该程序用于计算任意四则运算表达式.如 4 * ( 10 + 2 ) + 1 的结果应该为 49. 算法说明: 1. 首先定义运算符优先级.我们用一个 Map<String, Map<String, String>> 来保存优先级表.这样我们就可以通过下面的方式来计算两个运算符的优先级了: /** * 查表得到op1和op2的优先级 * @param op1 运算符1 * @param op2

随机推荐