23790


以下のようなコードを書きます。  
`char *n1,*n2;`のようにポインタを独立したものと定義すればそれぞれの値に応じて文字を取得できますが、`FILE *fp1,
*fp2;`は独立していますが、fgetcを呼ぶたびにポインタが更新されています。

[code]

    int main(int argc, char** argv){
        FILE *fp;
        fp = fopen("main.text", "w");
        char nn[]="mainworld";
        fputs(nn, fp);
        fclose(fp);
        fp = NULL;
    
        FILE *fp1, *fp2;
        char *n1,*n2;
        fp = fopen("main.text", "r"); //ファイルへのポインタを代入
        n1=nn;//文字列へのポインタを代入
    
        //コピー
        fp2 = fp;
        n2=n1;
        while (1) {//それぞれに対して一文字ずつ取り出す操作
    
            printf("%c%c",*(n1++), (char) fgetc(fp));
            if (feof(fp))break;
            printf("%c%c",*(n2++), (char) fgetc(fp2));
            if (feof(fp2))break;
        }
        return 0;
    }
    
[/code]

EOFを出力していますが気にしないでください。仕様です。

もっとわかりやすいコードでは、ファイルの時のものとメモリ内の文字列の時とに分け２つのコードと実行結果の比較がわかりやすいかと思います。なので
`printf("%c,%c",*(n1++),*(n2++));`と`printf("%c%c", (char) fgetc(fp), (char)
fgetc(fp2));//この書き方あまり良くなかったかも`の２つの時比べてもらえるとわかりやすいです。


CC BY-SA 3.0
2016-04-06T04:59:29.643
23785
2016-04-06T14:52:32.483
2016-04-06T05:04:58.113
10455
10455
question
c
なぜFILEポインターはコピーできないのですか？


FILEポインタはコピーできていますし、  
fgetc()を読んでもポインタは更新されないですよ。  
以下で確認できると思います。

[code]

    int main(int argc, char** argv){
      FILE *fp1, *fp2;
      fp2 = fp1 = fopen("main.text", "r");
    
      printf("%p, %p\n\n", fp1, fp2);
      while (feof(fp1)==0) {
        printf("%c", fgetc(fp1));
        printf("\t%c", fgetc(fp2));
        printf("\t%p\t%p\n", fp1, fp2);
      }
      return 0;
    }
    
[/code]

自分のところだとこんな風に出ました。

[code]

    $ ./a.out 
    0x1cb4010, 0x1cb4010
    
    m   a   0x1cb4010   0x1cb4010
    i   n   0x1cb4010   0x1cb4010
    w   o   0x1cb4010   0x1cb4010
    r   l   0x1cb4010   0x1cb4010
    d   
        0x1cb4010   0x1cb4010
    �   �   0x1cb4010   0x1cb4010
    
[/code]

ずっと 0x1cb4010 のままです。

疑問に思っているのは、  
`fgetc(fp1)` と `fgetc(fp2)` を続けて実行すれば、  
両方 `mmaaiinn` と、同じ文字が2回続けて出るハズじゃないか?  
という事ですか?


CC BY-SA 3.0
2016-04-06T05:55:22.417
23787
2016-04-06T05:55:22.417
15007
23785
answer


用語に対する理解に混乱があるので話が通じていないというか

用語 [ポインタ] 何かの変数があるとき、その変数を指すもの  
文言 [ポインタは更新される] だと既に [c](/questions/tagged/c "'c' のタグが付いた質問を表示")
[c++](/questions/tagged/c%2b%2b "'c++' のタグが付いた質問を表示") に親しんでいるユーザは

[code]

    char a[10];
    char* p=&a[0];
    ++p; // これがポインタの更新
    
[/code]

のようなコードを真っ先に思い浮かべます。  
しかしながら `fgetc` `fputc` 等をしても `FILE*` の更新はありません。

用語 [ファイル位置表示子] ファイルに対して入出力するとき、どこに行われるか

> fgetcを呼ぶたびにポインタが更新されています。

ここで言う「ポインタ」は、実際にはファイル位置表示子のことではないですか？  
ファイル位置表示子は入出力があるたびに更新されていきます。

* * *

`FILE* fp1;` があるということは、どこかにその実体である変数実体 `FILE f1;` があるわけです。

[code]

    FILE* fopen(中略) { /* f1 に対して何か処理 */ return &f1; }
    
[/code]

であると考えてください。すると `fopen` の行は

[code]

    FILE* fp1=&f1;
    
[/code]

と考えることができます。そして

[code]

    FILE* fp2=fp1;
    
[/code]

であるなら、この `fp1` `fp2` は同一変数 `f1` を指し示すようになるだけです。

[code]

    FILE* fp1=&f1;
    FILE* fp2=&f1;
    
[/code]

と書いてあるのと同じことです。  
`fp1` `fp2` のどちらを使っても、ライブラリ関数は `f1` に対して操作を行うことになります。  
よって同じファイルに入出力されるのは当たり前です。


CC BY-SA 3.0
2016-04-06T06:29:48.487
23788
2016-04-06T06:29:48.487
8589
23785
answer

[code]

    FILE *fp, *fp1;
    fp = fopen("main.text", "r");
    fp1 = fp;
    
