From: Joe.M on
Hi, all,

I want to use fwrite() to just write plain text file. Can I do this
with fwrite? My code such like the following:

int main(int argc, const char* argv[])
{
FILE *f;
const char c[] = "hello world!";
int count;
int err;

f = fopen("/home/joem/wrk/t", "a");
if (!f)
{
err = errno;
fprintf(stderr, strerror(err));
exit(EXIT_FAILURE);
}

count = fwrite(c, sizeof(c)/sizeof(char), strlen(c), f);
if (!count)
{
err = errno;
fclose(f);

fprintf(stderr, strerror(err);
exit(EXIT_FAILURE);
}
}

fclose(f);
exit(EXIT_SUCCESS);
}

But I get some binary data at the tail of "hello world!", WHY?

Another: I use ubuntu 8.04 desktop environment, and gcc v4.2.3

Thanks.
From: viza on
On Thu, 26 Jun 2008 21:41:16 -0700, Joe.M wrote:

> I want to use fwrite() to just write plain text file. Can I do this with
> fwrite?

Yes, as long as you use a fixed size character set, (us-ascii,
iso-8859-?, utf16 etc) it's more difficult with a variable length one
(utf8 etc).

> const char c[] = "hello world!";

> count = fwrite(c, sizeof(c)/sizeof(char), strlen(c), f);

> But I get some binary data at the tail of "hello world!", WHY?

The second argument to fwrite is the size of *one* element, not the total.

Also, there's no real need for the const above. Either use:
char c[] = "hello world!";
or
const char *c = "hello world!";

The former is an automatic array that you can write to, the latter is a
pointer to an array somewhere that you can't write. What you have above
is an automatic array that you tell the compiler that you don't want to
write to. This will make many compilers copy the data for nothing. It's
not wrong, just potentially inefficient.

HTH
viza
From: Joe.M on
On Jun 27, 3:13 pm, viza <tom.v...(a)gmil.com> wrote:
> On Thu, 26 Jun 2008 21:41:16 -0700, Joe.M wrote:
> > I want to use fwrite() to just write plain text file. Can I do this with
> > fwrite?
>
> Yes, as long as you use a fixed size character set, (us-ascii,
> iso-8859-?, utf16 etc) it's more difficult with a variable length one
> (utf8 etc).
>
> >         const char c[] = "hello world!";
> >         count = fwrite(c, sizeof(c)/sizeof(char), strlen(c), f);
> > But I get some binary data at the tail of "hello world!", WHY?
>
> The second argument to fwrite is the size of *one* element, not the total..
>
> Also, there's no real need for the const above.  Either use:
>   char c[] = "hello world!";
> or
>   const char *c = "hello world!";
>
> The former is an automatic array that you can write to, the latter is a
> pointer to an array somewhere that you can't write.  What you have above
> is an automatic array that you tell the compiler that you don't want to
> write to.  This will make many compilers copy the data for nothing.  It's
> not wrong, just potentially inefficient.
>
> HTH
> viza

Hi, viza,

I'm sorry, I want to reply to you on this group, but I send my post to
your directly by email.

Thank you for your help.

And I'm confused with const char *c = "hello world!" -- is a pointer
to an array somewhere that you can't write
"somewhere can't be write" is be restricted at compile-time or run-
time? and by whom?

Joe.M
From: Ian Collins on
Joe.M wrote:
>
> And I'm confused with const char *c = "hello world!" -- is a pointer
> to an array somewhere that you can't write
> "somewhere can't be write" is be restricted at compile-time or run-
> time? and by whom?
>
'const'

A string literal is a const char*. You can't change the data pointed to
by a pointer to const char.

--
Ian Collins.
From: Jens Thoms Toerring on
Joe.M <cholyjoe(a)gmail.com> wrote:
> And I'm confused with const char *c = "hello world!" -- is a pointer
> to an array somewhere that you can't write
> "somewhere can't be write" is be restricted at compile-time or run-
> time? and by whom?

When you have

char *c = "Hello world!";

the thing on the right hand side is called a "string literal".
It's set up by the compiler for you so that 'c' can point to
it. But the compiler/linker can put it into memory that you
are not allowed to change, so you shouldn't try to (on some
systems you may get away with it, on other it would result in
a segmentation fault). This allows the compiler to use the
same string if you next define another pointer

char *d = "world!";

In that case 'd' could point into the same string literal.
If you now could change it via the 'c' pointer suddenly
also what 'd' is pointing to would change behind your back!

That's also the reason why 'c' is often defined as a const
char pointer since 'c' is pointing here to a constand string,
i.e. a string that can't be changed.

On the other hand, if you have

char c[ ] = "hello world!";

you've got something rather different. In this case 'c' is
an array of chars that gets initialized with the string on
the right hand side. It's actually "syntactic sugar" since
you could also write that as

char c[ ] = { 'h', 'e', 'l', 'l', 'o', ' ',
'w', 'o', 'r', 'l', 'd', '!', '\0' };

i.e. using the normal notation for initializing arrays. And
since 'c' is now a normal array you can change its elements,
i.e. the string stored in there, whenever you want,

Regards, Jens
--
\ Jens Thoms Toerring ___ jt(a)toerring.de
\__________________________ http://toerring.de