以下代码中 if(len ....) 的 meaning/logic 是什么?

What is the meaning/logic of if(len ....) in the following bit of code?

这是来自 chux 对这里问题的回答:How to get the strings from a file and store in a 2D char array and compare that 2D char array with a string in C?

Lop off the potential tailing '\n'

size_t len = strlen(buf);
  if (len && buf[len-1] == '\n') buf[--len] = '[=11=]';

我理解 if 语句的第二部分(检查 if buf[len-1] == '\n'),但不要以为我不理解它的 if (len) 部分...是它只是检查缓冲区中的任何内容是否实际上有一个非零长度(如果是这样,怎么会出现 strlen returns 0 的情况?)还是别的什么?

空字符串的长度为 0

以下代码将导致 len 成为 0:

const char * str = "";
size_t len = strlen(str);

所以我们必须在访问之前检查它 str[len-1] 以避免整数回绕。

注意存放str的缓冲区的长度是1,因为尾随'[=18=]',所以内存看起来像这样:

buf --> [ '[=11=]' ]
size_t is the unsigned integer type of the result of sizeof , alignof (since C11) and offsetof, depending on the data model.

我认为你在检查方面是对的。 size_t 是无符号整数类型,因此它正在检查该条件以便继续进行其他检查和 buf[--len]

https://en.cppreference.com/w/c/types/size_t

只有当某个值大于零时,您才能为数组建立索引。因此,要访问 buff[len-1]len 必须大于零,否则如果 len 为零,则 len - 1 将是一个由 SIZE_MAX 定义的非常大的数字,而 buff[-1] 是一个错误。 语句 if (len && buff[len-1]=='\n') 结合了两个条件:
首先检查 len > 0 然后 buff[len-1] == '\n'.
上面给出的 if 语句的含义如下: if( (len > 0) && (buff[len-1] == '\n'))

while (i < 100 && fgets(buf, sizeof buf, f) != NULL ) {
  // Lop off the potential tailing '\n'
  size_t len = strlen(buf);
  if (len && buf[len-1] == '\n') buf[--len] = '[=10=]';

Is it simply checking if there's actually a non-zero length to whatever's in the buffer

是的。

代码正在测试 len != 0,然后尝试 buf[len-1] 以防止访问 buf[] 超出范围。


(and if so, how can a situation where strlen returns 0 arise?)

防御性编码:读取的可能以空字符.

开头

前面的代码有fgets(buf, sizeof buf, f),它读取,然后形成一个字符串。在 C 标准库1 中, 的输入是 '\n' 之前的字符。 空字符对输入没有特殊意义,它就像另一个其他字符一样。用fgets()读取并保存在buf[]后,会附加一个空字符size_t len = strlen(buf); return 基于第一个 空字符 的长度,不一定是附加的

如果文本文件行是

'[=11=]', 'a', 'b', 'c', '\n'

然后 fgets(buf, ...) 将导致 buf[]

'[=12=]', 'a', 'b', 'c', '\n', '[=12=]'

len == 0.

ASCII 文本文件很少包含 空字符。他们的存在通常是错误的或恶意的(黑客利用)。 空字符 在 UTF-16 文本文件中很常见,但读取带有相关代码的此类文件也有其他问题。


1 "A text stream is an ordered sequence of characters composed into lines, each line consisting of zero or more characters plus a terminating new-line character. Whether the last line requires a terminating new-line character is implementation-defined." C11dr §7.21.2 2