[comp.lang.c] Difference between fseek

a3@earth.rivm.nl (Adri Verhoef) (04/27/91)

I thought "rewind(fp)" was the same as "fseek(fp, 0L, 0)",
but it is not, as I will show in the program below.

The program can be compiled in several ways:
1.  cc		rewind_fseek.c
2.  cc -DFSEEK  	rewind_fseek.c
3.  cc -DFSEEK -DUPDATE=\"w+\"	rewind_fseek.c

In case 2, the result of running a.out is:
	[1] First string
	[2] First string

In any other case, the result will be:
	[1] First string
	[2] Second string

The difference in compiling is clear: with -DFSEEK, "fseek" is used;
in any other case "rewind" is used.

before running a.out, make sure that "small_file" exists, 
as opening a file with type "r+" does not create the file for you.
# ============= rewind_fseek.c ==============
sed 's/^X//' << 'SHAR_EOF' > 'rewind_fseek.c' &&
X#include <stdio.h>
X
X#define SMALL_FILE	"small_file"
Xchar *	string[2] = { "First string\n", "Second string\n" };
X
X#ifndef UPDATE
X#define	UPDATE	"r+"
X#endif
X
Xmain()
X{
X	FILE *	Cfpwr = fopen(SMALL_FILE, UPDATE);
X	FILE *	Cfprd = fopen(SMALL_FILE, "r");
X	char	buf[BUFSIZ];
X	int	i;
X
X	if (Cfprd == NULL || Cfpwr == NULL) (void) perror(SMALL_FILE);
X	else
X
X	for (i=0; i<2; i++) {
X		rewind(Cfpwr);
X		(void) fprintf(Cfpwr, string[i]);
X		(void) fflush(Cfpwr);
X#ifdef FSEEK
X		(void) fseek(Cfprd, 0L, 0);	/* There is a difference  */
X#else /* REWIND */				/* between defining FSEEK */
X		rewind(Cfprd);			/* and defining REWIND.   */
X#endif /* REWIND */
X		if (fgets(buf, BUFSIZ, Cfprd) == NULL) {
X			(void) perror("fgets");
X			continue;
X		}
X		(void) printf("[%d] %s", i+1, buf);
X	}
X	return 0;
X}
SHAR_EOF
true || echo 'restore of rewind_fseek.c failed'
touch small_file
exit 0

Note that "small_file" must exist, when using "r+" for updating a file.

In the manual it is stated, that:
  When a file is opened for update, both input and output may be
  done on the resulting _s_t_r_e_a_m.  However, output may not be
  directly followed by input without an intervening _f_s_e_e_k or
  _r_e_w_i_n_d, and input may not be directly followed by output without
  an intervening _f_s_e_e_k, _r_e_w_i_n_d, or an input operation which
  encounters end-of-file.

This is not the case in the program above, because two different file
pointers to the same file are being used; but why the odd behaviour, i.e.

	Why is there a difference between using fseek and rewind, or
	rather, why does rewind(x) do what fseek(x, 0L, 0) doesn't ?
	[As shown above.]

As a side note, if I define UPDATE to be "w+", everything works.
(But I don't want to truncate the file in my application.)

I have tried this on Ultrix 4.1 and on SunOS 4.1 with the same result.
--
Adri (a3@rivm.nl) - Postmaster, NewsAdmin, SysAdmin, you name it...