几个典型的按位运算符示例


一.题目:编写一个函数setbits(x, p ,n, y),该函数返回对x执行下列操作后的结果值: 将x中从第p位开始的n个(二进制)位设置为y中最右边n位的值,x的其余各位保持不变。

<span style="font-size:18px;">#include <stdio.h>
#include <stdlib.h>
#include "limits.h"
#include "float.h"

unsigned setbits(int x,int p,int n,int y)
{
    return x&~(~(~0<<n)<<(p + 1 - n))| (y & ~(~0 <<n )) << (p + 1 - n);
}
int main()
{
    printf("%u\n",setbits(5,4,3,6));
    int end = getchar();
    return 0;
}</span>


分析:
x的值:xxx...xnnnx...xxx     (n表示需要被替换的n位)
y的值:yy..............ynnn    
题目需要用y中的n位值替换x中的n位值。要实现该功能,需要以下几步:
我们需要对x中n位清零,把y中最右边n位其他以为的位都清零并左移到第p位处,然后进行or操作。
xxx....x000x...xxx |(or操作)
000...  nnn....000     
--------------------------
xxx....xnnnx...xxx  (操作完成,得到想要的值)


步骤分解:
1.对x中n位清零,得到【xxx....x000x...xxx】


a.得到 【111...000...111】这样的结果。一般都用0作为辅助来得到想要的结果。
~0<<n:得到【111......000】
~(~0<<n):得到【000......111】
~(~0<<n)<<(p + 1 - n):得到【000...111...000】
~(~(~0<<n)<<(p + 1 - n)):得到【111...000...111】


b.得到【xxx....x000x...xxx】结果。
上一步步骤a中的结果与【x的值:xxx...xnnnx...xxx】&与运算,得到
xxx...xnnnx...xxx
111....000....111 &
-----------------
xxx...x000x...xxx
总运算:
x &~(~(~0<< n) << (p + 1 -n))


2.对y处理,得到【000...  nnn....000】
~0<<n:得到【111......000】
~(~0<<n):得到【000......0111】
与y相与&,得到【000......0nnn】
移位运算<<(p + 1 - n)),得到:【000...  nnn....000】
总运算:
(y & ~(~0 <<n )) << (p + 1 - n)


3.合并步骤1,2,用与运算:

x &~(~(~0<< n) << (p + 1 -n)) | (y & ~(~0 <<n )) << (p + 1 - n)


二、编写函数invert(x,p,n),将函数返回对x执行下列操作后的结果值: 将x中从第p位开始的n个(二进制)位


求反(即1变成0, 0变成1), x的其余各位保持不变.
分析:
(~0<<n) : 1111 1000
~(~0<<n):0000 0111
~(~0<<n)<<(p + 1 - n):000...111...000
异或:
0^0 = 0, 
1^0 = 1, 
0^1 = 1, 
1^1 = 0
所以用【000...111...000】去和x异或,可得到想要的值。


<span style="font-size:18px;">unsigned int invert(int x,int p,int n)
{
    return x ^ (~(~0<<n)<<(p + 1 - n));
}
</span>



三、编写一个函数rightrot(x, n),该函数返回将x循环右移(即从最右端移出的位将从最左端再移入)n(二进制)位后所得到的值。
分析:
a.每次将取x最右端的那一位,将该位移到最左端
b.将x向右端移动一位
c.将a得到的值|b得到的值


<span style="font-size:18px;">int wordlength(void)
{
 int i;
 unsigned v = (unsigned) ~0;


 for(i = 1; (v = v >> 1) > 0; ++i)
  ;
 return i;
}
unsigned int rightrot(int x,int n)
{
    int ret;
    while(n-- > 0)
    {
        int rBit = (x & 1) << wordlength() - 1;
        ret = x>>1 | rBit;
    }
    return ret;
}</span>


