C++ Primer 第4章 表达式

news2024/10/6 22:24:59

C++ Primer 第4章 表达式

  • 4.1 基础
    • 4.1.1 基本概念
      • 一、组合运算符和运算对象
      • 二、运算对象转换
      • 三、重载运算符
      • 四、左值和右值
    • 4.1.2 优先级与结合律
      • 一、括号无视优先级与结合律
      • 二、优先级与结合律有何影响
    • 4.1.3 求值顺序
      • 一、求值顺序、优先级、结合律
  • 4.2 算术运算符
    • 练习
  • 4.3 逻辑和关系运算符
    • 一、逻辑与和逻辑或运算符
    • 二、逻辑非运算符
    • 三、关系运算符
    • 四、相等性测试与布尔字面值
  • 4.4 赋值运算符
    • 一、赋值运算满足右结合律
    • 二、赋值运算优先级较低
    • 三、切勿混淆相等运算符和赋值运算符
    • 四、复合赋值运算符
  • 4.5 递增和递减运算符
    • 一、在一条语句中混用解引用和递增运算符
    • 二、运算对象可按任意顺序求值
  • 4.6 成员访问运算符
  • 4.7 条件运算符
    • 一、嵌套条件运算符
    • 二、在输出表达式中使用条件运算符
  • 4.8 位运算符
    • 一、移位运算符
    • 二、位求反运算符
    • 三、位与、位或、位异或运算符
    • 四、使用位运算符
    • 五、移位运算符(又叫IO运算符)满足左结合律
    • 练习
  • 4.9 sizeof运算符
  • 4.10 逗号运算符
    • 练习
  • 4.11 类型转换
    • 一、何时发生隐式类型转换
    • 4.11.1 算术转换
      • 一、整型提升
      • 二、无符号类型的运算对象
      • 三、理解算术转换
    • 4.11.2 其他隐式类型转换
    • 4.11.3 显式转换
      • 一、命名的强制类型转换
      • 二、旧式的强制类型转换
  • 4.12 运算符优先级表
  • 小结

表达式由一个或多个运算对象组成,对表达式求值将得到一个结果。字面值和变量是最简单的表达式,其结果就是字面值和变量的值。把一个运算符和一个或多个运算对象组合起来可以生成较复杂的表达式。

4.1 基础

4.1.1 基本概念

一元运算符:作用于一个运算对象的运算符。
二元运算符:作用于两个运算对象的运算符。
三元运算符
函数调用也是一种特殊的运算符,它对运算对象的数量没有限制。

一、组合运算符和运算对象

二、运算对象转换

三、重载运算符

我们使用重载运算符时,其包括运算对象的类型和返回值的类型,都是由该运算符定义的;但是运算对象的个数、运算符的优先级和结合律都是无法改变的。

四、左值和右值

左值可以位于赋值语句的左侧,右值则不能。
当一个对象被用作右值的时候,用的是对象的值(内容);当对象被用作左值的时候,用的是对象的身份(在内存中的位置)。
(1)赋值运算符需要一个(非常量)左值作为其左侧运算对象,得到的结果也仍然是 一个左值。
(2)取地址符作用域一个左值运算对象,返回一个指向该运算对象的指针,这个指针是一个右值。
(3)内置解引用运算符、下标运算符、迭代器解引用运算符、string和vector的下标运算符的求值结果都是左值。
(4)内置类型和迭代器的递增递减运算符作用于左值运算对象,其前置版本所得到的结果是左值。
如果表达式的求值结果是左值,decltype作用于该表达式(不是变量)得到一个引用类型。例,假定p的类型是int*,因为解引用运算符生成左值,所以decltype(*p)的结果是int&。另一方面,因为取地址运算符生成右值,所以decltype(&p)的结果是int **,结果是一个指向整型指针的指针。

4.1.2 优先级与结合律

算术运算符满足左结合律,意味着如果运算符的优先级相同,将按照从左向右的顺序组合运算对象。

一、括号无视优先级与结合律

二、优先级与结合律有何影响

4.1.3 求值顺序

对于那些没有指定执行顺序的运算符来说,如果表达式指向并修改了同一个对象,将会引发错误并产生未定义的行为。
有四种运算符明确规定了运算对象的求值顺序:逻辑与运算符(&&)、逻辑或运算符(||)、条件运算符(?:)、逗号运算符(,)。

一、求值顺序、优先级、结合律

