- c - 在位数组中找到第一个零
- linux - Unix 显示有关匹配两种模式之一的文件的信息
- 正则表达式替换多个文件
- linux - 隐藏来自 xtrace 的命令
考虑这段代码(bits.c
):
#include <assert.h>
#include <inttypes.h>
#include <stdio.h>
static uint64_t pick_bits(unsigned char *bytes, size_t nbytes, int lo, int hi)
{
assert(bytes != 0 && nbytes > 0 && nbytes <= 8);
assert(lo >= 0 && lo < 64);
assert(hi >= 0 && hi < 64 && hi >= lo);
uint64_t result = 0;
for (int i = nbytes - 1; i >= 0; i--)
result = (result << 8) | bytes[i];
result >>= lo;
result &= (UINT64_C(1) << (hi - lo + 1)) - 1;
return result;
}
int main(void)
{
unsigned char d1[8] = "\xA5\xB4\xC3\xD2\xE1\xF0\x96\x87";
for (int u = 0; u < 64; u += 4)
{
uint64_t v = pick_bits(d1, sizeof(d1), u, u+3);
printf("Picking bits %2d..%2d gives 0x%" PRIX64 "\n", u, u+3, v);
}
return 0;
}
在带有严格警告的情况下编译时(使用为 Ubuntu 12.04 衍生版本构建的 GCC 4.8.2):
$ gcc -g -O3 -std=c99 -Wall -Wextra -Wmissing-prototypes -Wstrict-prototypes \
> -Wold-style-definition -Wold-style-declaration -Werror bits.c -o bits
In file included from bits.c:1:0:
bits.c: In function ‘main’:
bits.c:9:35: error: assuming signed overflow does not occur when assuming that (X + c) < X is always false [-Werror=strict-overflow]
assert(hi >= 0 && hi < 64 && hi >= lo);
^
cc1: all warnings being treated as errors
我很困惑:GCC 是如何提示添加的?该行中没有添加(即使经过预处理)!预处理输出的相关部分是:
# 4 "bits.c" 2
static uint64_t pick_bits(unsigned char *bytes, size_t nbytes, int lo, int hi)
{
((bytes != 0 && nbytes > 0 && nbytes <= 8) ? (void) (0) : __assert_fail ("bytes != 0 && nbytes > 0 && nbytes <= 8", "bits.c", 7, __PRETTY_FUNCTION__));
((lo >= 0 && lo < 64) ? (void) (0) : __assert_fail ("lo >= 0 && lo < 64", "bits.c", 8, __PRETTY_FUNCTION__));
((hi >= 0 && hi < 64 && hi >= lo) ? (void) (0) : __assert_fail ("hi >= 0 && hi < 64 && hi >= lo", "bits.c", 9, __PRETTY_FUNCTION__));
uint64_t result = 0;
for (int i = nbytes - 1; i >= 0; i--)
result = (result << 8) | bytes[i];
result >>= lo;
result &= (1UL << (hi - lo + 1)) - 1;
return result;
}
显然,我可以添加 -Wno-strict-overflow
来抑制该警告,但我不明白为什么警告首先被认为适用于此代码。
(我注意到错误据称是 In function 'main':
,但那是因为它能够积极地将函数代码内联到 main
中。 )
由答案引发的一些观察:
static
不足以避免此问题。main
分开编译即可。__attribute__((noinline))
也可以。-O2
优化也避免了这个问题。在我看来,这像是 GCC 编译器的可疑行为。
命令:
$ gcc -g -O3 -std=c99 -Wall -Wextra -Wmissing-prototypes -Wstrict-prototypes \
> -Wold-style-definition -Wold-style-declaration -Werror -S \
> -Wno-strict-overflow bits.c
$
汇编程序(顶部):
.file "bits.c"
.text
.Ltext0:
.section .rodata.str1.8,"aMS",@progbits,1
.align 8
.LC0:
.string "Picking bits %2d..%2d gives 0x%lX\n"
.section .text.startup,"ax",@progbits
.p2align 4,,15
.globl main
.type main, @function
main:
.LFB8:
.file 1 "bits.c"
.loc 1 19 0
.cfi_startproc
.LVL0:
pushq %rbp
.cfi_def_cfa_offset 16
.cfi_offset 6, -16
.LBB8:
.LBB9:
.loc 1 23 0
movl $3, %edx
.LBB10:
.LBB11:
.loc 1 13 0
movabsq $-8676482779388332891, %rbp
.LBE11:
.LBE10:
.LBE9:
.LBE8:
.loc 1 19 0
pushq %rbx
.cfi_def_cfa_offset 24
.cfi_offset 3, -24
.LBB22:
.loc 1 21 0
xorl %ebx, %ebx
.LBE22:
.loc 1 19 0
subq $8, %rsp
.cfi_def_cfa_offset 32
jmp .L2
.LVL1:
.p2align 4,,10
.p2align 3
.L3:
leal 3(%rbx), %edx
.LVL2:
.L2:
.LBB23:
.LBB20:
.LBB16:
.LBB12:
.loc 1 13 0
movl %ebx, %ecx
movq %rbp, %rax
.LBE12:
.LBE16:
.loc 1 24 0
movl %ebx, %esi
.LBB17:
.LBB13:
.loc 1 13 0
shrq %cl, %rax
.LBE13:
.LBE17:
.loc 1 24 0
movl $.LC0, %edi
.LBE20:
.loc 1 21 0
addl $4, %ebx
.LVL3:
.LBB21:
.LBB18:
.LBB14:
.loc 1 13 0
movq %rax, %rcx
.LBE14:
.LBE18:
.loc 1 24 0
xorl %eax, %eax
.LBB19:
.LBB15:
.loc 1 14 0
andl $15, %ecx
.LBE15:
.LBE19:
.loc 1 24 0
call printf
.LVL4:
.LBE21:
.loc 1 21 0
cmpl $64, %ebx
jne .L3
.LBE23:
.loc 1 27 0
addq $8, %rsp
.cfi_def_cfa_offset 24
xorl %eax, %eax
popq %rbx
.cfi_def_cfa_offset 16
.LVL5:
popq %rbp
.cfi_def_cfa_offset 8
ret
.cfi_endproc
.LFE8:
.size main, .-main
.text
...
最佳答案
它正在内联函数,然后生成错误。你可以自己看看:
__attribute__((noinline))
static uint64_t pick_bits(unsigned char *bytes, size_t nbytes, int lo, int hi)
在我的系统上,原始版本会生成相同的警告,但 noinline
版本不会。
GCC 然后优化 hi >= lo
,因为它真的是 u+3 >= u
,并生成警告,因为它不够好地弄清楚 u+3
不会溢出。真可惜。
来自 GCC 文档,第 3.8 节:
An optimization that assumes that signed overflow does not occur is perfectly safe if the values of the variables involved are such that overflow never does, in fact, occur. Therefore this warning can easily give a false positive: a warning about code that is not actually a problem. To help focus on important issues, several warning levels are defined. No warnings are issued for the use of undefined signed overflow when estimating how many iterations a loop requires, in particular when determining whether a loop will be executed at all.
添加了强调。我个人的建议是使用 -Wno-error=strict-overflow
,或使用 #pragma
来禁用违规代码中的警告。
关于c - 为什么 GCC 4.8.2 在严格溢出下提示加法?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23020208/
最近我遇到了 AngularJS Strict DI 模式。使用它的目的和好处是什么?通过在移动设备上使用它,我们会获得显着的性能提升吗? 我尝试将它应用到我的代码中,并且在编写代码时我没有做任何注释
要在复制文本的底部添加额外信息 - 我想使用以下 JS: document.addEventListener('copy', (event) => { const pagelin
Java 是否有一个好的、严格 的日期解析器?我可以访问 Joda-Time,但我还没有看到这个选项。我发现了“Is there a good date parser for Java”这个问题,虽然
在下面的网页中,图像和 div 之间有几个像素的间隙。 (我已经在 Firefox 3 和 Safari 4 中测试过。) 我怎样才能缩小差距? body { background-color:
前段时间我遇到了一个“问题”,但我一直没有弄清楚。希望有人能照亮它。当我将 DOCTYPE 从严格更改为过渡时,是什么导致某些浏览器(Chrome、Opera 和 Safari)以不同方式呈现页面。我
PHP 以其类型杂耍而闻名。我必须承认这让我很困惑,而且我很难在比较中找出基本的逻辑/基本内容。 例如:如果 $a > $b 为真且 $b > $c 为真,是否意味着 $a > $c总是也是真的吗?
有在ECMAScript Language Specification11.9.1 等于运算符 (==): NOTE 3 The equality operator is not always tra
考虑这些不同的尝试,比如 last : Prelude> import Data.Foldable Prelude Data.Foldable> foldr const undefined (reve
我正在考虑使用 jQuery 元数据插件。看起来很有趣,但是... ... alert($('li.someclass').metadata().some); 这段代码有效吗? 更新 当然这是一个老例
我有一个 CSS 文件,我的本地开发服务器(webpack)正在提供一个显然错误的 mime 类型。 Refused to apply style from 'http://localhost:100
因此对于 Google Chrome 和 Opera,cookie 具有 SameSite 属性,该属性可以具有以下两个值之一:strict 或 lax。 它们之间的一些区别之一是 SameSite=
我试图到处寻找这个问题的答案,但似乎我运气不好。 我有一个非常简单的 Mongoose 模型 var userObject = { profile: { username: {
我正在为必须使用 XHTML 1.0 Strict 进行验证的类编写程序。根据 w3 的验证程序,我的页面通过了验证。我还有一个 HTML5 版本(这是原始版本),它可以按应有的方式进行验证和工作。
我得到了很多 validation errors因为 在 里面。如果我删除 br 标签,那么它工作正常。 为什么会产生问题? 最佳答案 不是br在p里面,而是你没有结束 br与 /特点。你有 在代码中
好吧,这让我抓狂。 我想在我的文档周围加上边框。它应该很好地绕过整个窗口/视口(viewport)。所以我定义: body { border: 1px solid red; } 当我的文档处于 q
我在 MySql 服务器上运行的查询遇到问题。这是查询: SELECT itms.Gender,itms.Age, (CASE WHEN (plv.Discount = 0 OR t1.EverGre
我有以下 javascript 函数,如果所有必填字段都不完整并且是我使用 Google Apps 脚本创建的表单的一部分,它会阻止表单提交。请注意,#submitbutton 实际上是一个常规按钮,
我是一名优秀的程序员,十分优秀!