拾忆🍂拾忆🍂
  • Ollama
  • OpenClaw-飞书
  • OpenClaw
  • skills
  • MySQL
  • Oracle
  • PostgreSQL
  • MyBatis
  • API升级
  • HMOS
  • HMOS 官方示例项目集
  • HDC
  • 百变小组件
  • 元服务
  • Java
  • MinIO
  • Stream
  • JSP & Struts2
  • Spring
  • FFmpeg
  • Linux
  • docker
  • Git
  • Nginx
  • 终端快捷键
  • Adobe Audition
  • Aseprite
  • cpp
  • Excel
  • K
  • Markdown基本用法
  • MuseScore 4.x
  • UVR
  • Windows
  • emoji-cheat-sheet
  • IDE快捷键
  • obs-studio
  • YOLO
  • Python
  • VuePress 2.x
  • 内置组件
  • markdown-container
  • markdown-ext
  • markdown-hint
  • markdown-preview
  • markdown-tab
  • Markdown扩展语法
  • 插件配置
  • prismjs
  • 样式
  • CSS
  • JS
  • TS
  • Vue3
主页
梦的开始🌅
  • Ollama
  • OpenClaw-飞书
  • OpenClaw
  • skills
  • MySQL
  • Oracle
  • PostgreSQL
  • MyBatis
  • API升级
  • HMOS
  • HMOS 官方示例项目集
  • HDC
  • 百变小组件
  • 元服务
  • Java
  • MinIO
  • Stream
  • JSP & Struts2
  • Spring
  • FFmpeg
  • Linux
  • docker
  • Git
  • Nginx
  • 终端快捷键
  • Adobe Audition
  • Aseprite
  • cpp
  • Excel
  • K
  • Markdown基本用法
  • MuseScore 4.x
  • UVR
  • Windows
  • emoji-cheat-sheet
  • IDE快捷键
  • obs-studio
  • YOLO
  • Python
  • VuePress 2.x
  • 内置组件
  • markdown-container
  • markdown-ext
  • markdown-hint
  • markdown-preview
  • markdown-tab
  • Markdown扩展语法
  • 插件配置
  • prismjs
  • 样式
  • CSS
  • JS
  • TS
  • Vue3
主页
梦的开始🌅
  • 「从开始,到永久」
  • AI

    • Ollama
    • OpenClaw-飞书
    • OpenClaw
    • skills
  • Database

    • MySQL
    • Oracle
    • PostgreSQL
    • MyBatis
  • HarmonyOS

    • API升级
    • HMOS
    • HMOS 官方示例项目集
    • HDC
    • 百变小组件
    • 元服务
  • Java

    • Java
    • MinIO
    • Stream
    • JSP & Struts2
    • Spring
  • Linux

    • FFmpeg
    • Linux
    • docker
    • Git
    • Nginx
    • 终端快捷键
  • Others

    • Adobe Audition
    • Aseprite
    • cpp
    • Excel
    • K
    • Markdown基本用法
    • MuseScore 4.x
    • UVR
    • Windows
    • emoji-cheat-sheet
    • IDE快捷键
    • obs-studio
    • YOLO
  • Python

    • Python
  • VuePress

    • VuePress 2.x
    • 内置组件
    • markdown-container
    • markdown-ext
    • markdown-hint
    • markdown-preview
    • markdown-tab
    • Markdown扩展语法
    • 插件配置
    • prismjs
    • 样式
  • Web

    • CSS
    • JS
    • TS
    • Vue3
  • 主页

运算符

& 和 *

  1. 星号在类型后:用于声明指针
类型名* 指针名;
int x = 10;
int* p = &x; // 定义一个指向`int`类型的指针`p`,并将它初始化为`x`变量的地址,&x 表示获取变量 x 的内存地址
*p = 20; // `x`仍然等于`10`所在的地址,但是地址中的实际值`10`现在被改为了`20`

含义

  • 定义一个指针,指向所指定类型的内存地址。
  • 指针存储的是某个变量的 内存地址,而不是变量本身的值。
数据类型& 引用名 = 变量名;

方法参数中的 * 和 &

指针传递:*

  • 表示传递指针,允许函数操作操作原始变量指向内存中实际存储的值:

    void modify(int *p) {
      *p = 20;  // 修改指针指向的值(修改这块内存实际存的值)
    }
    int x = 10;
    modify(&x);  // 传递 x 的地址
    

引用传递:&

  • 表示传引用,允许函数直接操作原始变量:

    void modify(int &ref) {
      ref = 20;  // 修改原始变量(相当于 x = 20, 而不是把20 = 10)
    }
    int x = 10;
    modify(x);  // 直接传递变量
    

