struct and pointer question

B

Bill Cunningham

In fread/fwrite the first parameter takes a pointer to a void. The
generic pointer. I wrote a struct that would insert the in file name and out
file name through fopen. My struct looks like this.

struct param {
char *infile;
char *outfile;
void *buf;
};
In the function I wrote that takes struct param as a type I don't know how
to chose a type in the struct for void *. I have:

fread(p.buf,1,sizeof p.buf,p.infile);

Is there no way to change a return type as declared in a struct's elements ?
The elements are all of type struct param now.
Should I just leave the void * variable out of the struct and declare it
as a type char * or int * or size_t * whatever I want later as I need it?

Is this clear?

Bill
 
B

Ben Bacarisse

Bill Cunningham said:
In fread/fwrite the first parameter takes a pointer to a void. The
generic pointer. I wrote a struct that would insert the in file name and out
file name through fopen. My struct looks like this.

struct param {
char *infile;
char *outfile;
void *buf;
};
In the function I wrote that takes struct param as a type I don't know how
to chose a type in the struct for void *. I have:

fread(p.buf,1,sizeof p.buf,p.infile);

You probably want buf to be array, not a pointer. This might be what
you mean by the fact that you " don't know how to chose a type in the
struct for void *". I suspect that means you don't know what type buf
should have.

If you don't want an array in the struct then the fread call is probably
wrong. The count argument should be the number of characters that you
want to read (size of p.buf is a small number like 4 or 8 -- it's the
size of a pointer).
Is there no way to change a return type as declared in a struct's
elements ?

I don't know what this means. Functions have a return type, but a
struct's elements just has a type.
The elements are all of type struct param now.

That does not make sense. Two are of type char * and one is of type
void *.
Should I just leave the void * variable out of the struct and declare it
as a type char * or int * or size_t * whatever I want later as I need
it?

It's impossible to tell because you give no context. What is this
struct for? It may be fine as it is of it could be all wrong. Without
context is just three bit of data collected together for no apparent
reason.
Is this clear?

Not without more context.
 
B

Bill Cunningham

Ben said:
You probably want buf to be array, not a pointer. This might be what
you mean by the fact that you " don't know how to chose a type in the
struct for void *". I suspect that means you don't know what type buf
should have.

