考虑这个代码:
std::vector<char>::size_type size = static_cast<std::vector<char>::size_type>(std::numeric_limits<std::vector<char>::difference_type>::max()) + 1;
std::vector<char> v(size);
std::vector<char>::difference_type diff = std::distance(v.begin(), v.end());
Run Code Online (Sandbox Code Playgroud)
其中size_type与size_t (unsigned int)相同,且difference_type与ptrdiff_t (signed int) 相同。
如果向量的大小比的限制更大difference_type,将性病::距离函数返回一个负值?
我正在查看下面代码的输出。当我将 1 增加到 float 的最大值时,输出似乎是我所期望的,但是当我执行 x=x*1.5 时,我将 inf 视为输出,我认为这是浮点溢出。我的问题是,从预期输出到 inf 的上限是多少?
x=sys.float_info.max
x=x+1
x
Run Code Online (Sandbox Code Playgroud) 我正在尝试计算 C 中两个时间点之间的差异,因为这些点是在 1900 年之前,所以我需要使用负值。
虽然转换应该将变量jahr_tod_negative写入ts.tm_year,但几乎每次运行程序时,它都会给我一个完全不同的日期,甚至日期和月份都混淆了。年份是唯一需要为负数的值。我怎样才能防止这种情况发生?
#include <stdio.h>
#include <time.h>
int main ()
{
time_t t;
struct tm ts;
char str[90];
int tag_tod;
int monat_tod;
int jahr_tod;
unsigned int jahr_tod_von_1900;
int jahr_tod_negative;
printf("Tag eingeben: ");
scanf("%d", &tag_tod);
printf("\nMonat eingeben: ");
scanf("%d", &monat_tod);
printf("\nJahr eingeben: ");
scanf("%d", &jahr_tod);
jahr_tod_von_1900 = 1900 - jahr_tod;
jahr_tod_negative = -jahr_tod_von_1900;
printf("jahr_tod_negative: %d\n", jahr_tod_negative);
//ts.tm_sec = 0;
//ts.tm_min = 0;
//ts.tm_hour = 0;
ts.tm_mday = tag_tod;
ts.tm_mon = monat_tod;
ts.tm_year = jahr_tod_negative; …Run Code Online (Sandbox Code Playgroud) 我从文本文件中提取数字并用它们填充int类型的数组.
我正在将值插入到数组中,同时使用这些代码行循环遍历.txt文件(其中k是.txt文件中的数字量):
for (int j = 0; j < k; j++)
inputFile >> tab[j];
Run Code Online (Sandbox Code Playgroud)
当文本文件中的数字小于2,147,483,647时,这是整数类型的最大大小,一切顺利.
当数字大于这个程序时,我假设溢出并且无法插入它,但它之后也无法插入任何数字.
导致溢出发生后不再插入数字的原因是什么?
我已经使用std::chrono了多年,并观看了许多 Howard Hinnant 关于图书馆设计和使用的演讲。我喜欢它,我想我一般都理解它。然而,最近,我突然意识到我不知道如何实际和安全地使用它来避免未定义的行为。
在我通过几个案例为我的问题做准备时,请耐心等待。
让我们从我认为“最简单”的std::chrono::duration类型开始,
nanoseconds. 它的最小rep大小是 64 位,这意味着在实践中它会是std::int64_t,因此可能没有标准不需要的“剩余”可选表示位。
这个函数显然并不总是安全的:
nanoseconds f1(nanoseconds value)
{ return ++value; }
Run Code Online (Sandbox Code Playgroud)
如果value是nanoseconds::max(),那么它就会溢出,我们可以用 clang 7 的 UBSan( -fsanitize=undefined)来确认:
runtime error: signed integer overflow: 9223372036854775807 + 1 cannot be
represented in type 'std::__1::chrono::duration<long long,
std::__1::ratio<1, 1000000000> >::rep' (aka 'long long')
Run Code Online (Sandbox Code Playgroud)
但这没什么特别的。它与典型的整数情况没有什么不同:
std::int64_t f2(std::int64_t value)
{ return ++value; }
Run Code Online (Sandbox Code Playgroud)
当我们不能确定这value不是它的最大值时,我们首先检查,然后处理我们认为合适的错误。例如:
nanoseconds f3(nanoseconds value)
{
if(value == …Run Code Online (Sandbox Code Playgroud) 我正在创建一种静态编译的编程语言,并使用 LLVM 作为其后端。我希望我的语言在发生整数溢出时捕获/崩溃。
我知道llvm.sadd.with.overflow之类的东西,但我认为这不是最佳/有效的解决方案。该函数返回一个包含两个值的结构,而不仅仅是让我直接访问 OF 寄存器标志。理想情况下,在每次算术运算之后,只要发生整数溢出,我就会有一个“JO”汇编指令来捕获。这正是 clang 的UndefinedBehaviorSanitizer所做的。但是,我正在编译为 LLVM IR,而不是 C 或 C++。
如何直接在 LLVM IR 中使用 UndefinedBehaviorSanitizer(或完成等效操作)来处理整数溢出?
由于隐式转换以及std::numeric_limits<T>::max()and Friends 返回 type 的事实,编写一个在概念上“做正确的事情”的T函数似乎并不简单。也就是说,如果它们共享公共范围,则进行比较,如果不是,则确定是否小于,无论位数或符号性如何。有没有比这个简单的实现更简单的实现?:bool cmp(IntA a, IntB b)return a < b;ab
template <typename IntA, typename IntB>
[[nodiscard]] constexpr bool cmp(IntA a, IntB b) noexcept {
static_assert(std::is_integral_v<IntA>);
static_assert(sizeof(IntA) <= sizeof(long long int), "We assume we can fit everything into long long");
static_assert(std::is_integral_v<IntB>);
static_assert(sizeof(IntB) <= sizeof(long long int), "We assume we can fit everything into long long");
if (a < 0) {
if (b < 0) {
return static_cast<signed long long int>(a) < …Run Code Online (Sandbox Code Playgroud) 在下面的程序中,如果算术表达式出现问题,我们如何使编译器发出警告/错误。
如果算术表达式产生的值超过其类型的最大值,我希望编译器发出警告/错误。
我已经使用编译了下面的程序gcc (GCC) 4.8.5 20150623 (Red Hat 4.8.5-4),使用的编译命令是gcc int_promo_flags.c -Wall -Wextra
我期待来自 line 的警告/错误long long int y = x + INT_MAX;,但没有报告错误/警告。
通过强制转换x,(long long) x我们可以使表达式产生正确的值。但是,如果算术表达式将溢出其参数类型,是否有任何编译器标志会发出警告。
#include <stdio.h>
#include <limits.h>
int main()
{
int x = 1;
long long int y = (long long) x + INT_MAX;
printf("%lld\n", y);
return 0;
}
Run Code Online (Sandbox Code Playgroud) c compiler-errors integer-overflow compiler-warnings type-promotion
我写了这段代码:
fn main() {
let mut k: i64 = 1;
loop {
k = k * 10;
println!("cool {}", k);
}
}
Run Code Online (Sandbox Code Playgroud)
如果我运行cargo run我会得到:
fn main() {
let mut k: i64 = 1;
loop {
k = k * 10;
println!("cool {}", k);
}
}
Run Code Online (Sandbox Code Playgroud)
但是如果我在(在发布目录中)之后运行可执行文件cargo build --release,我会得到一个无限循环:
cool 10
cool 100
cool 1000
cool 10000
cool 100000
cool 1000000
cool 10000000
cool 100000000
cool 1000000000
cool 10000000000
cool 100000000000
cool 1000000000000
cool 10000000000000
cool 100000000000000 …Run Code Online (Sandbox Code Playgroud) 今天我了解到,scanf()C 中不检查整数是否可以用指定类型表示。例如:
#include <stdio.h>
int main(void)
{
short num;
int ret = scanf("%hd", &num);
printf("read %d, returned %d\n", num, ret);
return 0;
}
Run Code Online (Sandbox Code Playgroud)
在我的系统(Clang/MacOS)上,上面的程序会说“returned 1”,意思是scanf()读取指定的标记,即使输入不可表示,例如4223215425243525443245234453. man scanf说:
当输入字符与格式字符不匹配时,扫描停止。当无法进行输入转换时,扫描也会停止。
C 标准是否要求这种行为,或者是否允许 的实现者scanf()将超出范围的数字输入视为无效(因此在上述情况下返回 0)?如果需要这种行为,我希望引用标准中的说法。