表达式:f() + g() * h() + j()
优先级规定,g()的返回值和h()的返回值相乘
结合律规定,f()的返回值先于g()和h()的乘积相加,所得结果再与j()的返回值相加
对于这些函数的调用顺序没有明确规定

4.2 算术运算符

在这里插入图片描述
算术运算符的运算对象和求值结果都是右值。
在表达式求值之前,小整数类型的运算对象被提升成较大的整数类型,所有运算对象最终会转换成同一类型。

// 一元正号运算符作用于一个指针或者算术值时,返回运算对象值的一个(提升后的)副本
// 一元负号运算符对运算对象值取负后,返回其(提升后的)副本
int i = 1024;
int k = -i; // k是-1024
bool b = true;
bool b2 = -b; // b2是true

// 整数相除结果还是整数,商一律向0取整(即直接切除小数部分)
int ival1 = 21 / 6; // 3

// 参与取余运算的运算对象必须是整数类型
int ival = 42;
double dval = 3.14;
ival % 12; // 6
ival % dval; // 错误

// (-m)/n和m/(-n)都等于-(m/n)
// m%(-n)等于m%n,(-m)%n等于-m%n
#include <iostream>

using namespace std;

int main()
{
    int i = 10;
    int *p = &i;
    cout << *p << endl; // 10
    cout << &i << endl;
    cout << p << endl; // 变量i的地址
    int *pt = +p;
    cout << *pt << endl; // 10
    cout << pt << endl; // 变量i的地址

    return 0;
}

练习

溢出是一种常见的算术运算错误。因为在计算机中存储某种类型的内存空间有限,所以该类型的表示能力(范围)也是有限的,当计算的结果值超出这个范围时,就会产生未定义的数值,这种错误称为溢出。

4.3 逻辑和关系运算符

运算对象和求值结果都是右值。
在这里插入图片描述

一、逻辑与和逻辑或运算符

先求左侧运算对象的值再求右侧运算对象的值,当且仅当左侧运算对象无法确定表达式的结果时才会计算右侧运算对象的值。

二、逻辑非运算符

三、关系运算符

if (i < j <k) ——if语句的条件部分首先把i、j和第一个<运算符组合在一起,其返回的布尔值再作为第二个<运算符的左侧运算对象。也就是说,k比较的对象是第一次比较得到的那个或真或假的结果。

四、相等性测试与布尔字面值

if (val) // 如果val是任意的非0值,条件为真
if (!val) // 如果val是0,条件为真
if (val == true) // 只有val等于1时条件才为真
// 进行比较运算时除非比较的对象是布尔类型,否则不要使用布尔字面值true和false作为运算对象

4.4 赋值运算符

赋值运算符的左侧运算对象必须是一个可修改的左值。赋值运算的结果是它的左侧运算对象。

int i = 0, j = 0, k = 0; // 初始化而非赋值
const int ci = i; // 初始化而非赋值
1024 = k; // 错误,字面值是右值
i + j = k; // 错误,算术表达式是右值
ci = k; // 错误,ci是常量左值

// C++11新标准允许使用花括号括起来的初始值列表作为赋值语句的右侧运算对象
k = {3.14}; // 错误,窄化转换
vector<int> vi;
vi = {0, 1, 2, 3, 4, 5};

一、赋值运算满足右结合律

int ival, *pval;
ival = pval = 0; // 错误,不能把指针的值赋给int
string s1, s2;
s1 = s2 = "OK"; // 正确,字符串字面值"OK"转换成string对象

二、赋值运算优先级较低

三、切勿混淆相等运算符和赋值运算符

if (i = j) // 若j的值非0,则表达式恒为真

四、复合赋值运算符

4.5 递增和递减运算符

两种形式:前置版本和后置版本。前置版本将对象本身作为左值返回,后置版本则将对象原始值的副本作为右值返回。

一、在一条语句中混用解引用和递增运算符

auto pbeg = v.begin();
while(pbeg != v.end() && *pbeg >= 0)
	cout << *pbeg++ << endl; 
// 后置递增运算符的优先级高于解引用运算符,先将pbeg加1,然后返回pbeg的初始值的副本作为其求值结果,此时解引用云端福的运算对象是pbeg未增加之前的值。因此这条语句输出pbeg开始时指向的那个元素,并将指针向前移动一个位置

二、运算对象可按任意顺序求值

4.6 成员访问运算符

string s1 = "a string", *p = &s1;
auto n = s1.size();
n = (*p).size();
n = p->size();
// 解引用运算符的优先级低于点运算符
*p.size(); // 错误,p是一个指针,它没有名为size的成员

