当前位置: 首页 > news >正文

C、C++打印地址用%u

文章目录

      • `%u`的含义
      • 使用`%u`打印地址的问题
      • 示例代码
      • 代码解释
      • 代码中不同打印方式的分析
        • 1. `printf("Using %%u: %u\n", (unsigned int)ptr);`
        • 2. `printf("Using %%p: %p\n", (void*)ptr);`
        • 3. `std::cout << "Using std::cout: " << ptr << std::endl;`
      • 结果不同的原因

首先,使用%u编译是不会报错的,在C/C++中,不建议使用 %u来打印地址。下面从 %u的含义、使用 %u打印地址的问题以及正确的打印地址方式这几个方面详细说明。

%u的含义

printf系列函数中,%u是格式控制符,用于以无符号十进制整数的形式输出一个值。它通常用于打印unsigned int类型的数据。

使用%u打印地址的问题

  • 类型不匹配:在C++里,地址(指针)的类型是void*或者具体类型的指针(如int*char*等),指针的大小和表示方式可能因操作系统和编译器而异。例如,在32位系统中指针通常是32位(4字节),在64位系统中指针通常是64位(8字节)。而%u期望的是unsigned int类型,在64位系统中,unsigned int通常是32位,这就会导致类型不匹配,可能会丢失指针的高32位信息。
  • 可移植性问题:使用%u打印地址会使代码的可移植性变差。因为不同的系统和编译器对于指针大小和整数类型的长度有不同的规定,代码在不同环境下运行可能会产生不同的结果。

示例代码

#include <iostream>
#include <cstdio>

int main()
{
    int num = 10;
    int* ptr = &num;

    // 使用 %u 打印地址(不推荐)
    printf("Using %%u: %u\n", (unsigned int)ptr); 

    // 正确的打印地址方式
    printf("Using %%p: %p\n", (void*)ptr); 
    std::cout << "Using std::cout: " << ptr << std::endl;

    return 0;
}

在这里插入图片描述
上面是64位,%u此时就是错的
在这里插入图片描述
32位 OK

代码解释

  • 使用%u打印地址printf("Using %%u: %u\n", (unsigned int)ptr); 这里将指针ptr强制转换为unsigned int类型后使用%u打印,在64位系统中可能会丢失高32位信息。
  • 正确的打印地址方式
    • 使用%pprintf("Using %%p: %p\n", (void*)ptr); %p是专门用于打印指针地址的格式控制符,它会以合适的格式输出指针的值,保证了在不同系统和编译器下的正确性。
    • 使用std::coutstd::cout << "Using std::cout: " << ptr << std::endl; 在C++中,std::cout可以直接输出指针的地址,它会自动处理指针类型并以合适的格式输出。
      在上述代码中,使用不同方式打印指针地址得到不同结果,即便在32位系统中也可能出现这种情况,下面详细分析每种打印方式及结果差异的原因。

代码中不同打印方式的分析

#include <iostream>
#include <cstdio>

int main()
{
    int num = 10;
    int* ptr = &num;

    // 使用 %u 打印地址(不推荐)
    printf("Using %%u: %u\n", (unsigned int)ptr);

    // 正确的打印地址方式
    printf("Using %%p: %p\n", (void*)ptr);
    std::cout << "Using std::cout: " << ptr << std::endl;
    system("pause");
    return 0;
}
1. printf("Using %%u: %u\n", (unsigned int)ptr);
  • 原理:这里使用%u格式说明符,它用于以无符号十进制整数形式输出数据。代码将指针ptr强制转换为unsigned int类型,然后用%u打印。在32位系统中,虽然unsigned int和指针通常都是32位,但这种转换可能会丢失一些信息。因为%u只是简单地将指针的二进制表示解释为无符号整数进行输出。
  • 问题:这种方式没有考虑指针本身的语义,只是将其当作普通整数处理。如果指针的值包含了特殊的位模式,那么打印出来的无符号整数可能没有直观的地址含义,而且这种做法不具有可移植性,在64位系统中会出现更严重的问题。
2. printf("Using %%p: %p\n", (void*)ptr);
  • 原理%p是专门用于打印指针地址的格式说明符。它会以一种符合系统指针表示规范的方式输出指针的值,通常是十六进制形式。将ptr转换为void*类型是为了确保以通用的指针类型进行输出,因为%p期望的参数类型是void*
  • 特点:这种方式能够正确地将指针的地址以标准的十六进制格式输出,结果直观且符合我们对地址的认知,是打印指针地址的标准做法。
3. std::cout << "Using std::cout: " << ptr << std::endl;
  • 原理:在C++中,std::cout流对象重载了对指针类型的输出操作符。当输出一个指针时,它会以十六进制的形式输出指针的地址。对于int*类型的指针,它会将指针所指向的内存地址以十六进制字符串的形式输出。
  • 特点:这是C++中常用的输出指针地址的方式,简单方便,并且输出结果也是符合我们对地址表示的预期。

结果不同的原因

  • 格式说明符语义不同%u是用于输出无符号整数,它不考虑指针的特殊性质,只是简单地将指针的二进制值解释为整数输出;而%pstd::cout都专门处理指针类型,会以标准的十六进制地址格式输出。
  • 显示形式差异%u输出的是十进制无符号整数,而%pstd::cout输出的是十六进制地址,两种进制表示下数值的外观不同,这也导致我们看到的打印结果不一样。

综上所述,虽然在32位系统中unsigned int和指针大小相同,但由于不同打印方式的语义和显示格式不同,会导致打印指针地址的结果不一样。并且使用%u打印指针地址不推荐,因为它可能导致结果不符合预期且缺乏可移植性。

综上所述,为了保证代码的正确性和可移植性,不建议使用%u来打印地址,而应该使用%p或者std::cout

相关文章:

  • DeepSeek面试——分词算法
  • 搭建基于flask的web应用框架
  • 源代码防泄漏之反向沙箱篇
  • 射频相关概念
  • 利用余弦相似度在大量文章中找出抄袭的文章
  • Peach配置文件中<Agent>模块的作用及参数解析
  • 分页查询的实现
  • ELK(Elasticsearch、Logstash、Kbana)安装及Spring应用
  • 【大模型】知识蒸馏(knowledge distillation)算法详解
  • Oracle中的INHERIT PRIVILEGES权限
  • 【搭建环境】windows环境redis\集群;rabbitmq
  • 通过mybatis的拦截器对SQL进行打标
  • 【GIT】什么是GitHub Actions ?
  • 【数据分享】1999—2023年地级市地方一般公共预算收支状况数据(科学技术支出/教育支出等)
  • python--面试题--基础题
  • Python的字符串优雅优化策略:特定编码 -> Unicode码点 -> UTF-8(可自定义)
  • MySQL的事务机制
  • Caused by: java.lang.ClassNotFoundException: jakarta.servlet.ServletContext
  • 每日一题——点击消除
  • 从零基础到能独立设计单片机产品,一般需要经历哪些学习阶段?
  • CBA官方对孙铭徽罚款3万、广厦投资人楼明停赛2场罚款5万
  • 水果预包装带来的环境成本谁来分担?
  • 中国旅马大熊猫“福娃”和“凤仪”启程回国
  • 北方首场高温将进入鼎盛阶段,江南华南多地需警惕降雨叠加致灾
  • 广东缉捕1名象牙走私潜逃非洲“红通”逃犯
  • 朱雀二号改进型遥二运载火箭发射成功