这是我的代码库的一部分。 我没有得到警告的意思,所以我无法解决这个问题...... 代码:
struct ParamsTube{
uint8 Colours01[4];
uint8 Colours02[4];
uint8 Colours03[4];
};
void sample_fun(const uint8 *diagData){
ParamsTube Record;
memcpy(&Record.Colours01[0], &diagData[0], 4); //Line 1
memcpy(&Record.Colours02[0], &diagData[4], 4); //Line 2
memcpy(&Record.Colours03[0], &diagData[8], 4); //Line 3
}
和第1,2和3行的逻辑LINT警告426是
Call to function 'memcpy(void *, const void *, std::size_t)' violates semantic '(3n>4)'
你能告诉我它究竟意味着什么......
答案 0 :(得分:7)
(3n > 4)
表示用于调用memcpy()
的第三个参数应大于4,并且您的调用违反了此语义。语义似乎表明memcpy()
不应该用于复制小于机器字的数据(通常为4)。这就是lint警告你的原因。语义是否合适是另一个问题。
以下是棉绒警告426的解释:
426调用函数'Symbol'违反语义'String' - 当违反用户语义(由-sem定义)时发出此警告消息。 'String'是被违反的语义的子部分。例如:
//lint -sem( f, 1n > 10 && 2n > 10 )
void f( int, int );
...
f( 2, 20 );
结果显示消息:
Call to function 'f(int, int)' violates semantic '(1n>10)'
因此,您环境中的memcpy()
可能具有这样的前导lint语义:
// lint -sem(memcpy, 3n > 4)
void* memcpy(void* s1, const void* s2, std::size_t n);
对于您的情况,如果您想要实现的目标是:
memcpy(&Record.Colours01[0], &diagData[0], 4); //Line 1
memcpy(&Record.Colours02[1], &diagData[4], 4); //Line 2
memcpy(&Record.Colours03[2], &diagData[8], 4); //Line 3
然后简单地说:
memcpy(&Record, diagData, sizeof(Record));
将在不触发lint警告的情况下完成所有工作。
答案 1 :(得分:1)
Lint告诉您不应该将memcpy
调用4个或更少的字节。
这是愚蠢的。
现代编译器知道它是什么memcpy
。如果使用GCC或Clang上的优化进行编译,至少可以在x86上找到,在生成的代码中,4字节memcpy
已被单个mov
替换。 (好吧,从内存复制到内存时可能有两个mov
。)
编写此代码的方式是唯一一种可靠,安全的方法来编写它,而不是逐个编写字节副本。特别是,编写此代码不可移植:
*((uint32_t*)&Record.Colours01[0]) = *((uint32_t*)&diagData[0]);
这将适用于x86,但仅限于该平台允许未对齐的访问。但是如果diagData[0]
没有与4字节边界对齐(并且绝对没有理由认为它是这样),那么这是一个未对齐的访问,并且很可能在其他平台上触发陷阱(ARM具有对齐 - 检查模式; IA-64和已故的Alpha根本不支持未对齐访问,各种嵌入式芯片也是如此。
就此而言,你甚至不能假设Colours01
是一致的。编译器应该对齐它没有任何约束理由;堆栈上的其他变量可能会使其不对齐。
memcpy
无论对齐是什么都是安全的,同时让编译器有机会将其优化为它认为最有效的任何内容(例如x86上的mov
,其中未对齐的访问是安全的,并且可能仍然比替代方案快。)
Lint抱怨这是对Lint的作者或memcpy
上的注释的严重错误。无论哪种方式,你都不应该遵循这条规则;它导致更糟糕的代码。