箭头运算符作用于一个指针类型的运算对象,结果是一个左值。点运算符分成两种情况:如果成员所属的对象是左值,那么结果是左值;反之,如果成员所属的对象是右值,那么结果是右值。

4.7 条件运算符

cond ? expr1 : expr2;
cond是判断条件的表达式
expr1和expr2是两个类型相同或可能转换为某个公共类型的表达式

当条件运算符的两个表达式都是左值或者能转换成同一种左值类型时,运算的结果是左值;否则运算的结果是右值。

int a = 10;
int b = 20;
((a > b) ? a : b) = 100; // 正确,左侧条件表达式运算结果为左值

一、嵌套条件运算符

string finalgrade = (grade > 90) ? "high pass" : (grade < 60) ? "fail" : "pass";

条件运算符满足右结合律,意味着运算对象(一般)按照从右向左的顺序组合

二、在输出表达式中使用条件运算符

cout << ((grade < 60) ? "fail" : "pass"); // 输出pass或fail
cout << (grade < 60) ? "fail" : "pass"; // 输出1或0
// 等价为 
// cout << (grade < 60);
// cout ? "fail" : "pass";
cout << grade < 60 ? "fail" : "pass"; // 错误:试图比较cout和60

4.8 位运算符

位运算符用于整数类型的运算对象,并把运算对象看成是二进制位的集合。位运算符提供检查和设置二进制位的功能。
在这里插入图片描述
如果运算对象是带符号的且它的值为负,那么位运算符如何处理运算对象的“符号位”依赖于及其。而且,此时的左移操作可能会改变符号位的值,因此使一种未定义的行为。
异或:不同为1,相同为0

一、移位运算符

令左侧运算对象的内容按照右侧运算对象的要求移动指定位数,然后经过移动的左侧运算对象的拷贝作为求值结果。其中,右侧的运算对象一定不能为负,而且值必须严格小于结果的位数,否则就会产生未定义的行为。二进制位或者向左移(<<)或者向右移(>>),移出边界之外的位就被舍弃掉了。
在这里插入图片描述
左移运算符(<<)在右侧插入值为0的二进制位。右移运算符(>>)的行为则依赖于其左侧运算对象的类型:如果该运算对象是无符号类型,在左侧插入值为0的二进制位;如果该运算对象是带符号类型,在左侧插入符号位的副本或者值为0的二进制位,如何选择要视具体环境而定。

二、位求反运算符

位求反运算符(~)将运算对象逐位求反后生成一个新值,将1置为0、将0置为1。
在这里插入图片描述
char类型的运算对象首先提升成int类型,提升时运算对象原来的位保持不变,往高位添加0即可。

三、位与、位或、位异或运算符

在这里插入图片描述

四、使用位运算符

unsigned long quiz1 = 0; // 把这个值当成是位的集合来使用
// 序号为27的学生对应的位置1,表示他通过了测验
1UL << 27 // 生成一个值,该值只有第27位为1
quiz1 |= 1UL << 27; // 表示学生27通过了测验
quiz1 |= (1UL << 27 | 1UL << 25);
quiz1 &= ~(1UL << 27); // 表示学生27没有通过测验
quiz1 &= ~(1UL << 27 | 1UL << 25)
bool status = quiz1 & (1UL << 27); //学生27是否通过了测验?

五、移位运算符(又叫IO运算符)满足左结合律

练习

在这里插入图片描述

4.9 sizeof运算符

sizeof运算符返回一条表达式或一个类型名字所占的字节数。sizeof运算符满足右结合律,其所得的值是一个size_t类型的常量表达式,sizeof并不实际计算其运算对象的值。

Sales_data data, *p;
sizeof *p;
因为sizeof满足右结合律并且与*运算符的优先级一样,所以表达式按照从右向左的顺序结合,因此它等价于sizeof(*p)
因为sizeof不会实际运算对象的值,所以即使p是一个无效的指针也不会有影响

sizeof data.revenue;
sizeof Sales_data::revenue;

对数组执行sizeof运算得到整个数组所占空间的大小。
sizeof(ia) / sizeof(*ia)返回ia的元素的数量。
对string对象或vector对象执行sizeof运算只返回该类型固定部分的大小,不会计算对象中的元素占用了多少空间。

vector<int> ivect = {1, 2, 3, 4, 5};
cout << "sizeof int = " << sizeof(int) << endl; // 4
cout << "sizeof ivect = " << sizeof(ivect) << endl; // 24且不变化
vector:
	pointer _M_start;
	pointer _M_finish;
	pointer _M_end_of_storage