[/code]

とすると、

[code]

    +---+
    |fp | -------+      +----------+
    +---+        |      |          |
                 +----->| FILE     |
    +---+        |      |          |
    |fp1| -------+      +----------+
    +---+
    
[/code]

という状況になります。  
FILEにはバッファやファイル位置などの情報が含まれています。  
fgetc(fp)は上記のFILEに対する操作で、fgetc(fp1)もやはり上記のFILEに対する操作です。  
fgetc(fp)もfgetc(fp1)も同じFILEに対する操作になります。

同じFILEに対する操作ではなくそれぞれ独立した操作にしたいのであれば、

[code]

    FILE *fp, *fp1;
    fp = fopen("main.text", "r");
    fp1 = fopen("main.text", "r");
    
[/code]

とすれば

[code]

                        +----------+
    +---+               |          |
    |fp | ------------->| FILE     |
    +---+               |          |
                        +----------+
                        +----------+
    +---+               |          |
    |fp1| ------------->| FILE     |
    +---+               |          |
                        +----------+
    
[/code]

となって、  
fgetc(fp)とfgetc(fp1)はそれぞれ独立したFILEに対する操作になります。


CC BY-SA 3.0
2016-04-06T07:11:56.647
23790
2016-04-06T07:11:56.647
7844
23785
answer


前のよりこっちの方が分かり易い気がしたので  
追加で書きます。  
元のも残しておきますが

↓は、元のプログラムに printf を2行追加しただけです。

[code]

    #include <stdio.h>
    int main(int argc, char** argv){
      FILE *fp;
      fp = fopen("main.text", "w");
      char nn[]="mainworld";
      fputs(nn, fp);
      fclose(fp);
      fp = NULL;
    
      FILE *fp1, *fp2;
      char *n1,*n2;
      fp = fopen("main.text", "r"); //ファイルへのポインタを代入
      n1=nn;//文字列へのポインタを代入
    
      //コピー
      fp2 = fp;
      n2=n1;
      while (1) {//それぞれに対して一文字ずつ取り出す操作
    
        printf("%c%c",*(n1++), (char) fgetc(fp));
        printf("\n%p\t%p\t%p\t%p\n", n1, n2, fp, fp2);
        if (feof(fp))break;
        printf("%c%c",*(n2++), (char) fgetc(fp2));
        printf("\n%p\t%p\t%p\t%p\n\n", n1, n2, fp, fp2);
        if (feof(fp2))break;
      }
      return 0;
    }
    
[/code]

こんな風に、何かポインタの操作をする度に  
printf の %p でポインタを見ていけば、  
何が起っているか、自分でも追えるんじゃないかなと思います。

自分のところだとこんな結果でした

[code]

    $ ./a.out 
    mm
    0x7ffd21f329d1  0x7ffd21f329d0  0x2341010   0x2341010
    ma
    0x7ffd21f329d1  0x7ffd21f329d1  0x2341010   0x2341010
    
    ai
    0x7ffd21f329d2  0x7ffd21f329d1  0x2341010   0x2341010
    an
    0x7ffd21f329d2  0x7ffd21f329d2  0x2341010   0x2341010
    
    iw
    0x7ffd21f329d3  0x7ffd21f329d2  0x2341010   0x2341010
    io
    0x7ffd21f329d3  0x7ffd21f329d3  0x2341010   0x2341010
    
    nr
    0x7ffd21f329d4  0x7ffd21f329d3  0x2341010   0x2341010
    nl
    0x7ffd21f329d4  0x7ffd21f329d4  0x2341010   0x2341010
    
    wd
    0x7ffd21f329d5  0x7ffd21f329d4  0x2341010   0x2341010
    w�
    0x7ffd21f329d5  0x7ffd21f329d5  0x2341010   0x2341010
    
[/code]

あと多分、引っかかっている部分は、FILEポインタに限らなくて、  
ポインタ全般についての事なんじゃないかと思います。

↓は、FILEポインタじゃなくて charのポインタですが、同じ様な状況かなと思います。

[code]

    #include <stdio.h>
    
    int fgetc_no_kawari(char *cp) {
      (*cp)++;
      return *cp;
    }
    
    int main(void) {
      char x = 'a';
      char *cp1, *cp2;
      int i;
    
      cp1 = &x;  /* fopen("main.text", "r"); の代り */
      cp2 = cp1; /* charのポインタをコピー */
    
      for (i=0; i<10; i++) {
        /* ↓ fgetc_no_kawari で x を書換えている */
        printf("%c", (char) fgetc_no_kawari(cp1));
    
        /* ↓ こっちも fgetc_no_kawari で x を書換えている */
        printf("%c", (char) fgetc_no_kawari(cp2));
    
        /* 念のため x を確認してみる */
        printf("%c", x);
    
        putchar('\n');
      }
      return 0;
    }
    
[/code]

結果はこんな感じです

[code]

    $ ./a.out 
    bcc
    dee
    fgg
    hii
    jkk
    lmm
    noo
    pqq
    rss
    tuu
    
[/code]


CC BY-SA 3.0
2016-04-06T14:52:32.483
23797
2016-04-06T14:52:32.483
15007
23785
answer