0

我在学习测试中使用 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 char),并将它们存储在长度变量中。然后它将 8 个字节的相应 unsigned int 值打印到标准输出。

所以,让我的测试如下:从 linux 终端运行这个程序,然后点击“enter”。我希望长度的值只是 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) 是一个原始系统调用,不应该从终端读取输入,这只是一个学习问题。

4

2 回答 2

1

如果 size_t 是 8 个字节,请在 printf 中尝试 %llu

于 2013-05-18T09:22:12.213 回答
1

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

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

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

printf()格式应该是( %zuC99) 或%lu(C89 withsize_t相当于 64-bit unsigned long;当然不能是unsigned long longC89)。

请注意,您的示例输出不是来自您的示例代码。示例输出显示,len = ...但代码会生成input = .... 所以,你的问题之一可能是你没有测试你认为你正在测试的东西。

你评论:

我知道 read(2) 是一个原始系统调用,不应该从终端读取输入。

系统read(2)调用(可能)由诸如getchar()从终端读取的功能使用。使用它从终端读取并没有错。从终端读取字符数组以外的内容可能是不正确的。


我只是从终端运行程序,然后从键盘输入。

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

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

这是一个带有示例输出的 SSCCE(简短、独立、正确的示例):

#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()特别);如果您没有获得预期的数据,那么您的结果也可能不是您预期的。在“hit newline”案例之后使用该值可能是“未定义的行为”,尽管显示的行为是您通常会得到的。

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

于 2013-05-18T09:22:45.967 回答