vector靠3个指针来管理,每个指针占8个字节(64位操作系统)

4.10 逗号运算符

逗号运算符含有两个运算对象,按照从左向右的顺序依次求值。逗号运算符真正的结果是右侧表达式的值,如果右侧运算对象是左值,那么最终的求值结果也是左值。

练习

在这里插入图片描述

4.11 类型转换

int ival = 3.541 + 3;
// 3转换成double类型,然后执行浮点数加法,所得结果的类型是double
// 在初始化过程中,加法运算得到的double类型的结果转换成int类型的值,这个值用来初始化ival

一、何时发生隐式类型转换

编译器自动地转换运算对象的类型:
(1)在大多数表达式中,比int类型小的整型值首先提升为较大的整数类型
(2)在条件表达式中,非布尔值转换成布尔类型
(3)初始化过程中,初始值转换成变量的类型;在赋值语句中,右侧运算对象转换成左侧运算对象的类型
(4)如果算术运算或关系运算的运算对象有多种类型,需要转换成同一种类型
(5)函数调用时也会发生类型转换

4.11.1 算术转换

一、整型提升

整型提升负责把小整数类型转换成较大的整数类型。对于bool、char、signed char、unsigned char、short、unsigned short等类型来说,只要它们所有可能的值都存在int里,它们就会提升成int类型;否则,提升成unsigned int类型。较大的char类型提升成int、unsigned int、long、unsigned long、long long和unsigned long long中最小的一种类型,前提是转换后的类型要能容纳远类型所有可能的值。

二、无符号类型的运算对象

如果一个运算对象是无符号类型、另外一个运算对象是带符号类型,而且其中的无符号类型不小于带符号类型,那么带符号的运算对象转换成无符号的。
剩下的一种情况是带符号类型大于无符号类型,此时转换的结果依赖于机器。如果无符号类型的所有值都能存在该带符号类型中,则无符号类型的运算对象转换成带符号类型。如果不能,那么带符号类型的运算对象转换成无符号类型。例如,如果两个运算对象的类型分别是long和unsigned int,并且int和long的大小相同,则long类型的运算对象转换成unsigned int类型;如果long类型占用的空间比int更多,则unsigned int类型的运算对象转换成long类型。

三、理解算术转换

4.11.2 其他隐式类型转换

(1)数组转换成指针:在大多数用到数组的表达式中,数组自动转换成指向数组首元素的指针。当数组被用作decltype关键字的参数,或者作为取地址符、sizeof及typeid等运算符的运算对象时,上述转换不会发生。
(2)指针的转换:常量整数值0或字面值nullptr能转换成任意指针类型;指向任意非常量的指针能转换成void*;指向对象的指针能转换成const void*。
(3)转换成布尔类型
(4)转换成常量:如果T是一种类型,能将指向T的指针或引用分别转换成指向const T的指针或引用
(5)类类型定义的转换

string s, t = "a value"; // 字符串字面值转换成string类型
while (cin >> s) // while的条件部分把cin转换成布尔值

4.11.3 显式转换

一、命名的强制类型转换

cast-name<type>(expression)
如果type是引用类型,则结果是左值
cast-name是static_cast、dynamic_cast、const_cast、reinterpret_cast

(1)static_cast:任何具有明确定义的类型转换,只要不包含底层const,均可使用

void *p = &d;
double *dp = static_cast<double*>(p);

(2)const_cast:只能改变运算对象的底层const,常用于有函数重载的上下文中

const char *pc;
char *p = const_cast<char*>(pc); // 正确,但是通过p写值是未定义的行为

const char *cp;
char *q = static_cast<char*>(cp); // 错误:static_cast不能转换掉const性质
static_cast<string>(cp); // 正确:字符串字面值转换成string类型
const_cast<string>(cp); // 错误:const_cast只改变常量属性

const int a = 10;
int b = const_cast<int>(a); // 错误,只能改变指针或引用的底层const属性 
#include <iostream>

using namespace std;

int main()
{
    const int a = 10;
    int *pt = const_cast<int *>(&a);
    int &r = const_cast<int &>(a);
    *pt = 20;
    cout << "*pt = " << *pt << endl; // 20
    cout << "r = " << r << endl; // 20
    cout << "a = " << a << endl; // 10:编译器优化,通过pt修改的是内存的值,而a保存在寄存器中

    return 0;
}

