getchar()的思考
memcpy还是memmove?

getchar 的思考v0.2

风中纸页 posted @ 2008年7月10日 05:03 in 程序设计 , 2765 阅读
转贴请保留本文作者及文章地址

通常我们学到的库函数getchar()会从标准输入得到一个字符,其返回值为intread as an `unsigned char', and cast to `int'.返回值为int的原因大致就是为了照顾特殊的EOF吧。

 

如果运行下面的程序:

 

 

#include <stdio.h>

int main(void)
{
      char a = 0;

      while ( (a = getchar()) && (a != EOF)) {
           putchar(a);
      }
      return 0;
}

 

 

==========

 

Hello,World!

 

输出:

 

Hello,World!

 

会发现居然能够输出整个字符串。其实跟踪一下代码即可发现原因。另外,在手册中还有说明:'getchar' is a macro, defined in `stdio.h'. You can use `getchar' to get the next single character from the standard input stream. As a side effect, `getchar' advances the standard input's current position indicator.这个就解释了为什么会把整个终端输入的所有内容都输出。

 

==========

这个程序还有更重要的问题是关于getchar()这个(类)函数的使用(返回值)。

RETURNS

The next character (read as an `unsigned char', and cast to `int')

 

这意味着getchar的返回值会是int让我们看看代码来深入了解一下为什么getchar要返回一个int值呢?

在glibc的源码中getchar()的实现如下:

 

#define _IO_getc_unlocked(_fp) '
(_IO_BE ((_fp)->_IO_read_ptr >= (_fp)->_IO_read_end, 0) '
? __uflow (_fp) : *(unsigned char *) (_fp)->_IO_read_ptr++)


int
getchar ()
{
int result;
_IO_acquire_lock (_IO_stdin);
result = _IO_getc_unlocked (_IO_stdin);
_IO_release_lock (_IO_stdin);
return result;
}

 

CEOF是一个整型,和任何的char类型都不相同。在上面的代码中_IO_getc_unlocke会返回当前_IO_read_ptr的字符,类型为unsigned char当读取到结束时就会返回__uflow_uflow就会返回EOF。因此EOFglibc中就定义为-1,这个值和任何一个unsigned char都不相同。在_IO_getc_unlocked 返回的时候就要返回一个int值来“照顾”EOF这个特殊角色了。

 

再请回头看在最开始的测试程序中变量a的类型是char。问题就处在这里了:对于char这种类型是signed char还是unsigned char是由编译器决定的。既然EOF是一个和unsigned char 类型(0x00~0xFF)不同的数据,显然char无论是signed char 还是unsigned char都是无法满足EOF的值,对于a != EOF这个条件就永远无法满足了。这样显然我们期望满足的unsigned char数值(0x00~0xFF),又要满足EOF的数据类型,显然int是比较合适的。

 

==========

关于while ( (a = getchar()) && (a != EOF))

 

这里我有意写成这样的原因是想着重说明一下: 对于赋值表达式的值即为赋值以后的左值。即上式同义为while((a = getchar() != EOF) 还要说一下的是 = 的优先级要比 != 低,因此要给 a = getchar 加括号以提升优先级。

 

最后要感谢

 

  • 无匹配
Avatar_small
说:
2008年7月10日 06:55

不客气啊。
不过还有一个问题,如果char和int比较的话,两者会先转换成相同的长度,这里char,用C的术语来说就是会提升到int,然后再做比较。不过对于signed char和unsigned char会有不同的扩展方式,假设a仍然定义为char,那么当返回EOF时,a的值用二进制表示为11111111,对于signed char会进行符号扩展,变成11111111111111111111111111111111,
仍然是-1,所以和EOF的值是相等的,对于unsigned char来说则会进行零扩展00000000000000000000000011111111,所以就不会和EOF的值相等了。

Head_small
风中纸页 说:
2008年7月11日 06:28

谢谢! 我接下来应该写一个关于数据转换的小文章来说明这个问题。

part time maids in d 说:
2022年4月22日 18:05

Cleanliness can be a basic need that stimulates good and also healthy living. But usually, it needs more energy than everything you can offer you. A washing service means that your life-style runs well with additional productivity and also great defense. However, you’ll encounter various program companies offering you washing services. It's rather a difficult task to produce a decision which is healthier based on your own requirements and also preferences. Properly, to help make things easier to suit your needs, there are usually prominent reasons for you to consider availing any cleaning program from DIALAMAID. Read more to learn.

maids in dubai 说:
2022年4月22日 18:21

In case you are trying to discover a maid inside Dubai who focuses primarily on kitchen washing then we will probably be your ultimate remedy. All individuals housemaids are usually kitchen washing specialists. They will care for every second detail within your kitchen. Beginning scrubbing the particular floors and counters and eliminating the fat and dirt from your kitchen surfaces, maids can assist you. They may also clean the particular appliances and also ensure to keep up the hygiene amount of your cooking area.


登录 *


loading captcha image...
(输入验证码)
or Ctrl+Enter