C - 使用定义表达式的 lseek 后读取错误

C - Wrong read after lseek with define expression

我有一个二进制文件,我需要从中读取时间戳。特别是,我正在尝试阅读最后一条记录。每条记录长 24 个字节,时间戳在前 8 个字节中。这是我写的代码:

#define IDX_RS_LEN (unsigned int)(sizeof(unsigned long) * 3)

int main(int argc, char** argv)
{
   int fd;
   unsigned long rGmte;
   char filename[256];
   int offset;

   fd = open(filename, O_RDONLY);
   if (fd != -1) {
      offset = lseek(fd, -IDX_RS_LEN, SEEK_END);
      read(fd, &rGmte, sizeof(unsigned long));
      printf("offset:%d\trGmte: %lu\n", offset, rGmte);
   } else {
      printf("Error opening file\n");
   }
   close(fd);

   return 0;
}

但这给了我以下输出:

offset:117384 rGmte: 0

这是错误的。如果我用固定值 24 替换定义中的表达式,我会得到正确的输出:

offset:117384 rGmte: 1606314900

另请注意,两种情况下的偏移量相同,但读取的值不同。 有什么想法吗?

您在 lseek 中使用了错误的类型来设置位置/偏移量,您应该使用 off_t(signed long) 而不是 unsigned int

看看What happens when I assign a negative value to an unsigned int?

设置为lseek的偏移量应该是-24:

printf("Output: %ld\n", -(signed long)(sizeof(unsigned long) * 3));
Output: -24

但你正在设置

printf("Output: %ld\n", -(unsigned int)(sizeof(unsigned long) * 3));
Output: 4294967272

切换自

#define IDX_RS_LEN (unsigned int)(sizeof(unsigned long) * 3)

int main(int argc, char** argv)
{
   int fd;
   unsigned long rGmte;
   char filename[256];
   int offset;

   fd = open(filename, O_RDONLY);
   if (fd != -1) {
      offset = lseek(fd, -IDX_RS_LEN, SEEK_END);

#define IDX_RS_LEN (sizeof(unsigned long) * 3)

int main(int argc, char** argv)
{
   int fd;
   unsigned long rGmte;
   char filename[256];
   off_t offset = IDX_RS_LEN;

   fd = open(filename, O_RDONLY);
   if (fd != -1) {
      offset = lseek(fd, -offset, SEEK_END);

它应该可以工作:https://godbolt.org/z/hEG4xx