如何正确的写加减乘除函数
有符号数加减法,存在溢出问题,经常被用于攻击构造。那么如何编写一个可以防止溢出的“正确的”函数呢?
加法运算
错误写法
signed int func(signed int a, signed int b) {return a + b;
}
分析:a与b相加可能溢出(又分为上溢和下溢)
上溢条件:a + b > INT_MAX
下溢条件:a + b < INT_MIN
正确写法
signed int func(signed int a, signed int b)
{if (((b > 0) && (a > INT_MAX - b)) || ((b < 0) && (a < INT_MIN - b))) {/* Handle error */} else {return a + b;}
}
减法运算
错误写法
signed int func(signed int a, signed int b)
{return a - b;
}
正确写法
signed int func(signed int a, signed int b)
{if ((b > 0 && a < INT_MIN + b) ||(b < 0 && a > INT_MAX + b)) {/* Handle error */} else {return a - b;}
}
乘法
错误写法
signed int func(signed int a, signed int b)
{return a * b;
}
正确写法
#include <stddef.h>
#include <assert.h>
#include <limits.h>
#include <inttypes.h>extern size_t popcount(uintmax_t)
#define PRECISION(umax_value) popcount(umax_value)signed int func(signed int a, signed int b)
{signed long long tmp;assert(PRECISION(ULLONG_MAX) >= 2 * PRECISION(UINT_MAX));tmp = (signed long long)a * (signed long long)b;if ((tmp > INT_MAX) || (tmp < INT_MIN)) {/* 处理错误 */} else {return tmp;}
}
除法
错误写法
signed int func(signed int a, signed int b)
{if (b == 0) {/* 处理错误 */} else {return a / b;}
}
正确写法
signed long func(signed long a, signed long b)
{if ((b == 0) || ((a == LONG_MIN) && (b == -1))) {/* 处理错误 */} else {return a / b;}
}
这里这个(a == LONG_MIN) && (b == -1)
的条件非常有意思,要理解为什么这种情况下计算会出错,得理解数在计算机中是如何存储的。
取余
错误写法
signed long func(signed long a, signed long b)
{if (b == 0) {/* 错误处理 */} else {return a % b;}
}
正确写法
#include <limits.h>signed long func(signed long a, signed long b)
{if ((b == 0) || ((a == LONG_MIN) && (b == -1))) {/* 错误处理 */} else {return a % b;}
}
如何正确的写加减乘除函数相关推荐
- linux 为什么 c语言,为什么C程序里一定要写main函数
为什么C程序里一定要写main函数 一. 学习过程 编写程序f.c: 对其进行编译,正常通过,再对其进行连接,出现错误: 显示的出错信息为: 翻译成中文是:在c0s模块没有定义符号'_main'. 那 ...
- 为什么c程序里一定要写main函数
一. 学习过程 编写程序f.c: 对其进行编译,正常通过,再对其进行连接,出现错误: 显示的出错信息为: 翻译成中文是:在c0s模块没有定义符号'_main'. 那么这个错误信息可能与文件c0s.ob ...
- 如何在matlab sfunction 函数中调用自己写的函数?
自己编写了一个s函数,有几个参数引用了自己写的几个函数,在脚本中可以正确运行,但在写成s函数,进行 simulink 仿真的时候,已知提示"too many input auguments& ...
- 自己动手写 printf函数
我们在C语言编程中会遇到一些参数个数可变的函数,例如printf() 这个函数,它的定义是这样的: int printf( const char* format, ...); 它除了有一个参数form ...
- ACMNO.41C语言-数字调序 有n个整数,使前面各数顺序向后移m个位置,最后m个数变成前面m个数,见图。写一函数:实现以上功能,在主函数中输入n个数和输出调整后的n个数
题目描述 有n个整数,使前面各数顺序向后移m个位置,最后m个数变成前面m个数,见图. 写一函数:实现以上功能,在主函数中输入n个数和输出调整后的n个数. 输入 输入数据的个数n n个整数 移动的位置m ...
- ACMNO.40 C语言-子串 有一字符串,包含n个字符。写一函数,将此字符串中从第m个字符开始的全部字符复制成为另一个字符串
题目描述 有一字符串,包含n个字符. 写一函数,将此字符串中从第m个字符开始的全部字符复制成为另一个字符串. 输入 数字n 一行字符串 数字m 输出 从m开始的子串 样例输入 6 abcdef 3 样 ...
- ACMNO.27 Python的两行代码解决 C语言-字符逆序 写一函数。使输入的一个字符串按反序存放,在主函数中输入输出反序后的字符串。 输入 一行字符 输出 逆序后的字符串
题目描述 写一函数,使输入的一个字符串按反序存放,在主函数中输入输出反序后的字符串. 输入 一行字符 输出 逆序后的字符串 样例输入 123456abcdef 样例输出 fedcba654321 来源 ...
- ACMNO.25 C语言-间隔输出 写一函数,输入一个四位数字,要求输出这四个数字字符,但每两个数字间空格。如输入1990,应输出1 9 9 0。 输入 一个四位数 输出 增加空格输出
题目描述 写一函数,输入一个四位数字,要求输出这四个数字字符,但每两个数字间空格.如输入1990,应输出"1 9 9 0". 输入 一个四位数 输出 增加空格输出 样例输入 199 ...
- ACMNO.24 C语言-转置矩阵 写一个函数,使给定的一个二维数组(3×3)转置,即行列互换。 输入 一个3x3的矩阵 输出 转置后的矩阵 样例
题目描述 写一个函数,使给定的一个二维数组(3×3)转置,即行列互换. 输入 一个3x3的矩阵 输出 转置后的矩阵 样例输入 1 2 3 4 5 6 7 8 9 样例输出 1 4 7 2 5 8 3 ...
最新文章
- 文献记录(part31)--Dynamic relationship identification for abnormality detection on financial time ...
- SpringBoot入门到精通_第2篇 _1分钟实战需求项目
- Django 博客教程(三):创建应用和编写数据库模型
- linux终端美化,如何美化你的命令行终端Terminal
- 实现文本超出显示省略号
- linux sftp创建多用户,同一台 Centos (Linux)服务器设置多个sftp 账号,并限制用户只能访问指定文件路径...
- STANDBY REDO LOG
- 软件开发项目成本管理实践
- 如何使用Teamtoken工具软件做员工股权激励
- 基于Python实现仿Windows标准计算器
- 代码 马佳义_武汉大学电子信息学院
- java 填数独_java – 数独求解方法
- win10自带看图工具找不到了咋办
- cupsd进程_CUPS 简介
- 刷四百道题总结的24种常用的刷题思路
- C语言中负数在计算机内部的二进制表示方式(以补码表示负数、整数的范围及所占字节数)
- JavaScript 实现网页截屏五种方法
- 编程笔试(解析及代码实现):求和为N的正整数序列之实现一个函数,输入为一个正整数N (比如100),输出为所有和等于N的[连续]正整数序列
- 晕菜:新域名在60天内不能转移。
- ALSA声卡驱动中的DAPM详解之一:kcontrol
热门文章
- 计算机屏幕无信号咋回事,电脑显示屏无信号怎么回事?电脑打不开显示器无信号的解决办法...
- python朋友圈数据分析_基于Python的微信朋友圈数据可视化分析之地点
- iOS个人整理33-GCD----多线程优化
- notoriously 众所周知地;声名狼藉地;恶名昭彰地
- 辞职文案火了!程序员的辞职理由要命不要钱。
- android 特效UI
- 干掉 LaTeX !用BookDown写本书
- 2021年中国建筑行业发展概况:建筑业总产值持续增长,未来发展方向明确[图]
- iOS11遇到的坑及解决方法
- H264和音频流打包成TS流 (MPEG2-TS)