我在编译以下代码时遇到上述错误。
long _version_tag;
size_t _timing;
ssize_t bytes_read = read(fd, &_version_tag, sizeof(long));
if (bytes_read < sizeof(long) || _version_tag != TIMING_FILE_VERSION_TAG)
return -1;
gcc在这一点上抱怨:
if (bytes_read < sizeof(long) || _version_tag != TIMING_FILE_VERSION_TAG)
^
我甚至试图明确地将 bytes_read 强制转换为 long 但是徒劳无功。有人可以帮助这里发生什么吗?
答案 0 :(得分:3)
read(3)如果失败则返回-1,因此首先测试。如果成功,那么你可以测试长度。类似的东西:
ssize_t bytes_read = read(fd, &_version_tag, sizeof(long));
if (bytes_read == -1 || (size_t)bytes_read < sizeof(long) || _version_tag != TIMING_FILE_VERSION_TAG)
return -1;
答案 1 :(得分:2)
问题是,bytes_read
的类型为ssize_t
,签名时sizeof(long)
的类型为size_t
且未签名。
由于sizeof(long)
永远不会太大而无法在我能想象的任何系统上表示为ssize_t
,我建议将sizeof(long)
的结果转换为ssize_t
:
bytes_read < (ssize_t)(sizeof(long)) // Or static_cast in C++
这通常只是一个警告,而不是错误,因为标准很好地定义了结果。但是,有符号和无符号整数类型的隐式比较可能会产生令人惊讶的结果,因此应该避免使用。
答案 2 :(得分:1)
各种答案提供了解决方案,以解决bytes_read < sizeof(long)
将比较的一方投射到另一方的类型所引起的警告。
(size_t) bytes_read < sizeof(long) // or
bytes_read < (ssize_t) sizeof(long)
如果采用第一种方法,则应进行先前的测试。
bytes_read == -1
许多评论都反映了铸造另一方的优点。铸造总是有点棘手,因为存在降级铸造(缩小范围)和丢失信息的可能性。
在OP的阅读long _version_tag
的示例中,没有区别哪一方被投放为long
肯定有大小小于32,767 - ssize_t
的最小最大值且小于65,535 - size_t
的最小最大值。
如果寻找一般解决方案而不假设_version_tag
是long
,但潜在的东西更大,并且使用Ref,则代码可以使用以下内容。代码知道bytes_read
中的值,如果不是-1,则必须符合size_t
,因为它肯定不会大于传递给read()
的值。
foo _version_tag;
ssize_t bytes_read = read(fd, &_version_tag, sizeof _version_tag);
if (bytes_read == -1 || (size_t) bytes_read < sizeof _version_tag || ...)
return -1;
就我而言,我避免使用铸造,而是选择乘法以避免降级。
if (bytes_read == -1 || ((size_t)1 * bytes_read) < sizeof _version_tag || ...)
return -1;
答案 3 :(得分:0)
ssize_t
是签名类型,但sizeof的结果是size_t
,这是一种无符号类型。在C中,如果您想避免警告/错误,可以将sizeof
结果转换为ssize_t
。
答案 4 :(得分:-2)
ssize_t
已签名,其中size_t
未签名。首先需要确保bytes_read
是非负的(意味着呼叫没有失败)。如果该检查通过,您可以bytes_read < static_cast<ssize_t>(sizeof(long))
。