我无法绕过这个话题,希望标题不要太让人误解。在两个代码段中,write
的第三个参数count
为何表现不同?似乎调用函数而不是在write
中指定数字是一件坏事,但这似乎没什么大不了的。
版本错误:
int main(int argc, char const *argv[])
{
char format[50];
char formattedTime[50];
time_t t;
if (read(STDIN_FILENO, format, 50) < 0)
fatalError("read() error");
time(&t);
strftime(formattedTime, 50, format, localtime(&t));
if (write(STDOUT_FILENO, formattedTime, strlen(formattedTime) + 1) != strlen(formattedTime) + 1)
fatalError("write() error");
return 0;
}
正确的版本:
int main(int argc, char const *argv[])
{
char format[50]; //zeljeni format
char formattedTime[50]; //formatirano vreme
time_t t; // trenutno vreme
// citamo s ulaza zeljeni format vremena
if (read(STDIN_FILENO, format, 50) < 0)
fatalError("read() error");
// zapisujemo trenutno vreme
time(&t);
strftime(formattedTime, 50, format, localtime(&t));
int n;
n = strlen(formattedTime) + 1;
// ispisujemo na izlaz
if (write(STDOUT_FILENO, formattedTime, n) != n)
fatalError("write() error");
return 0;
}
右输出:
%a %b %d
Wed Jan 16
错误的输出:
%a %b %d
Wed Jan 16
0
为什么在调用n
的前一步就计算write
会带来不同?
编辑: 希望这能满足所有信息。每次都乱七八糟,但要点仍然存在。
答案 0 :(得分:3)
如果您确实有这种行为,则可能意味着 formattedTime 中缺少空字符,并且偶然地 n 在堆栈中,并通过其引入了空字符存在,或由于存储在堆栈中的数据而造成的等效结果
答案 1 :(得分:1)
read
函数主要用于读取二进制数据,而不是字符串。这样,它仅读取您输入的字符(即字符序列,后跟换行符),而不会添加空终止字节。结果,您没有正确格式化的字符串,因此使用strftime
可以读取写入未初始化的字节中的内容,也可以读取数组末尾的内容。这将调用undefined behavior。
“正确的版本”似乎有效,因为您很幸运。这是未定义行为表现出来的方式之一。其他人可能会看到与您看到的结果相反的结果。
您需要捕获已读取的字节数并手动向该数组添加一个终止的空字节:
int rval;
if ((rval=read(STDIN_FILENO, format, 49)) < 0)
fatalError("read() error");
format[rval] = 0;