比较 unsigned char 和 EOF

发布于 2024-12-22 09:45:27 字数 703 浏览 3 评论 0原文

当编译以下代码时,它会进入无限循环:

int main()
{
    unsigned char  ch;
    FILE *fp;
    fp = fopen("abc","r");
    if(fp==NULL)
    {
        printf("Unable to Open");
        exit(1);
    }
    while((ch = fgetc(fp))!=EOF)
    printf("%c",ch);
    fclose(fp);
    printf("\n",ch);
    return 0;
}

gcc 编译器还会在编译时发出警告,

abc.c:13:warning: comparison is always true due to limited range of data type

unsigned charchar替换时,代码运行良好int 正如预期的那样,它终止。
但该代码对于 unsigned int 也运行良好。 正如我所读到的, EOFstdio.h 中定义为 -1 那么为什么这段代码对于 unsigned char 失败但运行良好对于无符号整数。

when the following code is compiled it goes into an infinite loop:

int main()
{
    unsigned char  ch;
    FILE *fp;
    fp = fopen("abc","r");
    if(fp==NULL)
    {
        printf("Unable to Open");
        exit(1);
    }
    while((ch = fgetc(fp))!=EOF)
    printf("%c",ch);
    fclose(fp);
    printf("\n",ch);
    return 0;
}

The gcc Compiler also gives warning on compilation

abc.c:13:warning: comparison is always true due to limited range of data type

the code runs fine when unsigned char is replaced by char or int as expected i.e. it terminates.
But the code also runs fine for unsigned int as well.
as i have i have read in EOF is defines as -1 in stdio.h then why does this code fails for unsigned char but runs fine for unsigned int.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

诠释孤独 2024-12-29 09:45:27

编写此行的黄金法则是

   while ((ch = fgetc(stdin)) != EOF)

ch 应该是 int 。使 ch 无符号的可爱技巧失败了,因为EOF 是一个有符号 int 数量。

好吧,现在让我们深入探讨......

第 1 步:

ch=fgetc(fp)

fgetc() 返回 -1 (一个带符号的 int)。根据 C 的黄金法则,ch 获取最后一个八位字节,全部为 1。因此值为 255。执行后ch的字节模式

ch = fgetc(fp); 

将是

11111111

步骤2:

ch != EOF

现在EOF是一个有符号整数并且ch 是一个 unsigned char ...

我再次参考 C 的黄金法则...较小的家伙 ch 转换为大尺寸int 在比较之前,所以它的字节模式现在是

00000000000000000000000011111111 = (255)10

,而 EOF

11111111111111111111111111111111 = (-1)10

他们不可能相等......因此引导以下 while 循环的语句

while ((ch = fgetc(stdin)) != EOF)

永远不会计算为 false ...

因此是无限循环。

The golden rule for writing this line is

   while ((ch = fgetc(stdin)) != EOF)

ch should be int .Your cute trick of making ch unsigned fails because EOF is a signed int quantity.

Ok, let's now go into the depth......

Step 1:

ch=fgetc(fp)

fgetc() returns -1 (a signed int). By the golden rules of C ch gets the last octet of bits which is all 1's. And hence the value 255. The byte pattern of ch after the execution of

ch = fgetc(fp); 

would thus be

11111111

Step 2:

ch != EOF

Now EOF is a signed integer and ch is an unsigned char ...

Again I refer to the golden rule of C ... the smaller guy ch is converted to big size int before comparision so its byte pattern is now

00000000000000000000000011111111 = (255)10

while EOF is

11111111111111111111111111111111 = (-1)10

There is no way they can be equal....... Hence the statement to steer the following while-loop

while ((ch = fgetc(stdin)) != EOF)

will never evaluate to false ...

And hence the infinite loop .

酷遇一生 2024-12-29 09:45:27

有几个隐式转换正在进行。它们与特定警告并不真正相关,但我将它们包含在这个答案中以显示编译器对该表达式的真正作用。

  • 您的示例中的 ch 是 unsigned char 类型。
  • EOF 保证为 int 类型(C99 7.19.1)。

因此,该表达式相当于

(unsigned char)ch != (int)EOF

C 中的整数提升规则将隐式地将 unsigned char 转换为 unsigned int:

(unsigned int)ch != (int)EOF

然后 C 中的平衡规则(又名通常的算术转换)将隐式将 int 转换为 unsigned int,因为每个操作数必须具有相同的类型:

(unsigned int)ch != (unsigned int)EOF

在您的编译器上 EOF 可能是 -1:

(unsigned int)ch != (unsigned int)-1

假设 32 位 CPU,它与 A 字符永远不会有如此高的值相同

(unsigned int)ch != 0xFFFFFFFFu

,因此 警告。

There are several implicit conversions going on. They aren't really relevant to the specific warning, but I included them in this answer to show what the compiler really does with that expression.

  • ch in your example is of type unsigned char.
  • EOF is guaranteed to be of type int (C99 7.19.1).

So the expression is equivalent to

(unsigned char)ch != (int)EOF

The integer promotion rules in C will implicitly convert the unsigned char to unsigned int:

(unsigned int)ch != (int)EOF