<think>我们根据用户需求,整理C++中常见运算符重载的实现公式和示例。结合引用内容,我们将覆盖以下运算符: 1. 算术运算符(+、-、*、/) 2. 关系运算符(==、!=、>、<等) 3. 赋值运算符(=) 4. 流运算符(<<、>>) 5. 下标运算符([]) 6. 自增自减运算符(++、--) 注意:我们将按照运算符分类,给出典型的实现方式和示例代码,并遵循以下原则: - 成员函数重载:适用于需要访问私有成员且操作数不对称的情况(如+=、=等) - 友元函数重载:适用于需要对称操作的情况(如+、-、*、/等)或需要访问私有成员的流运算符 每个示例将包含: - 运算符的声明和定义 - 简要说明 - 使用示例(如果需要) 由于用户要求“实现公式”,我们将以代码示例为主,并辅以必要的解释。 开始编写:</think>### C++ 常见运算符重载实现公式与示例 #### 一、算术运算符重载 **实现公式** ```cpp ReturnType operator[符号](const ClassName& other) { // 创建临时对象并计算结果 return ClassName(this->data [运算符] other.data); } ``` **示例:复数加法** ```cpp class Complex { public: Complex operator+(const Complex& c) const { return Complex(re + c.re, im + c.im); // 返回新对象[^1] } private: double re, im; }; // 使用 Complex c1(1.0, 2.0), c2(3.0, 4.0); Complex c3 = c1 + c2; // c3 = (4.0, 6.0) ``` #### 二、关系运算符重载 **实现公式** ```cpp bool operator[符号](const ClassName& other) const { return (this->data [关系符] other.data); } ``` **示例:对象相等比较** ```cpp class Person { public: bool operator==(const Person& p) const { return (name == p.name) && (age == p.age); // 比较所有成员[^4] } private: std::string name; int age; }; // 使用 Person p1("Alice", 30), p2("Alice", 30); if (p1 == p2) { /* 执行相等逻辑 */ } ``` #### 三、赋值运算符重载 **实现公式** ```cpp ClassName& operator=(const ClassName& other) { if(this != &other) { // 防止自赋值 // 释放旧资源 → 复制新资源 } return *this; // 返回引用支持链式赋值[^3] } ``` **示例:字符串深拷贝** ```cpp class String { public: String& operator=(const String& s) { if (this != &s) { delete[] data; // 释放旧内存 data = new char[strlen(s.data) + 1]; strcpy(data, s.data); // 深拷贝 } return *this; } private: char* data; }; // 使用 String s1("Hello"), s2; s2 = s1; // 深拷贝赋值 ``` #### 四、流运算符重载 **实现公式** ```cpp friend std::ostream& operator<<(std::ostream& os, const ClassName& obj) { os << obj.member; // 输出对象成员 return os; } ``` **示例:自定义输出格式** ```cpp class Point { public: friend std::ostream& operator<<(std::ostream& os, const Point& p) { os << "(" << p.x << ", " << p.y << ")"; // 格式化输出[^1] return os; } private: int x, y; }; // 使用 Point pt(3, 4); std::cout << "坐标: " << pt; // 输出: 坐标: (3, 4) ``` #### 五、下标运算符重载 **实现公式** ```cpp ElementType& operator[](int index) { return data[index]; // 返回引用可修改 } const ElementType& operator[](int index) const { return data[index]; // const版本[^1] } ``` **示例:安全数组访问** ```cpp class SafeArray { public: int& operator[](int idx) { if(idx < 0 || idx >= size) throw std::out_of_range("越界"); return data[idx]; } private: int* data; int size; }; // 使用 SafeArray arr(10); arr[3] = 42; // 安全访问 ``` #### 六、自增运算符重载 **实现公式** ```cpp // 前置++ ClassName& operator++() { // 修改当前对象 return *this; } // 后置++ ClassName operator++(int) { ClassName temp = *this; // 保存原值 ++(*this); // 调用前置++ return temp; // 返回原值[^1] } ``` **示例:迭代器自增** ```cpp class Iterator { public: // 前置++ Iterator& operator++() { ++ptr; return *this; } // 后置++ Iterator operator++(int) { Iterator tmp = *this; ++(*this); return tmp; } private: int* ptr; }; // 使用 Iterator it; ++it; // 前置 it++; // 后置 ``` > **关键原则** > 1. 算术运算符返回新对象而非引用 > 2. 赋值运算符需处理自赋值并返回引用 > 3. 流运算符必须声明为友元函数 > 4. 关系运算符保持严格弱序性 > 5. 下标运算符提供const和非const版本[^2][^4] --- ### 相关问题 1. 如何为自定义矩阵类重载 `*` 运算符实现矩阵乘法? 2. 重载 `new` 和 `delete` 运算符有哪些特殊注意事项? 3. 在哪些场景下必须将运算符重载声明为友元函数? 4. 如何通过运算符重载实现自定义类型的隐式类型转换? 5. 运算符重载与模板结合使用时有哪些常见陷阱?
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值