在 C++ 中,& 和 * 运算符有多种用途,主要体现在 引用、指针、以及 取地址和解引用 的操作上。下面将详细解释它们在 C++ 中的不同用途。

1. & 运算符的用途

(1) 取地址运算符

  • 用法:& 在变量前表示 取地址,即获取该变量的内存地址。

  • 例子:

    int x = 10;
    int* ptr = &x;  // 取 x 的地址,并将其赋给指针 ptr
    
    • 在这个例子中,&x 返回 x 变量的内存地址,然后赋给指针 ptr。

(2) 引用声明运算符

  • 用法:& 在类型后面表示 引用。引用是一个变量的别名,它不存储数据本身,而是存储另一个变量的内存地址。

  • 例子:

    int x = 10;
    int& ref = x;  // ref 是 x 的引用,表示 ref 和 x 是同一个变量
    ref = 20;  // 修改 ref 的值,x 也变成了 20
    
    • 在这里,ref 是 x 的引用,修改 ref 会直接影响 x。

(3) 在函数参数中使用引用(传引用)

  • 用法:在函数参数中使用 & 来传递变量的引用。这样,函数会直接修改传入的参数,而不需要创建该参数的副本。

  • 例子

    :

    void modify(int& x) {
        x = 20;  // 直接修改传入的 x
    }
    
    int main() {
        int a = 10;
        modify(a);  // 传递 a 的引用
        cout << a;  // 输出 20,因为 a 被修改了
        return 0;
    }
    

2. * 运算符的用途

(1) 指针声明

  • 用法:* 在变量声明时表示 指针,即该变量存储的是另一个变量的内存地址。

  • 例子:

    int x = 10;
    int* ptr = &x;  // ptr 是指向 int 类型的指针,存储 x 的地址
    
    • 在这里,* 表示声明 ptr 为指向 int 类型的指针。

(2) 解引用运算符

  • 用法:* 在指针变量前面表示 解引用,即访问指针所指向的内存地址的值。

  • 例子:

    int x = 10;
    int* ptr = &x;  // ptr 存储 x 的地址
    cout << *ptr;  // 输出 10,解引用 ptr,访问指针指向的值
    
    • *ptr 通过解引用操作访问 ptr 指向的内存中的值,也就是 x 的值。

(3) 指针的赋值(指针指向)

  • 用法:* 用于通过指针修改其指向的内容。

  • 例子:

    int x = 10;
    int* ptr = &x;  // ptr 指向 x
    *ptr = 20;      // 通过解引用 ptr 修改 x 的值
    cout << x;      // 输出 20
    
    • *ptr = 20; 通过指针 ptr 修改了 x 的值。

(4) 返回指针

  • 用法:函数可以返回指针,通常在返回函数中分配的内存地址时使用 *。

  • 例子:

    int* getPointer() {
        int x = 10;
        return &x;  // 返回指向局部变量 x 的指针(不推荐这样做,局部变量会被销毁)
    }
    

3. & 和 * 在函数中的结合使用

(1) 传递指针的引用

  • 用法:可以使用 * 和 & 结合在一起,传递指向指针的引用,这样可以修改传入的指针(即指针本身的地址)。

  • 例子:

    void modifyPointer(int*& ptr) {
        int x = 20;
        ptr = &x;  // 修改传入指针的值,使其指向 x
    }
    
    int main() {
        int y = 10;
        int* ptr = &y;
        modifyPointer(ptr);  // 修改指针 ptr,使其指向新变量 x
        cout << *ptr;  // 输出 20,因为 ptr 现在指向 x
        return 0;
    }
    

(2) 传递引用的指针

  • 用法:传递一个指向引用的指针(指针指向一个引用)。

  • 例子:

    void modify(int* &ptr) {
        int x = 30;
        ptr = &x;  // 修改指针 ptr,使其指向 x
    }
    
    int main() {
        int y = 10;
        int* ptr = &y;
        modify(ptr);  // 修改指针,使其指向新的变量 x
        cout << *ptr;  // 输出 30,因为 ptr 现在指向 x
        return 0;
    }
    

总结:& 和 * 的主要用途

运算符用途示例
&取地址运算符:获取变量的内存地址。int* ptr = &x; 获取 x 的地址并赋给 ptr。
&引用声明运算符:声明引用类型变量。int& ref = x; ref 是 x 的引用,ref 和 x 是同一个变量。
*指针声明:声明一个指针。int* ptr; 声明一个指向 int 的指针。
*解引用运算符:访问指针指向的值。int x = 10; int* ptr = &x; cout << *ptr; 输出 x 的值。
*修改指针指向的值:通过指针修改值。*ptr = 20; 修改指针所指向变量的值。