Then the balancing rules (aka the usual arithmetic conversions) in C will implicitly convert the int to unsigned int, because each operand must have the same type:

(unsigned int)ch != (unsigned int)EOF

On your compiler EOF is likely -1:

(unsigned int)ch != (unsigned int)-1

which, assuming 32-bit CPU, is the same as

(unsigned int)ch != 0xFFFFFFFFu

A character can never have such a high value, hence the warning.

讽刺将军 2024-12-29 09:45:27

我也遇到过这个问题。我的解决方案是使用 feof()。

unsigned int xxFunc(){
  FILE *fin;
  unsigned char c;
  fin = fopen("...", "rb");
  if(feof(fin) != 0) return EOF;
  c = fgetc(fin);
  fclose(fin);
...
}

您可以定义一个 int 变量来与 EOF 进行比较。例如:

int flag = xxFunc();
while(flag != EOF) {...}

这对我有用。

**重要更新***

之后使用我之前提到的方法,我发现了一个严重的问题。
feof() 不是打破 while 循环的好方法。
原因如下。 http://www.gidnetwork.com/b-58.html

所以我找到了一个更好的方法来做到这一点。我使用 int 变量来做到这一点。这里:

int flag;
unsigned char c;
while((flag = fgetc(fin)) != EOF) 
{ 
  //so, you are using flag to receive, but transfer the value to c later.
  c = flag;
  ... 
}

经过我的测试,这是有效的。

I have encountered this problem too. My solution is to use feof().

unsigned int xxFunc(){
  FILE *fin;
  unsigned char c;
  fin = fopen("...", "rb");
  if(feof(fin) != 0) return EOF;
  c = fgetc(fin);
  fclose(fin);
...
}

And you can define an int variable to compare with EOF. For example:

int flag = xxFunc();
while(flag != EOF) {...}

This works for me.

**IMPORTANT UPDATE***

After using the method I mentioned before, I found a serious problem.
feof() is not a good way to break the while loop.
Here is the reason for it. http://www.gidnetwork.com/b-58.html

So I find a better way to do this. I use an int variable to do it. here:

int flag;
unsigned char c;
while((flag = fgetc(fin)) != EOF) 
{ 
  //so, you are using flag to receive, but transfer the value to c later.
  c = flag;
  ... 
}

After my test, this works.

我喜欢麦丽素 2024-12-29 09:45:27

您需要使用 int

fgetc() 专门返回一个 int ,以便它可以指示文件结尾

,它可以使用有符号的 char 运行良好,因为 EOF (-1) 在范围内,但如果您使用 char 读取它会中断值大于 127。

使用 int,在检查 EOF 后将其转换为 char

you need to use an int

fgetc() returns an int specifically so that it can indicate the end of file

it runs fine with signed char because EOF (-1) is in the range, but it would break if you read in a char with value greater than 127.

Use an int, cast it to a char after you've checked for EOF

一影成城 2024-12-29 09:45:27

当您将无符号整型与有符号整型进行比较时,它将有符号整型转换为无符号整型并进行比较。因此,当您使用 unsigned int 'ch' 读取文件时,读取 EOF 会为您提供 2^32+1 (在 4 字节 int 机器上),并且当将其与 EOF 进行比较时,它将 EOF 转换为 unsigned,这也是 2^ 32+1,因此程序停止!

如果您使用 unsigned char ch,当您读取文件时,读取 EOF 返回 2^32+1,并且这将被转换为 unsigned char,这会将值截断为前 8 位(在 1 字节字符机器上)并给出您输出为 255。因此,您正在比较 255 和 2^32+1,从而导致无限循环。

这里的问题是比较之前截断。

如果你使用

while((ch = fgetc(fp))!=(unsigned char)EOF)
    printf("%c",ch);

你的程序将运行良好!

When you compare an unsigned int with a signed int, it converts the signed int to unsigned int and compares them. Hence when you are reading the file with an unsigned int 'ch', reading an EOF gives you 2^32+1 (on a 4 byte int machine) and when comparing it with EOF, it converts EOF to unsigned which is also 2^32+1 and hence the program stops!

If you use unsigned char ch, when you read the file, reading EOF returns 2^32+1, and this will be casted to unsigned char, which truncates the value to first 8 bits (on a 1 byte char machine) and gives you an output of 255. Hence you are comparing 255 and 2^32+1, causing an infinite loop.

The problem here is truncating before compare.

If you use

while((ch = fgetc(fp))!=(unsigned char)EOF)
    printf("%c",ch);

you program will run fine!

不美如何 2024-12-29 09:45:27

这种实现方式会产生 lint 警告

比较类型“char”与 EOF

 // read the data in a buffer
611     ch = getc(csv_file);
612     while (ch != EOF)

FIX 进行比较:

// read the data in a buffer
    while ((ch = getc(csv_file)) != EOF)

a lint warning is produced with this kind of implementation

Comparing type 'char' with EOF

 // read the data in a buffer
611     ch = getc(csv_file);
612     while (ch != EOF)

FIX:

// read the data in a buffer
    while ((ch = getc(csv_file)) != EOF)
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文