错误:有符号和无符号整数表达式之间的比较

时间:2015-11-24 17:05:03

标签: c

我在编译以下代码时遇到上述错误。

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 但是徒劳无功。有人可以帮助这里发生什么吗?

5 个答案:

答案 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_taglong,但潜在的东西更大,并且使用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))