为什么在fopen()中使用无效模式时gcc不会发出警告或错误?

时间:2015-02-16 00:45:09

标签: c gcc file-io compiler-errors compiler-warnings

我正在C中的FILE IO中练习一些练习题。下面是其中一个程序。

#include<stdio.h>
#include<stdlib.h>

int main()
{
    char fname[]="poem.txt";
    FILE *fp;
    char ch;
    fp = fopen ( fname, "tr");
    if (fp == NULL)
    {
    printf("Unable to open file...\n");
    exit(1);
    }
    while((ch =fgetc(fp)) != EOF)
    {
            printf("%c",ch);
    }
    printf("\n");

    return 0;
}

正如你在声明中所看到的那样

  fp = fopen ( fname, "tr");

模式&#34; tr&#34;不是有效模式(据我所知)。我期待gcc在编译上述程序时给出错误(或警告)。但是,gcc在编译时不会给出任何错误(或警告)。

然而,正如预期的那样,当我运行该程序时,它退出打印&#34;无法打开文件......&#34;这意味着fopen()返回NULL,因为打开文件时出错。

-bash-4.1$ ./a.out
Unable to open file...
-bash-4.1$

(文件poem.txt存在所以这是因为给fopen()的模式无效。我通过将模式更改为&#34; r&#34;来检查它是否正常显示&#34的内容;一下poem.txt&#34)

-bash-4.1$ ./a.out
THis is a poem.

-bash-4.1$

我期待gcc为无效模式发出错误(或警告)消息。

为什么gcc不会给出任何错误(或警告)?

4 个答案:

答案 0 :(得分:2)

编译器没有检查你做了什么,它只检查语法。

但是,在运行时,如果代码是这样写的:

#include<stdio.h>
#include<stdlib.h>

int main()
{
    char fname[]="poem.txt";
    FILE *fp;
    char ch;

    fp = fopen ( fname, "tr");
    if (fp == NULL)
    {
        perror( "fopen for poem.txt failed");
        exit( EXIT_FAILURE );
    }

    while((ch =fgetc(fp)) != EOF)
    {
            printf("%c",ch);
    }
    printf("\n");

    return 0;
}

然后输出正确的错误消息:

... $ ./untitled

fopen for poem.txt失败:参数无效

答案 1 :(得分:1)

编译器如何知道函数的有效参数是什么?

要做到这一点,你将在编译器中构建太多的知识 - 它必须通过名称识别函数及其参数。如果要覆盖该功能怎么办?如果不同模式在不同平台上有效会怎样?

答案 2 :(得分:1)

这是未定义的行为:

根据附件J.2“未定义的行为”,如果出现以下是UDB:

  

- 调用fopen函数时mode参数指向的字符串与指定的字符序列之一不完全匹配(7.19.5.3)。

虽然附件J是提供信息的,但请参阅§7.19.5.3:

  

/ 3参数模式指向一个字符串。如果字符串是以下之一,则文件以指示的模式打开。否则,行为未定义。

基本上,编译器可以在这里吹你 - 标准库函数名称(和行为)可以在包含标准头之外使用(例如,非标准扩展,完全用户定义的行为等。 )。标准规定了符合标准的库实现应包括的内容及其行为方式,但不要求您使用该标准库(或定义明确指定为UDB区域的特定实现的行为:此时,如果您的参数类型与其匹配)法律职能电话)。

非常好的lint实用程序可能会对您有所帮助。

答案 3 :(得分:0)

在Windows编程中,"tr" 是有效模式不是有效模式,尽管"rt" ist表示文字,r表示读取。 (如果您正在使用gcc并链接到MS的C运行时,那么您将能够使用它。)

但是你仍然经常看不到t,因为它是默认的,因此是多余的;此设置的另一个选项是b,意思是二进制。但MS似乎确实在他们的示例中明确使用t来明确表示翻译是有意的。

流的文本模式二进制模式的行为是实现定义的,尽管意图是二进制模式读取字符与它们出现在磁盘上完全一样,文本模式可以执行与文本处理相关的翻译;最着名的是,将MS文本文件中的\r\n转换为程序中的\n