• [技术干货] 【C++笔记】C++和C语言的类型转换对比分析-转载
    一 C中的类型转换在C语语言中,如果赋值运算符左右两侧类型不同,或者形参与实参类型不匹配,或者返回值类型与接收返回值类型不⼀致时等场景,就需要发生类型转化,C语言中总共有两种形式的类型转换:隐式类型转换和显式强制类型转换。隐式类型转化:编译器在编译阶段自动进行,能转就转,不能转就编译失败显式强制类型转化:需要用户自己去显示在变量前用括号指定要转换的类型并不是任意类型之前都支持转换,两个类型支持转换需要有⼀定关联性,也就是说转换后要有⼀定的意义,两个毫无关联的类型是不支持转换的。#include<stdio.h>#include<stdlib.h>int main(){int i = 1;// 隐式类型转换// 隐式类型转换主要发⽣在整形和整形之间,整形和浮点数之间,浮点数和浮点数之间double d = i;printf("%d, %.2f\n", i, d);int* p = &i;// 显⽰的强制类型转换// 强制类型转换主要发⽣在指针和整形之间,指针和指针之间int address = (int)p;printf("%p, %d\n", p, address);// malloc返回值是void*,被强转成int*int* ptr = (int*)malloc(8);// 编译报错:类型强制转换:⽆法从“int* ”转换为“double”// 指针是地址的编号,也是⼀种整数,所以可以和整形互相转换    // 但是指针和浮点数毫⽆关联,强转也是不⽀持的    // d = (double)p;return 0;}二. C++中的类型转换C++兼容C,所以C支持的隐式类型转换和显式强制类型转换C++都支持。C++还支持内置类型到自定义类型之间的转换,内置类型转成自定义类型需要构造函数的支持,自定义类型转成内置类型,需要一个operator类型()的函数去支持。C++还支持自定义类型到自定义类型之间的转换,需要对应类型的构造函数支持即可,比如A类型对象想转成B类型,则支持一个形参为A类型的B构造函数即可支持。三. C++显示强制类型转换3.1类型安全类型安全是指编程语言在编译和运行时提供保护机制,避免非法的类型转换和操作,导致出现一个内存访问错误等,从而减少程序运行时的错误。C语言不是类型安全的语言,C语言允许隐式类型转换,一些特殊情况下就会导致越界访问的内存错误,其次不合理的使用强制类型转换也会导致问题,比如一个int的指针强转成double访问就会出现越界。C++兼容C语言,支持隐式类型转换和强制类型转换,C++也不是类型安全的语言,C++提出4个显示的命名强制类型转换static_cast/reinterpret_cast/const_cast/dynamic_cast就是为了让类型转换相对而言更安全。void insert(size_t pos, char ch){// 这⾥当pos == 0时,就会引发由于隐式类型转换// end跟pos⽐较时,提升为size_t导致判断结束逻辑出现问题    // 在数组中访问挪动数据就会出现越界,经典的类型安全问题    int end = 10;while (end >= pos){// ...cout << end << endl; --end;}}int main(){insert(5, 'x');//insert(0, 'x');// 这⾥会本质已经出现了越界访问,只是越界不⼀定能被检查出来int x = 100;double* p1 = (double*)&x;cout << *p1 << endl;const int y = 0;int* p2 = (int*)&y;(*p2) = 1;// 这⾥打印的结果是1和0,也是因为我们类型转换去掉了const属性// 但是编译器认为y是const的,不会被改变,所以会优化编译时放到    // 寄存器或者直接替换y为0导致的cout << *p2 << endl;cout << y << endl;return 0;}3.2 C++中4个显示强制类型转换运算符static_cast用于两个类型意义相近的转换,这个转换是具有明确定义的,只要底层不包含const,都可以使用static_cast。reinterpret_cast用于两个类型意义不相近的转换,reinterpret是重新解释的意思,通常为运算对象的位模式提供较低层次上的重新解释,也就是说转换后对原有内存的访问解释已经完全改变了,非常的大胆。所以我们要谨慎使用,清楚知道这样转换是没有内存访问安全问题的。const_cast用于const类型到非const类型的转换,去掉了const属性,也是一样的我们要谨慎使用,否则可能会出现意想不到的结果。dynamic_cast用于将基类的指针或者引用安全的转换成派生类的指针或者引用。如果基类的指针或者引用时指向派生类对象的,则转换回派生类指针或者引用时可以成功的,如果基类的指针指向基类对象,则转换失败返回nullptr,如果基类引用指向基类对象,则转换失败,抛出bad_cast异常。其次dynamic_cast要求基类必须是多态类型,也就是基类中必须有虚函数。因为dynamic_cast是运行时通过虚表中存储的type_info判断基类指针指向的是基类对象还是派生类对象。int main(){//对应隐式类型转换--数据的解释意义没有改变double d = 12.34;int a = static_cast<int>(d);cout <<a << endl;int&& ref = static_cast<int&&>(a);//对应强制类型转换-—数据的解释意义已经发生改变int* pl = reinterpret_cast<int*>(a);//对应强制类型转换中有风险的去掉const属性//所以要注意加volatilevolatile const int b = 0;int* p2 = const_cast<int*>(&b);*p2² = 1;cout << b << endl;cout << *p2 << endl;return 0;}class A{public:virtual void f() {}int _a = 1;};class B :public A{public:int _b = 2;};void funl(A* pa){//指向父类转换时有风险的,后续访问存在越界访问的风险//指向子类转换时安全B* pbl = (B*)pa;cout << "pbl:"<< pb1 <<endl;cout << pbl->_a << endl;cout << pbl->_b << endl;pb1->_a++;pbl->_b++;cout << pbl->_a << endl;cout << pbl->_b << endl;}void fun2(A* pa){//dynamic_cast会先检查是否能转换成功(指向子类对象),能成功则转换,//(指向父类对象)转换失败则返回nullptrB* pbl = dynamic_cast<B*>(pa);if (pb1){cout << "pbl:" << pbl << endl;cout << pbl->_a << endl;cout << pbl->_b << endl;pb1->_a++;pb1->_b++;cout << pbl->_a << endl;cout << pbl->_b << endl;}else{cout <<"转换失败" <<endl;}}void fun3(A& pa){//转换失败,则抛出bad_cast异常try{B& pb1 = dynamic_cast<B&>(pa);cout << "转换成功" << endl;}catch (const exception& e){cout << e.what() << endl;}}int main(){A a;B b;//fun1(&a) ;//funl(&b) ;fun2(&a);fun2(&b);fun3(a);fun3(b);return 0;}四. RTTIRTTI的英文全称是"RuntimeTypeIdentification",中文称为"运行时类型识别",它指的是程序在运行的时候才确定需要用到的对象是什么类型的。用于在运行时(而不是编译时)获取有关对象的信息。RTTI主要由两个运算符实现,typeid和dynamic_cast;typeid主要用于返回表达式的类型,dynamic_cast前面已经讲过了,主要用于将基类的指针或者引用安全的转换成派生类的指针或者引用。typeid(e)中e可以是任意表达式或类型的名字,typeid(e)的返回值是typeinfo或typeinfo派生类对象的引用,typeinfo可以只支持比较等于和不等于,name成员函数可以返回c风格字符串表示对象类型名字,typeinfo的精确定义随着编译器的不同而略有差异,也就以为着同一个e表达式,不同编译器下,typeid(e).name()返回的名字可能是不一样的。typeinfo的文档如下:https://legacy.cplusplus.com/reference/typeinfo/kw=typeinfotypeid(e)时,当运算对象不属于类类型或者是一个不包含任何虚函数的类时,typeid返回的是运算对象的静态类型,当运算对象是定义了至少一个虚函数的类的左值时,typeid的返回结果直到运行时才会求得。#include<iostream>#include<string>#include<vector>#include<list>using namespace std;int main(){int a[10];int* ptr = nullptr;cout << typeid(10).name() << endl;cout << typeid(a).name() << endl;cout << typeid(ptr).name() << endl;cout << typeid(string).name() << endl;cout << typeid(string::iterator).name() << endl;cout << typeid(vector<int>).name() << endl;cout << typeid(vector<int>::iterator).name() << endl;return 0;// vs2019下的运⾏结果intint[10]int*class std::basic_string<char, struct std::char_traits<char>, classstd::allocator<char> >class std::_String_iterator<class std::_String_val<structstd::_Simple_types<char> > >class std::vector<int, class std::allocator<int> >class std::_Vector_iterator<class std::_Vector_val<structstd::_Simple_types<int> > >//gcc9。4下运行结果iA10_iPiNSt7__cxxll12basic_stringIcStllchar_traitsIcESaIcEEEN9__gnu_cxx17__normal_iteratorIPcNSt7__cxxll12basic_stringIcStllchar_traitsIcESaIcEEEEESt6vectorIiSaIiEEN9__gnu_cxx17__normal_iteratorIPiSt6vectorIiSaIiEEEE#include<iostream>using namespace std;class A{public:virtual void func()    {}protected:int _a1 = 1;};class B : public A{protected:int _b1 = 2;};int main(){try{B* pb = new B;A* pa = (A*)pb;if (typeid(*pb) == typeid(B)){cout << "typeid(*pb) == typeid(B)" << endl;}// 如果A和B不是继承关系,则会抛bad_typeid异常if (typeid(*pa) == typeid(B)){cout << "typeid(*pa) == typeid(B)" << endl;}// 这⾥pa和pb是A*和B*,不是类类型对象,他会被当做编译是求值的静态类型运算// 所以这⾥始终是不相等的if (typeid(pa) == typeid(pb)){cout << "typeid(pa) == typeid(B)" << endl;}}catch (const std::exception& e){cout << e.what() << endl;}return 0;}后言这就是 C++类型转换。大家自己好好消化!今天就分享到这!感谢各位的耐心垂阅!咱们下期见!拜拜~————————————————                            版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。                        原文链接:https://blog.csdn.net/2301_81670477/article/details/146606784
  • [软件平台] mviz可视化障碍物数量不全
    将地面点进行栅格化处理,以Haf3dDetectionOut格式存储,并将其赋值为可视化对象for (auto obj : out->detectionOut3d) {mdc::visual::Object object3d;object3d.header.frameId = "lidar_front_node";object3d.objectId = obj.objectID;object3d.objectBoxCenter.x = obj.rect.center.x;object3d.objectBoxCenter.y = obj.rect.center.y;object3d.objectBoxCenter.z = obj.rect.center.z;object3d.objectBoxSize.x = obj.rect.size.x;object3d.objectBoxSize.y = obj.rect.size.y;object3d.objectBoxSize.z = obj.rect.size.z;object3d.classification = obj.cls;object3d.objectBoxOrientation = obj.rect.orientation;//航向角// object3d.textDisplay = "grid_points = ";// object3d.textDisplay += std::to_string(obj.contourPoints.size());objectArray3d.objectList.push_back(object3d);outputFile << obj.rect.center.x << " " << obj.rect.center.y << " " << obj.rect.center.z << std::endl;}终端打印有1800个障碍物,但可视化只能看到几十个,如何显示所有的障碍物? 
  • [技术干货] 【开发者空间实践指导】基于华为开发者空间定制C/C++开发环境镜像
    1概述1.1案例介绍在云原生与远程协作成为主流的软件开发趋势下,开发环境的快速构建、一致性维护及跨团队共享已成为提升效率的关键挑战。C/C++开发因其对系统工具链(如编译器、调试器、第三方库)的高度依赖,环境配置复杂且易出错,传统的手动配置模式难以满足敏捷开发需求。此外,跨地域团队或开源协作场景中,环境差异常导致“本地正常、云端报错”等问题,严重影响交付效率。通过将C/C++开发环境预置为云主机镜像,开发者可一键获取标准化的开发环境,减少重复配置成本,同时为团队协作、CI/CD流水线提供底层支持,显著提升开发流程的可靠性与可复现性。本案例聚焦于利用华为云开发者空间功能(云主机),结合VS Code的IDE工具,定制包含C/C++全工具链(如GCC/Clang、CMake、Conan包管理器)、调试工具(GDB/LLDB)及常用依赖库的云主机镜像。该镜像可直接部署为云主机实例,开发者通过一键部署即可获得开箱即用的编程环境,无需手动安装配置。云主机的弹性资源特性(按需购买开发者专业会员)进一步支持高性能编译与测试场景,而镜像的版本化管理则确保环境更新可追溯、可回滚,与云平台的计算、存储服务无缝集成。1.2适用对象个人开发者高校学生1.3案例时间本案例总时长预计60分钟。1.4案例流程说明:登录云主机,终端Terminal命令安装编译工具链和调试工具,安装VS Code;在VS Code上编写实验代码,并运行测试实验结果;在开发者空间-工作台-我的镜像制作镜像,重置云主机,配置云主机自定义镜像,登录验证实验程序。1.5资源总览本案例预计花费总计0元。资源名称规格单价(元)时长(分钟)开发者空间(云主机)4vCPUs | 8GB RAM ARM UbuntuUbuntu 24.04 Server 定制版免费60VS Code1.97.2免费60实验环境搭建2 实验环境搭建2.1配置云主机登录开发者空间,参考“10分钟玩转云主机” 案例的2.2小节内容完成华为开发者空间云主机申请与配置,云主机配置参数如下:2.2安装编译工具链C/C++运行时环境需要依赖编译器(GCC/G++)和调试工具GDB。因此,在任务开始前我们首先需要确认云主机是否已经安装GCC/G++和GDB。云主机桌面右键,点击Open Terminal Here打开Terminal Emulator窗口。在窗口中输入如下命令进行验证:gcc --versiong++ --versiongdb --version如果云主机中未安装gdb,可通过如下命令进行部署:sudo apt update #更新软件包列表sudo apt install build-essential gdb -yVS Code安装部署3 VS Code安装部署3.1VS Code安装下载.deb在云主机Terminal Emulator窗口,可以通过命令行下载.deb安装Visual Studio Code:sudo wget -O code.deb https://vscode.download.prss.microsoft.com/dbazure/download/stable/e54c774e0add60467559eb0d1e229c6452cf8447/code_1.97.2-1739406006_arm64.deb注:这里使用wget命令下载的deb包会默认下载到当前目录,并且默认命名为code.deb。如果云主机类型是X86,可以通过以下命令下载:sudo wget -O code.deb https://vscode.download.prss.microsoft.com/dbazure/download/stable/e54c774e0add60467559eb0d1e229c6452cf8447/code_1.97.2-1739406807_amd64.deb安装VS Code下载完成后,使用 dpkg 命令来安装下载好的 .deb 包:sudo dpkg -i code.deb注:若在安装过程中遇到依赖问题,可使用以下命令修复依赖:sudo apt-get install -f运行VS Code安装完成后,可以在云桌面左下角所有应用程序 – 开发 – Visual Studio Code点击启动,也可以通过以下命令打开VS Code:code3.2 安装VS Code插件VS Code作为一个款强大的跨平台编辑器,为开发者提供了非常丰富的拓展插件。开发者可以打开VS Code扩展商店,点击插件管理图标,输入插件名称,点击install安装。插件介绍如下:C/C++:语法高亮、智能补全、代码跳转、调试支持(支持跨平台编译和多环境配置)‌,所有 C/C++ 项目的开发基础,无需额外配置即可直接使用。C/C++ Extension Pack:代码编辑、调试、构建和格式化的核心功能,覆盖从代码编写到编译调试的全流程,尤其适合需要跨平台或依赖 CMake 的中大型项目‌。CMake Tools:集成 CMake 构建系统,支持自动化编译、调试和项目配置‌,简化跨平台项目管理,适用于复杂工程依赖的构建。Code Runner:一键运行代码片段或文件,支持快速测试和调试,无需手动配置编译命令,实时输出结果到终端。GitLens:增强 Git 功能,支持代码历史追溯、差异对比、作者信息查看‌,协作开发时快速定位代码变更和提交记录。C/C++ Snippets:快速插入常用代码模板(如循环、条件语句),减少重复编码‌。3.3 配置开发环境在云主机左下角打开File Manager。在File Manager左上角文件 – 新建文件夹,编辑名称创建所需要的工程目录。点击VS Code左上角File – OpenFolder,选择上一步新建的工程目录cpp_project。在VS Code中,新建 main.cpp 文件,编写示例代码:#include <iostream>using namespace std;int main() {printf("欢迎来到华为云开发者空间!");return 0;}配置构建任务在VS Code中,按 Ctrl+Shift+P 输入 Tasks: Configure Task,选择 Create tasks.json from template → Others。完成上述步骤后,工程目录中自动增加了配置文件tasks.json。双击打开并修改tasks.json:{// See https://go.microsoft.com/fwlink/?LinkId=733558// for the documentation about the tasks.json format"version": "2.0.0","tasks": [{"label": "build","type": "shell","command": "g++","args": ["-g", "-o", "main", "main.cpp"],"group": {"kind": "build","isDefault": true}}]}配置launch.json点击左侧调试图标(或按 Ctrl+Shift+D),选择 Create a launch.json file → C++ (GDB/LLDB)。修改 launch.json:{// Use IntelliSense to learn about possible attributes.// Hover to view descriptions of existing attributes.// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387"version": "0.2.0","configurations": [{"name": "C++ Debug","type": "cppdbg","request": "launch","program": "${workspaceFolder}/main","args": [],"stopAtEntry": false,"cwd": "${workspaceFolder}","environment": [],"externalConsole": false,"MIMode": "gdb","preLaunchTask": "build"}]}修改完成后,左侧工具栏会发生变化如下:编译与调试开发者可以通过左上角的C++ Debug按钮启动编译调试。也可以通过如下方式进行编译调试:编译:按 Ctrl+Shift+B 或运行终端命令: g++ -g -o main main.cpp调试:按 F5 启动调试,支持断点、变量监视等功能。3.4 常见问题解决问题 1:编译器未找到确保已安装 build-essential,检查 PATH 环境变量:echo $PATH问题 2:调试器无法启动确保已安装 gdb:sudo apt install gdb -y问题 3:VS Code 插件安装失败尝试更换网络环境,或手动下载 .vsix 文件安装。4 镜像制作与使用4.1 制作镜像在制作镜像前,我们首先要确认云主机已处于关机状态。在开发者空间,工作台 – 我的云空间模块,点击我的镜像,进入镜像编辑页面。点击制作镜像,设置镜像名称、镜像描述、选择镜像源。点击确定,开发者空间将自动开始制作镜像,制作镜像需要30分钟,请耐心等待。镜像制作完成后,状态变为“就绪”状态。4.2 使用镜像在加载镜像前,需要先确认云主机当前是可配置状态。点击配置云主机,选择私有镜像,下拉选项中选择之前已经制作好的镜像,点击安装按钮。进入桌面,自定义镜像开始加载。等待镜像加载(约3-5分钟),进入云桌面,Terminal Emulator窗口通过code命令启动VS Code,点击运行程序,这里显示程序运行成功。至此,基于开发者空间,定制C/C++开发环境云主机镜像案例内容全部完成。更多案例,点击案例中心查看~
  • [问题求助] 第二十三期约束5
    请问最终代码会人工审查吗,之前出现过用到未来报文但没有报错的情况。
  • [技术干货] C++ snprintf 是否需要手动补 \0
    在使用 snprintf 函数时,不需要手动添加 \0,因为 snprintf 会自动在生成的字符串末尾添加空字符 \0,前提是缓冲区大小足够容纳字符串内容以及终止符。具体说明:函数行为:snprintf 的作用是将格式化的字符串写入指定的缓冲区,并确保字符串以 \0 结尾(只要缓冲区大小允许)。如果缓冲区大小不足以容纳整个格式化字符串(包括终止符 \0),snprintf 会截断字符串,但仍会确保在截断后的字符串末尾添加 \0。返回值:snprintf 返回的是理论上需要的缓冲区大小(不包括终止符 \0)。如果返回值大于或等于指定的缓冲区大小(n),说明缓冲区不足以容纳整个字符串,此时生成的字符串会被截断。例子:#include <stdio.h> int main() { char buffer[10]; int len = snprintf(buffer, sizeof(buffer), "Hello, World!"); printf("Buffer: '%s'\n", buffer); // 输出: Buffer: 'Hello, Wo' printf("Returned length: %d\n", len); // 输出: Returned length: 13 return 0; } 在这个例子中,缓冲区大小为 10,snprintf 只会写入前 9 个字符(Hello, Wo),并在末尾添加 \0。返回值 13 表示如果缓冲区足够大,完整字符串的长度(不包括 \0)是 13。注意事项:如果缓冲区大小过小,snprintf 会截断字符串,但依然会保证字符串以 \0 结尾。如果需要完整存储字符串,应根据返回值调整缓冲区大小。总结:使用 snprintf 时,不需要手动添加 \0,函数会自动处理。但需要确保缓冲区大小足够,或者根据返回值动态调整缓冲区大小以避免截断。
  • [工具链] 无法找到RPM第三方库
     1.硬件平台:MDC 6102.软件版本:MDC_Development_Studio-3.0.002-0000000-Ubuntu203.问题描述:已按照产品文档进行交叉编译环境、SCFI环境等配置(SCFI例程已成功在计算平台上运行),当使用MDS软件或直接使用scfirepo showrpm时,均提示找不到RPM库4.一点疑问:产品文档中描述“确认当前工程所关联SDK中的交叉编译环境已配置lyum源”,但仅有计算平台的第三方库安装方式之一涉及到lyum,而交叉编译环境的第三方库完全不涉及lyum,该如何配置  
  • [工具链] 创建SCFI工程后无法找到RPM第三方库
    1.产品名称:MDC 6102.软件版本:MDC_Development_Studio-3.0.002-0000000-Ubuntu203.问题现象:已按照产品文档完成交叉编译环境、第三方库、SCFI等相关配置,使用MDS软件创建SCFI工程,右键该工程打开属性配置窗口后,在“Build & Execution > RPM Management”中输入当前开发机的root密码,提示无法找到rpm库。  4.已采取的措施:交叉编译、SCFI的环境变量已加载,交叉编译环境的第三方库已安装,计算平台的第三方库也已安装。5.主要疑问:文档中提到“确认当前工程关联SDK中的交叉编译环境已配置lyum源”,但在产品文档中,仅计算平台的第三方库安装有一种安装方式是采用lyum_install.sh脚本的,而交叉编译环境的第三方库安装并未涉及lyum,请问如何解决当前问题。   
  • [大赛资讯] 上合赛区复赛信息收集问卷提前终止
    上合赛区复赛个人信息收集问卷短信上写的是4月3日下午两点前进行填写,但是目前(4月3日中午12点)发现问卷已经无法进行填写了,想询问一下如何解决。
  • [大赛资讯] 为什么在线运行速度会比本地快?
    与比赛无关,但是很好奇,想请教一下。判题在线运行速度是怎么做到比本地快的?照理来说,服务器cpu主频很低,性能不如本地,运行时间应该会长于呀?
  • [问题求助] 华为算法精英实战营第二十三期-软切片调度时延隔离 输入输出单位问题
    按照赛题中的说明,输入Pktsize的单位是Byte,但是在例子中的计算看起来是按bit计算,同时问一下输出的报文离开时间单位是什么,在例子中看起来是ns,实际提交作品也是这么算的吗?
  • [大赛资讯] 本地Linux编译通过,提交后提示编译报错
    本地编译结果如图:提交后返回 compile_error ,求助。
  • [大赛资讯] 关于对象标签数量的问题
    请问某一个类型tag的数量在总数量中的占比,在测试数据sample_official.in中和线上评测数据中是一样的吗?
  • [大赛资讯] 编译错误的,有可能是压缩软件的问题,我自己的电脑一开始用360压缩编译错误,换了个压缩软件突然行了,建议Bandizip
    编译错误的,有可能是压缩软件的问题,我自己的电脑用360压缩编译错误,换了个压缩软件突然行了
  • [大赛资讯] 一直报错unexpected_eoln
    本地三个数据集都能跑通,但是一提交就报错  
  • [大赛资讯] 线上出现unexpected_eoln
    在windows本地使用sample_extra数据集能够正常运行并且在合理时间内全部跑完,但是在线上测试中出现unexpected_eoln。
总条数:181 到第
上滑加载中