简体   繁体   English

编译错误

[英]Compilation errors

I've been creating a function that's supposed to open a file (catalogname []) . 我一直在创建一个应该打开文件的函数(catalogname []) However whenever I compile I get these two errors that I can't figure out. 但是,每当我编译时,我都会得到我无法弄清的两个错误。

a3.c: In function 'openCatalog': a3.c:在函数“ openCatalog”中:

a3.c:20: warning: assignment from incompatible pointer type a3.c:20:警告:来自不兼容指针类型的赋值

a3.c:22: warning: return makes pointer from integer without a cast a3.c:22:警告:return使指针从整数开始而不进行强制转换

Here is my code: 这是我的代码:

FILE* openCatalog(char catalogname[])
{
    catalogname = fopen ("*catalogname", "r");
    if(fopen != 0)
    {
        return 1;
    }
    else 
    {
        return 0;
    }
}

Thanks in advance for any insight you can provide. 在此先感谢您提供的任何见解。

A full exegesis on this code will take a while. 有关此代码的完整解释,需要一些时间。

The brief version is: 简短的版本是:

FILE *openCatalog(char catalogname[])
{
    FILE *fp = fopen(catalogname, "r");
    return(fp);
}

This opens the named file for reading and returns the file stream pointer. 这将打开已命名的文件以供读取,并返回文件流指针。

An alternative brief version checks whether the file can be opened: 另一个简短版本检查文件是否可以打开:

int openCatalog(char catalogname[])
{
    FILE *fp = fopen(catalogname, "r");
    if (fp != 0)
    {
        fclose(fp);
        return 1;
    }
    else 
    {
        return 0;
    }
}

Exegesis 注释

The original code is: 原始代码是:

FILE* openCatalog(char catalogname[])
{
    catalogname = fopen ("*catalogname", "r");
    if(fopen != 0)
    {
        return 1;
    }
    else 
    {
        return 0;
    }
}

We don't have a specification beyond 'open the file'. 除了“打开文件”之外,我们没有其他规范。 Given the function signature, it appears that you want the FILE * (file stream pointer) for the open file returned. 给定函数签名后,您似乎希望返回打开文件的FILE * (文件流指针)。 So, let's critique the code on that basis. 因此,让我们在此基础上对代码进行评论。

  • The function prototype line is OK; 功能原型行可以; it could be char const catalogname[] to emphasize that the function won't modify the file name, but that's a refinement, not a bug-fixing change. 可以使用char const catalogname[]来强调该函数不会修改文件名,但这只是一种改进,而不是错误修复的更改。

  • The type of catalogname in the function is char * . 该类型的catalogname在功能char * In a function's argument list, an array is loosely equivalent to a pointer. 在函数的参数列表中,数组大致等同于指针。 I'd normally write FILE *openCatalog(char const *catalogname) to emphasize that within the function, it is a char const * variable. 我通常会写FILE *openCatalog(char const *catalogname)来强调函数内,它是char const *变量。 Nevertheless, it is 100% legitimate to use the array notation you used; 但是,使用您使用的数组符号是100%合法的。 it is purely a stylistic preference for me to use the pointer notation. 对我而言,使用指针表示法纯粹是一种风格偏好。

  • The next executable line has a couple of problems. 下一个可执行行有两个问题。 The function call to fopen() is not technically wrong, though it opens a file with a fixed name *catalogname rather than the file specified in the variable catalogname . fopen()的函数调用在技术上没有错,尽管它会打开一个具有固定名称*catalogname的文件,而不是使用变量catalogname指定的文件。 To fix that, you need to remove the quotes. 要解决此问题,您需要删除引号。 The * would give you a character instead of a string, and it would be the first character of the file name. *将给您一个字符而不是一个字符串,它是文件名的第一个字符。 So, remove the * too. 因此,也请删除*

  • This leaves you with fopen() returning a value, actually a FILE * , and you assign it to catalogname , a char * . 这使您留给fopen()返回一个值,实际上是一个FILE * ,并将其分配给catalogname ,一个char * This is a type mismatch, which the compiler warns about. 这是类型不匹配,编译器会警告该类型不匹配。 As shown in the first rewrite, the more normal way to handle this would be: 如第一次重写所示,更一般的处理方法是:

     FILE *fp = fopen(catalogname, "r"); 

    This accounts for your error message: 这说明了您的错误消息:

     a3.c:20: warning: assignment from incompatible pointer type 
  • We do not know whether your catalog is a text file or a binary file. 我们不知道您的目录是文本文件还是二进制文件。 If it is a binary file, then you should use "rb" to open it if you are on Windows (where it really matters), and that will work fine on Unix-like systems too (where there is no distinction between text and binary files). 如果它是一个二进制文件,那么如果您在Windows上(它确实很重要),则应该使用"rb"将其打开,并且在类似Unix的系统上也可以正常工作(在文本和二进制文件之间没有区别)文件)。

  • The next line in your code is the conditional: 代码中的下一行是有条件的:

     if (fopen != 0) 

    This actually checks whether the function pointer for the function fopen() is null or not. 这实际上检查函数fopen()的函数指针是否为null。 And the C standard guarantees that in a hosted environment (which you are using), no function pointer will be null. C标准保证在托管环境(您正在使用)中,没有任何函数指针为null。 So the compiler can optimize that test to assume that the condition is always true. 因此,编译器可以优化该测试以假定条件始终为真。

    What you actually need is a test of the result: 您实际需要的是对结果的测试:

     if (fp != 0) 
  • You then have two return statements, one returning 1, one returning 0. The one returning 1 elicits a warning about converting an integer to a pointer because the function is defined to return a FILE * and 1 is an integer. 然后,您有两个return语句,一个返回1,一个返回0。一个返回1引发有关将整数转换为指针的警告,因为该函数已定义为返回FILE *并且1是整数。

    This accounts for your other warning message: 这说明了您的其他警告消息:

     a3.c:22: warning: return makes pointer from integer without a cast 
  • The return returning 0 does not generate a warning because 0 is a null pointer constant, and that is a valid value for a function like this to return. 返回值为0的返回值不会产生警告,因为0是一个空指针常量,并且对于像这样的函数来说,这是一个有效值。

  • The code should probably simply return the value from fopen() . 代码可能应该简单地从fopen()返回值。 It is correct to test the value somewhere, either in this function or in the calling function, to ensure that the open succeeded. 在此函数或调用函数中的某处测试该值是正确的,以确保打开成功。 You might test it here with: 您可以在这里进行测试:

     if (fp == 0) err_report_and_exit("Failed to open file %s (%d: %s)\\n", catalogname, errno, strerror(errno)); 

    Using errno and strerror() means that you should also include the headers: 使用errnostrerror()意味着还应该包含标题:

     #include <errno.h> #include <string.h> 
  • The code should return the file stream from fopen() : 该代码应从fopen()返回文件流:

     return fp; 

