2013-05-18 23 views
0

我在学习测试中使用read(2)时遇到了一些问题。POSIX读取(2),意外行为

的代码如下:

#include <stdio.h> 

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

    return 0; 
} 

我想,这个代码将读取从标准输入输出8个字节(即ASCII字符),将它们存储在可变长度。然后它将打印出标准输出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()的返回值,那么来自同一输入的输出将有所不同?

N.B.我知道read(2)是一个原始系统调用,不应该读取来自终端的输入,这只是一个学习问题。

+1

如何为'/ test'将数据输入程序?在程序中键入什么 - 输入数据是什么。 (还有一个'len = 4195338',这大概应该是'input = 4195338'。) –

+0

@JonathanLeffler我只是从终端运行程序,然后按键盘输入。 – eang

回答

1

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

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

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

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

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

您发表评论:

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

read(2)系统调用(可能)被诸如getchar()之类的函数用于从终端读取。使用它从终端读取是不正确的。从终端读入字符数组以外的东西可能是不正确的。


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

哦。烦。我从来没有想到你会那样做。那么,你读取一个字节的数据到一个变量,需要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()具体);如果您没有获得足够的数据,您的结果可能与您的预期不符。在'hit newline'事件后使用这个值可能是'未定义的行为',虽然显示的行为是你通常得到的。

(测试用在Mac OS X 10.8.3 GCC 4.7.1 - 英特尔芯片,小端)

+0

对不起,'len = ...'只是复制粘贴过程中的一个错误。我编辑过。感谢您的其他信息。 – eang

+1

提供SSCCE([Short,Self-Contained,Correct Example](http://sscce.org/))有很大的好处,因为那样我们就可以看到你真正在做什么。它只会将6-10行(最大)添加到代码中。它也可能回答你的程序输入的奥秘 - 你还没有显示。 –

+0

只有main()相关的LOC。顺便说一句,我会编辑这个问题。 ^^ – eang

1

如果为size_t为8字节尝试%LLU在你的printf