通过 & 和 *,C++ 提供了强大的指针和引用机制,允许直接操作内存和对象,提供了高效的内存管理能力。

模运算 %

在不同语言中分别对应 取余 | 取模 运算:

  • 取余(JavaScript):a % b = a - b * Math.trunc(a / b)
    • Math.trunc() 表示向0取整(即去掉小数部分)
  • 取模(Python):a % b = a - b * math.floor(a / b)
    • math.floor() 表示向下取取整(负数可以理解为向负无穷取整)

重要

这两种方式结果的 核心差异 就在于 被除数 和 除数 是否 异号 。

如果为异号,则计算结果就不同:

  • 向0取整 的商会比 向下取整 的商大 1 。
  • 导致最终结果相差一个 |b| 。
数学概念取余取模
核心思想求除法运算后的 余数求除法运算后的 模
商的取整方式向0取整向下取整(向负无穷)
结果的符号与 被除数 的符号相同与 除数 的符号相同
示例 10 % 311
示例 -10 % 3-12
示例 10 % -31-2
示例 -10 % -3-1-1
常见语言C, C++, Java, JavaScript, GoPython, Ruby, Haskell,Lua
Python 内置取模函数(向下取整)
# quotient=-4, remainder=2(这是取模)
quotient, remainder = divmod(-10, 3)
如何模拟对方行为?

重要

由上方表格 四个示例 结合 核心差异 可以得出等式(仅在异号情况下):

JS结果+除数=Python结果JS\text{结果} + \text{除数} = Python\text{结果} JS结果+除数=Python结果

所以模拟对方行为的关键代码就有了两个实现方式:

  • 按照数学定义
  • 根据公式实现
  1. JavaScript 模拟 Python 行为

    • 手动处理为总是返回非负结果(推荐)

      // 利用双重取模技巧
      function floor_remainder(a, b) {
          if (b === 0) return Number.NaN
          // 第二次“取模”是在避免处理同号问题时,余数未落在正确区间的问题
          return ((a % b) + b) % b
      }
      

      重要

      把内部的 (a % b) 看做是 x ,(x + b) % b 不会改变 模b 下的等价类。

      提示

      那什么是"模 b 下的等价类"?

      想象把所有整数按照"除以 b 的余数"来分组:

      以 b = 3 为例:

      • 余数为 0 的数:..., -6, -3, 0, 3, 6, 9, ...(这些数在 模3下 是"等价的")
      • 余数为 1 的数:..., -5, -2, 1, 4, 7, 10, ...
      • 余数为 2 的数:..., -4, -1, 2, 5, 8, 11, ...

      每个这样的分组就是一个等价类。

      对于任意 x = a % b:

      1. 第一步:x + b

        • 这保证了结果是正数吗?不一定!
        • 但保证了我们还在同一个等价类中
      2. 第二步:(x + b) % b

        • 这确保最终结果在标准范围内 [0, |b|)
    • 控制结果符号与 除数 相同

      function floor_remainder(a, b) {
          // 先得到 JS 原生的余数
          let result = a % b
      
          // 如果结果的符号与除数 `b` 的符号不同
          if (result !== 0 && (b < 0 ? result > 0 : result < 0)) {
              // 加上除数来调整符号(利用结果相差一个 `|b|` 特性)
              result += b
          }
          return result;
      }
      
  2. Python 模拟 JavaScript 行为

    • 使用 math.fmod()(推荐)

      import math
      
      def trunc_remainder(a, b):
          if b == 0:
              return float('nan')
          return math.fmod(a, b)
      
    • 使用 math.trunc 去掉小数(向0取整)

      import math
      
      def trunc_remainder(a, b):
          if b == 0:
              return float('nan')
          # 或使用整除运算a - b * (a // b)
          return a - b * math.trunc(a / b)
      
    • 控制结果符号与 被除数 相同

      def trunc_remainder(a, b):
          if b == 0:
              return float('nan')
          result = a % b  # Python 的取模
      
          # 调整符号:如果结果不为零且符号与 JS 期望的不同
          if result != 0 and ((a < 0) != (result < 0)):
              # 结果符号应该与 a 相同,但现在是 b 的符号
              if b > 0:
                  result -= b
              else:
                  result += b
          return result
      
最近更新: 2026/2/27 12:23
Contributors: Enlin
Prev
Aseprite
Next
Excel