0

这是读取行的函数的简短片段。这怎么可能与它bufsize相比((size_t)-1)/2

我想象将变量与例如进行比较。int- 那是不可能的;我认为相反,INT_MAX 是正确的。那么该代码如何才能真正工作并且不出错呢?

int c;
size_t bufsize = 0;
size_t size = 0;

while((c=fgetc(infile)) != EOF) {
    if (size >= bufsize) {
        if (bufsize == 0)
                bufsize = 2;
        else if (bufsize <= ((size_t)-1)/2)
                bufsize = 2*size;
        else {
                free(line);
                exit(3);
        }
        newbuf = realloc(line,bufsize);
        if (!newbuf) {
                free(line);
                abort();
        }
        line = newbuf;
    }
    /* some other operations */
}
4

5 回答 5

6
(size_t)-1

这是将值转换-1为 a size_t(type)value是 C 中的一个演员表。

由于size_t是无符号类型,这实际上是可以容纳的最大值size_t,因此它用于确保缓冲区大小实际上可以安全地加倍(因此随后除以二)。

于 2012-08-31T20:46:12.677 回答
2

(size_t)-1强制转换-1为 type size_t,这导致(在stdint.hSIZE_MAX中定义的宏),该类型可以容纳的最大值。size_t

所以比较是检查是否bufsize小于或等于可以包含在一个中的最大值的一半size_t

于 2012-08-31T20:50:46.437 回答
2

该代码依赖于一些关于位的假设,然后进行了一个众所周知的破解来找到最大 size_t 值(假设 size_t 不容纳比寄存器更多的位,这是许多机器上的安全赌注)。

首先它用位填充寄存器1,然后将其转换size_t数据类型,因此比较将起作用。只要该寄存器的位数大于size_t数据类型,那么(如果有)未使用的1位将被截断,并且您将获得可以容纳位的最大无符号数size_t

之后,它除以 2 得到该数字的一半,并进行比较以查看在不超过 " maximum " 的情况下增加大小是否安全size_t。但到那时,它正在划分size_t数据类型,并比较两种size_t数据类型(类型安全操作)。

如果您真的想删除这个位巫术(好吧,这不是我见过的最糟糕的位巫术示例)。考虑以下代码段

    else if (bufsize <= ((size_t)-1)/2)
            bufsize = 2*size;

可以替换为

    else if (bufsize <= (MAX_SIZE/2)
            bufsize = 2*size;

并且在没有强制转换的情况下是类型安全的,并且更具可读性。

于 2012-08-31T20:55:58.837 回答
0

size_tin((size_t)-1)/2)只是用作演员表:转换-1size_t.

这里的诀窍是它size_t是无符号的,所以强制转换将转换为, 或(size_t) -1的最大值。这在循环的上下文中很有用。但是,我更愿意看到直接使用而不是这个技巧。size_tSIZE_MAXSIZE_MAX

于 2012-08-31T20:46:26.470 回答
0

size_t 没有被解释为一个值,它被用来将负一的值转换为 size_t 类型。

((size_t)-1)/2

将 -1 转换为 size_t 然后除以 2。

于 2012-08-31T20:47:00.540 回答