If you don't want an array in the struct then the fread call is
probably wrong. The count argument should be the number of
characters that you want to read (size of p.buf is a small number
like 4 or 8 -- it's the size of a pointer).


I don't know what this means. Functions have a return type, but a
struct's elements just has a type.


That does not make sense. Two are of type char * and one is of type
void *.


It's impossible to tell because you give no context. What is this
struct for? It may be fine as it is of it could be all wrong.
Without context is just three bit of data collected together for no
apparent reason.


Not without more context.

I suspect the author of fread and fwrite used the generic pointer type
for a reason. So you could change array types like for example char
buf[200]; or int buf [1000]; I usually use a size_t as the array type. But
putting the type void * in the prototype gives flexibility normally. But
what about in the struct? Do I need to change the type to int * or size_t *
for the array type. I don't know how to change it later to a int * or char *
..

Make Sense? If not I'll post some code.

Bill
 
B

Barry Schwarz

Ben said:
You probably want buf to be array, not a pointer. This might be what
you mean by the fact that you " don't know how to chose a type in the
struct for void *". I suspect that means you don't know what type buf
should have.

If you don't want an array in the struct then the fread call is
probably wrong. The count argument should be the number of
characters that you want to read (size of p.buf is a small number
like 4 or 8 -- it's the size of a pointer).


I don't know what this means. Functions have a return type, but a
struct's elements just has a type.


That does not make sense. Two are of type char * and one is of type
void *.


It's impossible to tell because you give no context. What is this
struct for? It may be fine as it is of it could be all wrong.
Without context is just three bit of data collected together for no
apparent reason.


Not without more context.

I suspect the author of fread and fwrite used the generic pointer type
for a reason. So you could change array types like for example char
buf[200]; or int buf [1000]; I usually use a size_t as the array type. But
putting the type void * in the prototype gives flexibility normally. But
what about in the struct? Do I need to change the type to int * or size_t *
for the array type. I don't know how to change it later to a int * or char *

You have allowed the presence of the structure to completely obscure
whatever the real topic of your question is. Your real question seems
to be how to use fread and fwrite. Both functions require four pieces
of information:

1 - The address of a buffer. fread will store data obtained from
the stream in this buffer. fwrite will copy the data from the buffer
to the stream. No matter what type of address you provide, it will be
converted to a void* if it has a different type. If you define the
buffer as an array and use the array name as the argument, then you
don't have to worry about the type since the array name will be
automatically converted to the address of the first element with the
correct type. If you dynamically allocate the buffer or otherwise
designate its address in a pointer, then you would use the pointer as
the argument. While neither fread nor fwrite care about the pointer
type, when you attempt to access the elements of the buffer, it is
your responsibility to make sure that the pointer is of the correct
type.

2 - The size of a single unit of data in the buffer. One
possibility would be sizeof(int) if the buffer contains objects of
type int.

3 - The number of objects to be transferred to or from the
buffer.

4 - The address of a FILE object usually obtained from fopen().
Neither fread nor fwrite take the file name as an argument as you
coded in your original post.
Make Sense? If not I'll post some code.

Since you tend to post code that has nothing to do with your question,
you should include a verbal description of what it you intend to
accomplish.
 
N

Nick Keighley

    In fread/fwrite the first parameter takes a pointer to a void. The
generic pointer. I wrote a struct that would insert the in file name and out
file name through fopen.

what does "through fopen" mean?

My struct looks like this.

struct param {
    char *infile;
    char *outfile;
    void *buf;};

looks ok
In the function I wrote that takes struct param as a type

you mean "as a parameter" or "as an argument"
I don't know how
to chose a type in the struct for void *.

I've no idea what this means. void* IS a type.
I have:

   fread(p.buf,1,sizeof p.buf,p.infile);

ok. But make sure buf is pointing to something. Where do you think
fread(0 is going to put the data it reads?
Is there no way to change a return type as declared in a struct's elements ?

no idea what this means. A structs elements do not declare a "return
type"
The elements are all of type struct param now.

what elements? The elements in struct param are certainly not of type
struct param
    Should I just leave the void * variable out of the struct and declare it
as a type char * or int * or size_t * whatever I want later as I need it?

no idea
    Is this clear?

you're kidding, right?
 
B

Barry Schwarz

what does "through fopen" mean?



looks ok


you mean "as a parameter" or "as an argument"


I've no idea what this means. void* IS a type.


ok. But make sure buf is pointing to something. Where do you think
fread(0 is going to put the data it reads?

I wonder what fread will do with a char* when it is expecting a FILE*
as the fourth argument.
 
B

Bill Cunningham

Barry said:
I wonder what fread will do with a char* when it is expecting a FILE*
as the fourth argument.

I didn't notice that error. It's not in my code either. I don't seem to
be making myself clear. I will post some code later when I get the time. If
that doesn't work I'll go from there.

Bill
 
A

Angel

In fread/fwrite the first parameter takes a pointer to a void. The
generic pointer. I wrote a struct that would insert the in file name and out
file name through fopen. My struct looks like this.

struct param {
char *infile;
char *outfile;
void *buf;
};
In the function I wrote that takes struct param as a type I don't know how
to chose a type in the struct for void *. I have:

fread(p.buf,1,sizeof p.buf,p.infile);

Is there no way to change a return type as declared in a struct's elements ?
The elements are all of type struct param now.
Should I just leave the void * variable out of the struct and declare it
as a type char * or int * or size_t * whatever I want later as I need it?

Is this clear?

It's pretty clear that you have no idea what you're talking about or
what you are doing, yes. You've asked about fread() and fwrite()
several times now and you still don't seem to understand what these
functions do. (As well as generic confusion about structures,
functions, and return values.)

fread() reads objects from a stream into memory. fwrite() writes
objects from memory into a stream. In both cases, it is your job to
provide the following information to the function:
1. The location in memory to read from or write to.
2. The size of one single object, in bytes.
3. The number of objects to be read or written.
4. The stream to read from or write to.

The first argument of fread() and fwrite() is of type void* because
these functions can be used to read or write any kind of object, hence
you can pass any type of pointer to it. It's your duty to pass a
pointer that matches with your needs. (If you are reading char objects,
use a pointer to char. If you're writing structures, pass a pointer to
a structure.)

Here is a very simple example of a program that writes some structures
to a file:


#include <stdio.h>

struct Person
{
char name[20];
unsigned int age;
};

int main(void)
{
struct Person people[] = { { "John", 34u },
{ "Dick", 48u },
{ "Harry", 25u } };

FILE *file = fopen("people.db", "wb");
fwrite(people, sizeof (people[0]), 3, file);
fclose(file);
}
 
B

Bill Cunningham

Barry said:
I wonder what fread will do with a char* when it is expecting a FILE*
as the fourth argument.

#include <stdio.h>

struct param {
char *infile;
char *outfile;
void *buf;
};

#include "p.h"

int copi(struct param p)
{
size_t nread, nwrite;
FILE *in, *out;
if ((in = fopen(p.infile, "rb")) == NULL) {
perror("fopen 1");
return 1;
}
if ((out = fopen(p.outfile, "wb")) == NULL) {
perror("fopen 2");
return 2;
}
do {
nread = fread(p.buf, 1, sizeof p.buf, in);
nwrite = fwrite(p.buf, 1, nread, out);
}
while (!feof(in));
fclose(in);
fclose(out);
printf("%zu %zu\n", nread, nwrite);
return 0;
}

My question concerns the generic pointer in the struct. It's the prototype
for fread/fwrite in my copi function but what if I wanted a int * or char *
how would I choose that in a file calling main? Say I want buf to be a
size_t for example.

Bill
 
B

Bill Cunningham

Angel said:
It's pretty clear that you have no idea what you're talking about or
what you are doing, yes. You've asked about fread() and fwrite()
several times now and you still don't seem to understand what these
functions do.

[snip]

I write successful code with fread and fwrite all the time.

Bill
 
B

Ben Bacarisse

Bill Cunningham said:
#include <stdio.h>

struct param {
char *infile;
char *outfile;
void *buf;
};

#include "p.h"

I wonder what's in here?
int copi(struct param p)
{
size_t nread, nwrite;
FILE *in, *out;
if ((in = fopen(p.infile, "rb")) == NULL) {
perror("fopen 1");
return 1;
}
if ((out = fopen(p.outfile, "wb")) == NULL) {
perror("fopen 2");
return 2;
}
do {
nread = fread(p.buf, 1, sizeof p.buf, in);

That size if wrong. The code may well work, but that's not a sensible
size to use.
nwrite = fwrite(p.buf, 1, nread, out);
}
while (!feof(in));
fclose(in);
fclose(out);
printf("%zu %zu\n", nread, nwrite);
return 0;
}

My question concerns the generic pointer in the struct. It's the prototype
for fread/fwrite in my copi function but what if I wanted a int * or char *
how would I choose that in a file calling main? Say I want buf to be a
size_t for example.

I read this about a dozen times and finally I think I worked it out.
The trouble is that you ask how do so what you think is needed when
that's not what's needed at all.

I think you want a function that can read int one time and chars the
next. Other times you might want it to read size_ts or even something
else like doubles. To do that, you don't change the type of the buffer,
you change the size of the data being read. But (and it's a big but)
this only works if the data you are reading is in the right format.
You've posted questions about reading various file formats in the past
so I can't tell if reading the data using fread is appropriate or not.

Of course, at some point you need the data to be in a C object of the
right type. You might read one or more ints using fread into a generic
buffer, but you need to process them as ints. That may be, ultimately
what you are asking, but the answer to how you do that is not
substantially different to the answer to the question "how do I write a
program?".
 
B

Barry Schwarz

I didn't notice that error. It's not in my code either. I don't seem to
be making myself clear. I will post some code later when I get the time. If
that doesn't work I'll go from there.

You change your code at random so we have no idea what is in it now
but it certainly was in the code you originally posted as shown below:
 
B

Barry Schwarz

Angel said:
It's pretty clear that you have no idea what you're talking about or
what you are doing, yes. You've asked about fread() and fwrite()
several times now and you still don't seem to understand what these
functions do.

[snip]

I write successful code with fread and fwrite all the time.

Strange that you never post any of this successful code when asking a
question. Or did I miss the smiley?
 
B

Barry Schwarz

On Fri, 14 Sep 2012 17:29:00 -0400, "Bill Cunningham"

snip unrelated quotes from previous messages
#include <stdio.h>

struct param {
char *infile;
char *outfile;
void *buf;
};

#include "p.h"

int copi(struct param p)
{
size_t nread, nwrite;
FILE *in, *out;
if ((in = fopen(p.infile, "rb")) == NULL) {
perror("fopen 1");
return 1;
}
if ((out = fopen(p.outfile, "wb")) == NULL) {
perror("fopen 2");
return 2;
}
do {
nread = fread(p.buf, 1, sizeof p.buf, in);

p.buf is a pointer, not an array. This code will cause the input data
to be placed in the memory where p.buf points to. Unfortunately, it
will read only sizeof(void*) bytes (usually 4 or 8). Your third
argument should evaluate to the size of the area that p.buf points to.
nwrite = fwrite(p.buf, 1, nread, out);

At some point, you should confirm that fread was successful. Depending
on where the out stream resides, checking fwrite may also make sense.
}
while (!feof(in));

This loop will never end if there is an error reading from in.
fclose(in);
fclose(out);
printf("%zu %zu\n", nread, nwrite);

Of what significance is the amount of data processed by the last read
and write? Why do you print only the results of the last iteration
through the while loop?
return 0;
}

My question concerns the generic pointer in the struct. It's the prototype
for fread/fwrite in my copi function but what if I wanted a int * or char *

You should not have, and you didn't show, a prototype for fread or
fwrite in your function. The prototype should always be obtained by
including the stdio.h standard header.
how would I choose that in a file calling main? Say I want buf to be a

What do you mean when you say a file is "calling main"? Only a
function can call a function. The only exception is the initial call
to main which is performed by the startup code.

One more time - no matter what type of object pointer you code as the
first argument in your call to fread, fread WILL ALWAYS RECEIVE A
void*. When fread transfers the data to your buffer, it takes no
notice of the type of data. It doesn't know and doesn't care about
types. It is simply transferring bytes. The same is true for fwrite.

If you attempt to access the data with something other than fwrite,
then the type becomes important. Go back and read my comments on this
in my 9/13 11:26PM post.

If you have an array x (of any type such as int or char), then in the
calling program you can simply assign the address of the array to
p.buf with the statement
p.buf = x;
Then when you call fread, the data will be placed in the array. IT IS
YOUR JOB to insure that the array x is the correct type for the data
that is in the file. You do not need a separate int* or char*.
size_t for example.

Make up your mind. Do you want buf to be an object that holds the
data being read or a pointer to an area that will hold the data? Right
now, buf is a pointer and can point to any object you would like. If
you want buf to actually hold the data, then first you change the type
of buf from void* to the correct data type (size_t in this case) and
then you pass fread the address of this object with
nread = fread(&p.buf, 1, sizeof p.buf, in);
 
A

Angel

Angel said:
It's pretty clear that you have no idea what you're talking about or
what you are doing, yes. You've asked about fread() and fwrite()
several times now and you still don't seem to understand what these
functions do.

[snip]

I write successful code with fread and fwrite all the time.

Given your utter confusion about basic concepts just about every time
you post here, I strongly doubt that. Last time you asked about them
you didn't even know what their return code meant.

But maybe I am mistaken. Try posting some actual code next time you ask
a question, instead of some half-baked lines that wouldn't even compile.
 
K

Kaz Kylheku

It's pretty clear that you have no idea what you're talking about or

That has been clear for pretty much the entire decade since Cunningham
started posting to comp.lang.c. Someone posting under the name "Bill
Cunningham:" evidently first appeared on July 4, 2002.

Assuming it is even the same person posting under that name, the passage
of ten years leaves him yet grappling with the same beginner issues.

Some people who have university degrees now and working as developers
were elementary school kids in 2002.

The idiot regulars in this newsgroup keep responding to Cunningham, like
predictable drones. (You know what they say about endlessly repeating the same
action, expecting different results.)
 
B

Bill Cunningham

Ben said:
I wonder what's in here?

The above.
That size if wrong. The code may well work, but that's not a sensible
size to use.
OK


I read this about a dozen times and finally I think I worked it out.
The trouble is that you ask how do so what you think is needed when
that's not what's needed at all.

I think you want a function that can read int one time and chars the
next. Other times you might want it to read size_ts or even something
else like doubles.

Yes! Yes! I hoped I could cross the usenet understanding barrier. This post
is not directly related to the fread fwrite functions I just happened to use
them so I can get used to them. Personally I like fgetc and fputc.

To do that, you don't change the type of the
buffer, you change the size of the data being read. But (and it's a
big but) this only works if the data you are reading is in the right
format. You've posted questions about reading various file formats in
the past so I can't tell if reading the data using fread is
appropriate or not.

I've been reading binary data. Jpeg format.
Of course, at some point you need the data to be in a C object of the
right type. You might read one or more ints using fread into a
generic buffer, but you need to process them as ints. That may be,
ultimately what you are asking, but the answer to how you do that is
not substantially different to the answer to the question "how do I
write a program?".

True.

Bill
 
B

Bill Cunningham

Angel said:
It's pretty clear that you have no idea what you're talking about or
what you are doing, yes. You've asked about fread() and fwrite()
several times now and you still don't seem to understand what these
functions do. (As well as generic confusion about structures,
functions, and return values.)

fread() reads objects from a stream into memory. fwrite() writes
objects from memory into a stream. In both cases, it is your job to
provide the following information to the function:
1. The location in memory to read from or write to.
2. The size of one single object, in bytes.
3. The number of objects to be read or written.
4. The stream to read from or write to.

The first argument of fread() and fwrite() is of type void* because
these functions can be used to read or write any kind of object, hence
you can pass any type of pointer to it. It's your duty to pass a
pointer that matches with your needs. (If you are reading char
objects, use a pointer to char. If you're writing structures, pass a
pointer to a structure.)

Here is a very simple example of a program that writes some structures
to a file:


#include <stdio.h>

struct Person
{
char name[20];
unsigned int age;
};

int main(void)
{
struct Person people[] = { { "John", 34u },
{ "Dick", 48u },
{ "Harry", 25u } };

FILE *file = fopen("people.db", "wb");
fwrite(people, sizeof (people[0]), 3, file);
fclose(file);
}

This thread has nothing to do with fread or fwrite.

Bill
 
A

Angel

Bill explained long ago that he had a mental illness. It's not possible to
tell if he's really a troll. Mental illness is a pretty good cover story.
And 10+ years would make for an extraordinarily long troll, even if by
multiple persons.

If people want to spend their time answering his questions, so be it. It's
not skin off your back.

As trolls go, he's fairly benign. His questions are at least on topic,
and even if he doesn't learn from the answers he's given, others might.
As far as I can tell he has yet to throw a tantrum, and his posting
volume is fairly low. I'd wish more trolls were like him.
 
B

Bill Cunningham

Ben said:
I read this about a dozen times and finally I think I worked it out.
The trouble is that you ask how do so what you think is needed when
that's not what's needed at all.

I think you want a function that can read int one time and chars the
next. Other times you might want it to read size_ts or even something
else like doubles. To do that, you don't change the type of the
buffer, you change the size of the data being read.
[snip]

Problem solved. Thanks Much.

Bill
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,992
Messages
2,570,220
Members
46,807
Latest member
ryef

Latest Threads

Top