gpt4 book ai didi

c - POSIX 读取 (2),意外行为

转载 作者:太空宇宙 更新时间:2023-11-04 08:56:40 25 4
gpt4 key购买 nike

我在学习测试中使用 read(2) 时遇到一些问题。

代码如下:

#include <stdio.h>

int main() {
size_t length;
read(0, &length, sizeof(length));
printf("input = %u\n", length);

return 0;
}

我想这段代码将从 stdio 读取 8 个字节(即 ascii 字符),并将它们存储在长度变量中。然后它会把这8个字节对应的unsigned int值打印到stdout。

所以,让我的测试如下:从 linux 终端运行这个程序,然后点击“enter”。我希望 length 的值仅为 10(换行字符的 ascii 值)。

但是运行这个测试(也是很多次):

$ ./test
len = 4195338

但是这个版本的代码像我期望的那样工作:

#include <stdio.h>

int main() {
int a = 10;
size_t length;
int b = 123;
ssize_t n = read(0, &length, sizeof(length));
printf("input = %u\n", length);

return 0;
}


$ ./test
input = 10

那么,有什么意义呢?为什么如果我添加一些随机的和未使用的变量,并且如果我存储 read() 的返回值,相同输入的输出会不同?

注意我知道 read(2) 是一个原始系统调用,不应该从终端读取输入,这只是一个学习问题。

最佳答案

如果 sizeof(size_t) == 8,代码将读取 8 个字节 — true。

一般来说,这些字节不会全部是 ASCII(这意味着有些字节将设置第 8 位并且值在 0x80..0xFF 范围内,这不是 ASCII 的一部分)。

但是,没有字符的转换。如果您的文件包含 12345678,则该值将为 0x3132333435363738(或者可能为 0x3837363534333231)。如果需要转换,则不要使用 read(2)

printf() 格式应该是 %zu (C99) 或 %lu (C89 with size_t相当于64位unsigned long;当然不能是unsigned long long和C89)。

请注意,您的示例输出并非来自您的示例代码。示例输出显示 len = ... 但代码会生成 input = ...。因此,您的问题之一可能是您没有测试您认为正在测试的内容。

你的评论:

I know that read(2) is a raw system call and is not supposed to read input from terminal.

read(2) 系统调用(可能)被 getchar() 等函数用来从终端读取数据。用它从终端读取并没有错。从终端读取到字符数组以外的内容可能是不正确的。


I simply run the program from terminal, and then hit enter from keyboard.

哦。打扰。我从没想过你会那样做。

好吧,你将一个字节的数据读入一个需要 8 个字节的变量中,你会得到垃圾。您的变量未可靠初始化。

这是一个带有示例输出的 SSCCE ( Short, Self-Contained, Correct Example ):

#include <stdio.h>
#include <unistd.h>

int main(void)
{
size_t length = 0xFFFFFFFFFFFFFFFF;
int nbytes = read(0, &length, sizeof(length));
printf("nbytes = %d: input = %zu (0x%zX)\n", nbytes, length, length);
return 0;
}

两个样本运行:

$ ./test

nbytes = 1: input = 18446744073709551370 (0xFFFFFFFFFFFFFF0A)
$ ./test
12345678
nbytes = 8: input = 4050765991979987505 (0x3837363534333231)
$ ./test < /dev/null
nbytes = 0: input = 18446744073709551615 (0xFFFFFFFFFFFFFFFF)
$

你看到那里发生了什么吗?请注意,SSCCE 代码关注并报告读取的字节数。始终检查类似读取操作的返回值很重要(这里,这具体意味着 read());如果您没有获得预期的那么多数据,那么您的结果也可能不是您预期的那样。在“命中换行符”的情况下使用值可能是“未定义的行为”,尽管显示的行为是您通常会得到的。

(在 Mac OS X 10.8.3 上使用 GCC 4.7.1 进行测试 — Intel 芯片,little-endian。)

关于c - POSIX 读取 (2),意外行为,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16622565/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com