简体   繁体   English

回到C中的main时,为什么传递给函数的FILE指针改变了?

[英]Why FILE pointer after being passed to a function changes when back in main in C?

As far as I understand passing a pointer to a function essentially passes the copy of the pointer to the function in C. I have a FILE pointer that I pass to a function func() , func() reads a line from a file and then when we return to main() . 据我了解,将指针传递给函数实际上是将指针的副本传递给C中的函数。我有一个FILE指针,该指针传递给函数func()func()从文件中读取一行,然后当我们返回main() I read another line from the file using the same FILE pointer. 我使用相同的FILE指针从文件中读取了另一行。

However, while I would imagine that I'd read the line exactly from before func() was called, I actually read the next line after what func() had read. 但是,虽然我可以想象我是从func()之前完全读取了该行,但实际上我是在读取func()之后读取了下一行。 Can you please explain why FILE pointer behaves this way? 您能解释一下为什么FILE指针如此行为吗?

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

#include <stdio.h>

#define STR_LEN 22

void func(FILE *fd);

int main() {
    FILE *fd;
    char mainString[STR_LEN];
    if (!(fd = fopen("inpuFile", "r"))) {
        printf("Couldn't open file\n");
        fprintf(stderr, "Couldn't open file\n");
    }

    func(fd);
    fgets(mainString, STR_LEN, fd);
    printf("mainString = %s\n", mainString);

    fclose(fd);

    return 0;
}

void func(FILE *fd) {
    char funcString[STR_LEN];
    fgets(funcString,STR_LEN, fd);
    printf("funcString = %s\n", funcString);
}

However, while I would imagine that I'd read the line exactly from before func was called ... 但是,虽然我想我会在调用func之前准确地读过该行……

I can't imagine why you would imagine that. 我无法想象你为什么会那样想。 What if the FILE* references a network connection that has no replay capability at all where reading is consumption. 如果FILE*引用的网络连接根本没有重播功能,那该怎么办呢? Where would the line be stored such that you could read it again? 该行将存储在哪里,以便您可以再次阅读? There would be absolutely no place to put it. 绝对没有地方放它。

Not only would I not imagine that, it's kind of crazy. 不仅不敢想象,而且有点疯狂。

As far as I understand passing a pointer to a function essentially passes the copy of the pointer to the function in C. 据我了解,将指针传递给函数实际上是将指针的副本传递给C语言中的函数。

Correct. 正确。 But a copy of a pointer points to the very same object. 但是指针的副本指向同一对象。 If I point to a car and you copy me, you're pointing to the very same one and only car that I'm pointing to. 如果我指的是一辆车,而您抄袭了我,则是指我所指向的同一辆也是唯一一辆车。

Because FILE pointer points on some data that gets changed when the file is read/written. 因为FILE指针指向一些在读取/写入文件时更改的数据。

So the pointer doesn't change (still points to the handler structure of the file) but the data pointed by the structure does. 因此,指针不会改变(仍然指向文件的处理程序结构),但是结构所指向的数据会改变。

Try passing pointer as const FILE * you'll see that you cannot because fread operation (and others) alter the pointed data. 尝试将指针作为const FILE *传递const FILE *您将看到您无法执行此操作,因为fread操作(及其他操作)会更改指向的数据。

One way would be to duplicate the file descriptor, which dup does, but doesn't work on buffered FILE object, only raw file descriptors. 一种方法是复制文件描述符,而dup可以复制文件描述符,但不适用于缓冲的FILE对象,而仅适用于原始文件描述符。

The problem is in your initial statement: As far as I understand passing a pointer to a function essentially passes the copy of the pointer to the function in C . 问题出在您的初始声明中: As far as I understand passing a pointer to a function essentially passes the copy of the pointer to the function in C

This does not change much, as whatever you are accessing as a pointer, still holds the location of the FILE you are accessing, the whole point of using pointers as arguments for a function in C, is so that you can modify a certain value outside the scope of a function. 这并没有太大变化,因为无论您作为指针访问什么,仍然保留您正在访问的FILE的位置,使用指针作为C中函数的参数的全部目的是,以便您可以在外部修改某个值功能范围。

For example, common usage of an integer pointer as a function argument: 例如,整数指针作为函数参数的常见用法:

void DoSomethingCool(int *error);

Now using this code to catch the error would work like this: 现在使用此代码捕获错误将像这样工作:

int error = 0;
DoSomethingCool(&error);

if(error != 0)
  printf("Something really bad happened!");

In other words, the pointer will actually modify the integer error, by accessing it's location and writing to it. 换句话说,指针实际上将通过访问它的位置并写入它来修改整数错误。

An important thing to keep in mind to avoid these kinds of misunderstandings is to recognize that all a pointer is, is essentially the address of something. 要避免这些误解要记住的重要事情是认识到所有指针实际上就是某物的地址。

So you could (in theory, by simplifying everything a lot) think of an int * as simply an int , the value of which happens to be an address of some variable, for a FILE * , you can think of it as an int , where the value of the int is the location of the FILE variable. 因此,您可以(从理论上讲,通过简化很多事情)将int *视为简单的int ,其值恰好是某个变量的地址,对于FILE * ,您可以将其视为int ,其中,int的值是FILE变量的位置。

FILE *fd is a pointer only in the sense that its implementation uses C construct called a "pointer". FILE *fd仅在其实现使用称为“指针”的C构造的意义上是指针。 It is not a pointer in the sense of representing a file position. 不是表示文件位置的指针。

FILE *fd represents a handle to a file object inside the I/O library, a struct that includes the actual position of the file. FILE *fd表示I / O库中文件对象的句柄 ,该struct包括文件的实际位置。 In a grossly simplified way, you can think of fd as a C pointer to a file pointer. 以非常简化的方式,您可以将fd视为指向文件指针的C指针。

When you pass fd around your program, I/O routines make modifications to the file position. 在程序中传递fd ,I / O例程会修改文件位置。 This position is shared among all users of fd . 此位置由fd所有用户共享。 If a func() makes a change to that position by reading some data or by calling fseek , all users of the same fd will see the updated position. 如果func()通过读取一些数据或调用fseek更改该位置,则同一fd所有用户都将看到更新后的位置。

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

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