(3)reinterpret_cast

二、旧式的强制类型转换

type (expr); // 函数形式的强制类型转换
(type) expr; // C语言风格的强制类型转换

4.12 运算符优先级表

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

小结

C++语言提供了一套丰富的运算符,并定义了这些运算符作用域内置类型的运算对象时所执行的操作。此外,C++语言还支持运算符重载的机制,允许我们自己定义运算符作用于类类型时的含义。
对于含有超过一个运算符的表达式,要想理解其含义关键要理解优先级、结合律和求值顺序。每个运算符都有其对应的优先级和结合律,优先级规定了复合表达式中运算符组合的方式,结合律则说明当运算符的优先级一样时应该如何组合。
大多数运算符并不明确规定运算对象的求值顺序:编译器有权自由选择先对左侧运算对象求值还是先对右侧运算对象求值。一般来说,运算对象的求值顺序对表达式的最终结果没有影响。但是,如果两个运算对象指向同一个对象而且其中一个改变了对象的值,就会导致程序出现不易发现的严重缺陷。
最后一点,运算对象经常从原始类型自动转换成某种关联的类型。例如,表达式中的小整型会自动提升成大整型。不论内置类型还是类类型都涉及类型转换的问题。如果需要,我们还可以显式地进行强制类型转换。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1015327.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

图片拖动验证效果(源码)

JS案例图片拖动验证 &#x1f31f;效果展示 &#x1f31f;前置知识 CSS sprite 精灵图 &#x1f31f; 代码实现 页面搭建 距离计算 逻辑部分 随机生成背景图片 计算拖动图块和空缺图块的位置 绑定事件 &#x1f31f;写在最后 &#x1f31f;效果展示 &#x1f31f;…

六、不root不magisk不xposed lsposed frida原生修改定位

前言常用风控APP检测1.Aida64检测2.momo检测3.微霸检测4.cellular-z检测 厂商测试总结 前言 不root不戴面具 不xposed lsposed frida&#xff0c;不分身&#xff0c;不多开&#xff0c;最完美的原生修改定位。 常用风控APP检测 先看效果再说原理&#xff0c;先过一遍环境 1.Ai…

mysql内连接与外连接详解

内连接与外连接 内连接外连接 在数据库中&#xff0c;连接操作是一种把两个或者多个表的记录组合在一起的操作&#xff0c;常用的有内连接&#xff08;Inner Join&#xff09;、外连接&#xff08;Outer Join&#xff09;等。 内连接 内连接&#xff08;Inner Join&#xff0…

STM32 Cubemx 通用定时器 General-Purpose Timers同步

文章目录 前言简介cubemx配置 前言 持续学习stm32中… 简介 通用定时器是一个16位的计数器&#xff0c;支持向上up、向下down与中心对称up-down三种模式。可以用于测量信号脉宽&#xff08;输入捕捉&#xff09;&#xff0c;输出一定的波形&#xff08;比较输出与PWM输出&am…

mysql 日志总结

mysql 根据日志的功能&#xff0c;分6种 慢查询日志&#xff1a;记录所有执行时间超过 long_query_time 的所有查询&#xff0c;方便我们对查询进行优化通用查询日志&#xff1a;记录所有连接的起始时间和终止时间&#xff0c;以及连接发送给数据库服务器的所有指令&#xff0…

Junit单元测试异常处理方法

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 Junit单元测试异常处理方法 前言案例准备一、类方法内处理异常二、测试方法中处理异常1.try/catch/finally 语句2.Test(expected)3.ExpectedException 前言 提示&#xff1a…

【C语言】指针和数组笔试题解析(2)

【C语言】指针和数组笔试题解析&#xff08;1&#xff09;&#xff0c; 这是第一篇关于sizeof与strlen在指针中的应用&#xff0c;而这一篇主要讲解在各种情形下的灵活运用&#xff0c;也是大厂中经典的面试题 第一题&#xff1a; int main() {int a[5] { 1, 2, 3, 4, 5 };in…

开始在 Windows 上使用 Next.js

&#x1f3ac; 岸边的风&#xff1a;个人主页 &#x1f525; 个人专栏 :《 VUE 》 《 javaScript 》 ⛺️ 生活的理想&#xff0c;就是为了理想的生活 ! 目录 必备条件 安装 Next.js 本指南帮助你安装 Next.js Web 框架并在 Windows 上启动和运行。 Next.js 是一个框架&…

利用idea新创建maven项目时的一些基本配置