In total, that leads to: 总体而言,这导致:

FILE *openCatalog(char catalogname[])
{
    FILE *fp = fopen(catalogname, "r");
    if (fp == 0)
        err_report_and_exit("Failed to open file %s (%d: %s)\n",
                            catalogname, errno, strerror(errno));
    return(fp);
}

The problems cited above are much the same if the function is intended to check whether the file can be opened for reading. 如果该功能旨在检查文件是否可以打开以供读取,则上面引用的问题几乎相同。 The revised code I showed first is slightly verbose. 我首先显示的修订代码有些冗长。 Since the presumed purpose is to check whether the file can be opened, the calling code should be responsible for dealing with the 'it cannot be opened case'; 由于假定的目的是检查文件是否可以打开,因此调用代码应负责处理“无法打开的情况”; it knows what sort of diagnostic to generate. 它知道要生成哪种诊断。 This is a slightly more compact version of the revision, but the object code for the this and the one above would be identical. 这是该修订版的紧凑版本,但是this和上面的那个的目标代码是相同的。

int openCatalog(char catalogname[])
{
    FILE *fp = fopen(catalogname, "r");
    if (fp != 0)
    {
        fclose(fp);
        return 1;
    }
    return 0;
}

A simple implementation of err_report_and_exit() is: err_report_and_exit()简单实现是:

#include "errreport.h"
#include <stdio.h>
#include <stdlib.h>
#include <starg.h>

void err_report_and_exit(char const *format, ...)
{
    va_list args;
    va_start(args, format);
    vfprintf(stderr, format, args);
    va_end(args);
    exit(EXIT_FAILURE);
}

The "errreport.h" header might be: “ errreport.h”标头可能是:

#ifndef ERRREPORT_H_INCLUDED
#define ERRREPORT_H_INCLUDED

#ifdef __GNUC__
#define PRINTFLIKE(n,m) __attribute__((format(printf,n,m)))
#define NORETURN()      __attribute__((noreturn))
#else
#define PRINTFLIKE(n,m) /* If only */
#define NORETURN()      /* If only */
#endif /* __GNUC__ */

extern void err_report_and_exit(char const *format, ...) PRINTFLIKE(1,2) NORETURN();

#endif /* ERRREPORT_H_INCLUDED */

The GCC-specific bits mean that you get the same level of format error reporting as if you were using printf() directly. 特定于GCC的位意味着您将获得与直接使用printf()相同级别的格式错误报告。

