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

[C/C++]_[初级]_[关于编译时出现有符号-无符号不匹配的警告-sizeof使用注意事项]

场景

  1. 自从有了C++11auto关键字之后,声明变量经常使用它。之后有一次发现编译控制台大量输出有符号/无符号不匹配的警告信息。怎么回事?

说明

  1. 这里的有符号和无符号指的就是整数的类型,无符号的整数无论怎么运算都不会出现负数。

  2. 计算机里存储无符号的类型是通过原码,也就是二进制格式存储。而有符号的正数是通过原码存储,负数是通过补码存储的。

  3. 问题就是出现了如下的一种错误, 在使用比较运算符 < 是操作数的类型不匹配,一个是有符号,一个是无符号。可能导致错误的比较结果。因为有无符号的等级更高些,有符号的操作数会被转换为无符号再进行比较。这里的警告就是提醒如果有负值的时候比较的结果可能就是错误的。

testcpp.cpp(55): warning C4018: “<”: 有符号/无符号不匹配
  1. Csizeof()函数返回的就是unsigned int类型,而这个函数经常用在对数组求大小时。当我们使用auto声明变量size的时候,默认就是sizeof的类型了。
int ns[] = { 4,5,6,7,78,8 };
auto size = sizeof(ns) / sizeof(int); //unsigned int 
  1. 这时候如果使用size在循环里做减法希望得到负数的时候就会出问题,因为unsigned int类型不会有负数。比如对数组倒序求解, i-0 时候等于 4294967295,这个循环就会进入死循环。
for (auto i = size - 1; i >= 0; --i) {
	cout << i << endl;
	assert(i < size);
}

方案

  1. 最好的方法就是在求解size的时候不要使用auto,使用int类型让它隐式转换。
int size = sizeof(ns) / sizeof(int);
  1. 其他使用unsigned int类型的时候,如果和常量整数(默认是int有符号)或变量进行运算时,都要转换为统一的类型再运算。

例子

#include <string.h>
#include <iostream>
#include <bitset>
#include <assert.h>

using namespace std;

void TestUnsignedInt() {
	unsigned char a = 1; 
	unsigned char b = 3;
	unsigned char res = a - b; //00000001 + 11111101(-3的补码)
	unsigned char ma = 255;
	cout << (unsigned)ma << endl;
	cout << (unsigned)res << endl;  //254
	cout << bitset<8>(res) << endl; //11111110
}

void TestUnsignedSizeofFunc() {
	
	int ns[] = { 4,5,6,7,78,8 };

	// sizeof()返回值是unsigned int类型
	// 方法1: 要把auto改为int,推荐,这样没有编译警告。
	auto size = sizeof(ns) / sizeof(int); //unsigned int 

	cout << "++++++" << endl;
	for (auto i = 0; i < size; i++)
		cout << i << endl;

	cout << "------" << endl;
	// 当 0 -1 的时候等于 4294967295
	// 方法2: 要把 auto 改为 int
	for (auto i = size - 1; i >= 0; --i) {
		cout << i << endl;
		assert(i < size);
	}
}

int main()
{
	TestUnsignedInt();
	TestUnsignedSizeofFunc();
}

相关文章:

  • aarch64服务器-部署mysql
  • PDF转为网页文件怎么转?这篇文章告诉你
  • Java 基本数据类型-包装类-String的相互转换(总结+代码实现)
  • JUC并发编程
  • Spring注解驱动系列总结
  • 记一次mysql 命令行登录报错(error while loading shared libraries: libssl.so.1.1)
  • PyTorch中DataLoader及其与enumerate()用法介绍
  • mac 使用 PyQt5 和 py_designer 搭建窗体
  • 嵌入式SQL开发
  • 对于HTTP协议,什么是长连接和短连接?
  • ReentrantLock读写锁
  • leetcode 1680. Concatenation of Consecutive Binary Numbers(连接连续的二进制数)
  • Python数据分析之时间序列的处理
  • 【PHP】如何搭建服务器环境 原生篇 | Ubuntu 18.04 + PHP8.1 + MySQL5.7 + Nginx 1.4
  • 【c语言】数据在内存中的存储
  • @jsonView过滤属性
  • 【附node操作实例】redis简明入门系列—字符串类型
  • 【技术性】Search知识
  • 【刷算法】从上往下打印二叉树
  • CSS选择器——伪元素选择器之处理父元素高度及外边距溢出
  • Django 博客开发教程 8 - 博客文章详情页
  • Docker下部署自己的LNMP工作环境
  • ESLint简单操作
  • JavaScript 是如何工作的:WebRTC 和对等网络的机制!
  • Javascript编码规范
  • Linux链接文件
  • 技术:超级实用的电脑小技巧
  • 每天10道Java面试题,跟我走,offer有!
  • 使用Gradle第一次构建Java程序
  • 它承受着该等级不该有的简单, leetcode 564 寻找最近的回文数
  • 小程序开发之路(一)
  • 阿里云服务器如何修改远程端口?
  • ​渐进式Web应用PWA的未来
  • #pragma once与条件编译
  • #Spring-boot高级
  • #鸿蒙生态创新中心#揭幕仪式在深圳湾科技生态园举行
  • (1)(1.9) MSP (version 4.2)
  • (C语言)求出1,2,5三个数不同个数组合为100的组合个数
  • (WSI分类)WSI分类文献小综述 2024
  • (二)丶RabbitMQ的六大核心
  • (翻译)Quartz官方教程——第一课:Quartz入门
  • (规划)24届春招和25届暑假实习路线准备规划
  • (力扣)循环队列的实现与详解(C语言)
  • (南京观海微电子)——COF介绍
  • (一)VirtualBox安装增强功能
  • *2 echo、printf、mkdir命令的应用
  • .NET CF命令行调试器MDbg入门(二) 设备模拟器
  • .NET CF命令行调试器MDbg入门(四) Attaching to Processes
  • .net core IResultFilter 的 OnResultExecuted和OnResultExecuting的区别
  • .NET Framework Client Profile - a Subset of the .NET Framework Redistribution
  • .net MySql
  • .Net 代码性能 - (1)
  • .NET是什么
  • .NET与java的MVC模式(2):struts2核心工作流程与原理
  • @RequestMapping 的作用是什么?