1.修改项目默认的maven仓库 file->Settings->Build 2.设置项目的jdk版本 设置完点OK即可。 同样的我们还需要在项目配置中进行修改。 通过以上设置一般就可以解决jdk版本不兼容地方问题。

详细解释HiveSQL执行计划

一、前言 Hive SQL的执行计划描述SQL实际执行的整体轮廓&#xff0c;通过执行计划能了解SQL程序在转换成相应计算引擎的执行逻辑&#xff0c;掌握了执行逻辑也就能更好地把握程序出现的瓶颈点&#xff0c;从而能够实现更有针对性的优化。此外还能帮助开发者识别看似等价的SQL其…

Redis 高性能设计之epoll和IO多路复用深度解析

I/O多路复用模型是什么 I/O&#xff1a;网络I/O多路&#xff1a;多个客户端连接&#xff08;连接就是套接字描述符&#xff0c;即socket或者channel&#xff09;&#xff0c;指的是多条TCP连接复用&#xff1a;用一个进程来处理多条的连接&#xff0c;使用单进程就能的够实现同…

【Linux系统编程】操作系统的概念、定位 及系统调用

文章目录 前言1. 操作系统的概念和定位2. 如何理解“管理”3. 操作系统为什么要做管理4. 系统调用和库函数概念5. 局部性原理6. 计算机体系结构 前言 上一篇文章我们学习了冯诺依曼体系结构&#xff08;属于计算机硬件的范畴&#xff09;&#xff0c;其中我们提到&#xff0c;因…

c++静态成员变量与静态成员函数

一、静态成员变量 1、说明 1.1、所有对象共享同一份静态变量 1.2、编译阶段分配内存 1.3、类内声明&#xff0c;类外初始化操作 静态成员变量&#xff0c;不属于某个具体的类对象&#xff0c;多有的类对象共享同一份数据 因此静态成员变量有两种方式访问 2、…

阿里云大数据实战记录10:Hive 兼容模式的坑

文章目录 1、前言2、什么是 Hive 兼容模式&#xff1f;3、为什么要开启 Hive 模式&#xff1f;4、有什么副作用&#xff1f;5、如何开启 Hive 兼容模式&#xff1f;6、该场景下&#xff0c;能不能不开启 Hive 兼容模式&#xff1f;7、为什么不是DATE_FORMAT(datetime, string)&…

【小记录】jupyter notebook新版本

手欠升级 &#x1f605;今天手贱&#xff0c;在anaconda navigator里面更新了最新版本的spyder&#xff0c;然后莫名奇妙地jupyter notebook就打不开了&#x1f605;&#xff0c;报错说缺少模块”ModuleNotFoundError: No module named jupyter_server.contents“&#xff0c;…

给微信小程序添加隐私协议

前些日子&#xff0c;微信官方针对用户的安全信息又进行了增强&#xff0c;这次更新几乎要求所有的小程序都需要进行整改&#xff0c;只要是涉及到用户的隐私的小程序都需要进行整改&#xff0c;这次整改是强制性的。 点开相关指引之后会跳转到下面的链接&#xff1a;参考链接…

解决php导出excel中小数尾部0不显示的问题

调整代码前&#xff1a; 新增代码&#xff1a; //小数避免末尾0不显示的问题 foreach ($list as &$line) {foreach ($line as &$column) {if (is_numeric($column) && strpos($column, .)!false) {$column " {$column} ";}} } 效果&#xf…

【【萌新的riscV的学习之关于risc指令集的学习使用总五】】

萌新的riscV的学习之关于risc指令集的学习使用总五 opcode&#xff08;操作码&#xff09; 指令的基本操作 rd目的操作数寄存器 用来存放操作结果 funct3 一个另外的操作码字段 rs1: 第一个源操作数寄存器 rs2: 第二个源操作数寄存器 funct7: 一个另外的操作码字段 还有一种I型…

ApplicationContext实现

基于classpath下的xml格式的配置文件来创建bean对象 java代码 package com.example;import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.context.support.ClassPathXmlApplicationContext; import org.springframework.context.support.Fi…

力扣刷题班 第3课 02-分治与回溯算法

分治&#xff08;例题1&#xff09;九键电话号码的字母组合 电话号码的字⺟组合 给定⼀个仅包含数字 2-9 的字符串&#xff0c;返回所有它能表示的字⺟组合。答案可以按 任意顺序 返回。 给出数字到字⺟的映射如下&#xff08;与电话按键相同&#xff09;。注意 1 不对应任何字…