所以这个gcc警告困扰着我:
warning: assuming signed overflow does not occur when simplifying multiplication
它指向的代码如下所示:
/* Move the memory block of entries after the removed one - if any. */
if (database->entries + database->entries_size - 1 != database_entry) {
memmove(
database_entry,
database_entry + 1,
sizeof(spm_database_entry_t)
* (
(database->entries + database->entries_size)
- database_entry - 1
)
);
}
正如您可以轻易猜到的那样,它会在元素移除后移动容器内存的一部分,以允许其进一步重新分配(缩小)。
database_entry
是已移除元素spm_database_entry_t*
类型指针
database->entries
是指向spm_database_entry_t
database->entries_size
是一个size_t
代表<{>>元素 之前如何摆脱警告?我可以阻止乘法简化,或者可能有更好的方法来计算需要移动的内存量吗?
修改
您确定database->entries
?
正。
您正在使用哪些编译器标志?
database_entry < database->entries + database->entries_size
EDIT2
在乘法之前转换为-Wall -Wextra -Wshadow -Wpointer-arith -Wcast-qual -Wstrict-prototypes
-Wmissing-prototypes -Wdeclaration-after-statement -Wwrite-strings
-Winit-self -Wcast-align -Wstrict-aliasing=2 -Wformat=2
-Wmissing-declarations -Wmissing-include-dirs -Wno-unused-parameter
-Wuninitialized -Wold-style-definition -Wno-missing-braces
-Wno-missing-field-initializers -Wswitch-default -Wswitch-enum
-Wbad-function-cast -Wstrict-overflow=5 -Winline -Wundef -Wnested-externs
-Wunreachable-code -Wfloat-equal -Wredundant-decls
-pedantic -ansi
-fno-omit-frame-pointer -ffloat-store -fno-common -fstrict-aliasing
似乎可以解决问题,但是转换为unsigned int
则不行。我不明白 - 标准说size_t
始终是无符号的......
EDIT3
如果上下文可以有用:https://github.com/msiedlarek/libspm/blob/master/libspm/database.c#L116
edit4
基于史蒂夫莎的回答的解决方案:
size_t
答案 0 :(得分:2)
就个人而言,我赞成其他中间临时变量。编译器将看到它们仅用于一次计算,并将优化变量;但是在调试版本中,您可以单步执行,检查变量,并确保它确实按照您的预期进行。
/* Move the memory block of entries after the removed one - if any. */
assert(database_entry >= database->entries &&
database_entry < database->entries + database->entries_size);
size_t i_entry = database_entry - database->entries;
size_t count_to_move = (database->entries_size - 1) - i_entry;
size_t bytes_to_move = count_to_move * sizeof(spm_database_entry_t);
memmove(database_entry, database_entry + 1, bytes_to_move);
大多数情况下,bytes_to_move
不会为0,但如果为0,那么memmove()
将只移动0个字节并且不会造成任何伤害。所以我们可以删除那个if
语句,除非你内部有其他内容,只有在移动发生时才需要这样做。
此外,如果你这样做,并且你仍然收到警告,你将得到一个行号,指出编译器担心的是什么。
答案 1 :(得分:0)
我怀疑这个问题与size_t
返回的sizeof(spm_database_entry_t)
始终是无符号类型(通常只是unsigned int
或unsigned long int
的类型同义词有关,如果我没记错的话)。但是,理论上有可能的是,如果database_entry
的值超过database->entries + database->entries_size
,您最终会将有符号数乘以无符号类型,从而增加了错误或整数溢出的可能性。通常,当有符号和无符号类型像这样混合时,较小的类型被转换/强制转换为较大的类型,或者,如果它们被同等地排序,则签名类型被强制转换为无符号类型。我不知道你的代码的其余部分是什么样的,因此很难提出改进建议。