views:

412

answers:

4
FILE *out=fopen64("text.txt","w+");
unsigned int write;
char *outbuf=new char[write];
//fill outbuf
printf("%i\n",ftello64(out));
fwrite(outbuf,sizeof(char),write,out);
printf("%i\n",write);
printf("%i\n",ftello64(out));

output:

0
25755
25868

what is going on? write is set to 25755, and I tell fwrite to write that many bytes to a file, which is at the beginning, and then im at a position besides 25755?

+3  A: 

If you are on a DOSish system (say, Windows) and the file is not opened in binary mode, line-endings will be converted automatically and each "line" will add one byte.

So, specify "wb" as the mode rather than just "w" as @caf points out. It will have no effect on Unix like platforms and will do the right thing on others.

For example:

#include <stdio.h>

#define LF 0x0a

int main(void) {
    char x[] = { LF, LF };

    FILE *out = fopen("test", "w");

    printf("%d", ftell(out));
    fwrite(x, 1, sizeof(x), out);
    printf("%d", ftell(out));

    fclose(out);
    return 0;
}

With VC++:

C:\Temp> cl y.c
Microsoft (R) 32-bit C/C++ Optimizing Compiler Version 15.00.21022.08 for 80x86
Copyright (C) Microsoft Corporation.  All rights reserved.

y.c
Microsoft (R) Incremental Linker Version 9.00.21022.08
Copyright (C) Microsoft Corporation.  All rights reserved.

/out:y.exe

C:\Temp> y.exe
04

With Cygwin gcc:

/cygdrive/c/Temp $ gcc y.c -o y.exe

/cygdrive/c/Temp $ ./y.exe
02
Sinan Ünür
...and you open in binary mode by using `"wb"` instead of `"w"` in `fopen()`.
caf
Based on the OP's (slight) presence in the **[mingw]** and **[cygwin]** tags, I suspect this is the answer.
Chris Lutz
That's curious because **cygwin** setup asks which type of line endings to use (and recommends Unix style).
Sinan Ünür
@Sinan - Yes, but MinGW will probably use the native line endings, thus causing slight confusion when switching between the two environments.
Chris Lutz
"Doing the right thing on others" is not the right way to think about it. DOS/CPM and UNIX just made different decisions in their architecture. DOS decided to separate the concept of carriage return and line feed while UNIX decided to merge the concepts just in the line feed character. The fact that there is no real difference between "wb" and "w" in UNIX means that you can't make "mysterious mistakes" with respect to opening and closing files in the "wrong mode". OTOH, DOS separates the concepts of line feed and carriage return which matches up with line printer semantics.
Paul Hsieh
+1  A: 

It may depend on the mode in which you opened the file. If you open it as a text file, then \n may be written as \r\n in DOS/Windows systems. However, ftello64() probably only gives the binary file pointer, which would count in the extra \r characters written. Try clearing the outbuf[] of any \n data or try opening the out file as binary ("wb" instead of "w").

Paul Hsieh
A: 

Interesting. Works fine on Windows VC++, albeit ftello64 replaced with ftell.

John Lockwood
Can't you give an example?
Sinan Ünür
+2  A: 

The variable write is uninitialized and so the size of the array and the amount written will be essentially random.

Graeme Perrow
I suspect it's initialized in the real code and the OP is just being overly-protective of posting production code on a public website.
Chris Lutz
Yes, after re-reading the question I agree this is not likely the cause of the original problem - I think Sinan's answer is probably right. But just in case it _is_ a direct copy of the original code, I'll leave my answer here.
Graeme Perrow