(This code is modelled on a bigger package that systematically uses err_ as a function prefix. In that package, this function would be err_error() . That's why it is err_ rather than error_ — though the explanation takes longer to type than it would to fix it. The big package is contained in files stderr.c and stderr.h , though there's an argument that it is treading on thin ice using the std prefix. It is, however, my standard error reporting package.) (此代码以更大的程序包为模型,该程序包系统地使用err_作为函数前缀。在该程序包中,该函数将是err_error() 。这就是为什么它是err_而不是error_ -尽管解释输入的时间比输入的时间长大文件包包含在文件stderr.cstderr.h ,尽管有一个论点说使用std前缀它已经stderr.c stderr.h 。但是,这是我的标准错误报告包。)

  • Incompatible pointer type 指针类型不兼容

     catalogname = fopen ("*catalogname", "r"); 

    catalogname is an array of chars ( char catalogname[] ), while fopen() returns a file pointer ( FILE* ). catalogname是一个chars数组( char catalogname[] ),而fopen()返回一个文件指针( FILE* )。 Naturally, assignment of file pointer to char array (which is a different kind of pointer - and, what's more, unassignable) doesn't make any sense. 自然地,将文件指针分配给char数组(这是另一种类型的指针,而且是无法分配的)没有任何意义。

  • return makes pointer from integer without a cast return使指针从整数开始而无需强制转换

    You declare that your function returns FILE* here: FILE* openCatalog(...) . 您在此处声明函数返回FILE*FILE* openCatalog(...) But, your return statements are return 1; 但是,您的return语句为return 1; and return 0; return 0; . There, the compiler thinks you want to to return a file pointer of value 1 (or 0), hence the response. 在那里,编译器认为您想返回值为1(或0)的文件指针,从而返回响应。

FILE* openCatalog(char catalogname[])

This would be better as char *catalogname , as you're not actually getting passed an array -- you're getting a pointer to a character. 最好使用char *catalogname ,因为实际上并没有传递数组 -您正在获得指向字符的指针。 (It's a funny little quirk of C.) While this works, I find the reminder that you're only getting a pointer is very welcome. (这是对C的一个有趣的小怪癖。)尽管如此,但我发现提醒您,只得到一个指针是非常受欢迎的。

catalogname = fopen ("*catalogname", "r");

fopen(3) returns a FILE* object. fopen(3)返回FILE*对象。 You cannot assign a FILE* to a char [] variable. 您不能将FILE*分配给char []变量。

If you want to use the catalogname variable in the fopen(3) call, just use it: 如果要在fopen(3)调用中使用catalogname变量,请使用它:

FILE *f = fopen(catalogname, "r");
if(fopen != 0)

fopen is a function pointer in this context. 在这种情况下, fopen是一个函数指针 You're not comparing the return value of the previous fopen() call against 0 , but instead the function pointer against 0 . 您不是将前一个fopen()调用的返回值与0 ,而是将函数指针0 That's not what you want. 那不是你想要的。

    return 1;

You declared your function to return a FILE * , and that is what you should return -- not an integer. 您声明了要返回FILE *函数,这就是应该返回的内容-而不是整数。

A re-written version would look like this: 重新编写的版本如下所示:

FILE* openCatalog(char *catalogname) {
    FILE *f = fopen(catalogname, "r");
    if (!f)
        perror("Unable to open file");
    return f;
}

Actually, you have quite a few errors, some of which hare masked 实际上,您有很多错误,其中一些已被掩盖

First: 第一:

catalogename = fopen("*catalogname", "r");

Is wrong. 是错的。 I think what you want is: 我认为您想要的是:

FILE *fPtr = fopen(catalogname, "r");

Then, after that, your function's body changes quite a bit: 然后,之后,函数的主体发生了很大变化:

if (fPtr == NULL || ferror(fPtr) != 0) // if the file isn't NULL or if there is no errors with opening the file...
{
    if (fPtr != NULL) // never try to close a NULL file ...
        fclose(fPtr);

    return NULL; // best way to report an error in C - return NUL or set errno
}

else
{
     return fPtr; // return the file we just made.
}

The first warning: 第一个警告:

You are assigning FILE* (what fopen returns) to catalogname which is char [] . 您正在将FILE*fopen返回的内容)分配给catalogname名称char []

The second warning: 第二个警告:

The function returns type FILE* while you are returning an integer 0 or 1 当您返回整数01该函数返回FILE*类型

Did you want something else? 您还想要其他东西吗? Like: 喜欢:

FILE* openCatalog(char catalogname[])
{
   FILE* file = fopen (catalogname, "r");

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM