compiling error

K

Kapteyn's Star

Firstly thank you so much for your detailed advices Keith! I am not able
to understand now all you say but i have saved your post for reading
later. I hope you wont mind?
There's no magic. fread() *doesn't* know that you've passed it an
integer array (and in fact you haven't; see below).

The first argument to fread() is normally the address of an array, or of
the first element of an array, which will be converted to void* (a raw
address). This tell fread() where in memory your object is, but nothing
else about it.

okay, so inside fread() the voip pointer will be typecast to unsigned
char pointer when writing read bytes into the buffer correct?
The second and third arguments are the size in bytes of each element of
your array, and the number of elements you want to read into. This
tells fread() how much data to read; it's the second and third arguments
multiplied together to yield the size in bytes of the array.

(So why not just use a single size argument? Because fread() reads
whole elements at a time. If you ask it to read 10 4-byte elements from
a file that only has 15 remaining byte, it will only set the first 3
4-byte elements of your array; it won't touch the 4th element of your
array.)

So the point of having fread() take parametres for no. and size of
elements is to tailor it to read to various types of arrays, even though
it actually writes into teh buffer through an unsigned char pointer cast?
am I confusing things here?

If I get all this right then when we need to fill an array of N elemenets
it's better to tell fread() to read N elements than 1 big read for the
entire array. This way if fread() only reads partially, then returned
value will not be 0 and we can find out how many elements have been
stored.
I see what you say. But sizeof(type) is understandable when i look at
it but sizeof expression means i have to figure out the expresson and
find out to which type it belongs.

Not necessarily; the *compiler* has to figure that out. Typically the
expression is the name of an object. You usually need the size of that
object, whatever type it happens to be. And you don't necessarily have
to know the type of the object to understand why you need its size.

some_type arr[N];
fread(arr, sizeof arr[0], N, some_file);

To know that the fread call's arguments are correct, you don't need to
know the type of arr, you just need to know that it's an N-element array
of *something*.

Okay I understand but when i am reading codes that have this statement:

ptr= (ptr*)malloc(N * sizeof(type));

I can instantly know what value the product is because i have memorised
the default sizes for int, float and so on. But with sizeof *ptr i have
to jump to ptr's declaration and then multiply the type's size with N.

But i realise that your style is auto-correcting itself to changes. taht
is better code...

Im sorry for snipping your excellent explanations for sizeof op. not
needing parenthesis except with types and return statement not needing
parenthisis also... but Pan is not allowing me to post articles with
"mostly quotes text"...

Re. operators not needing brackets doesnt the cast op. need it? Atleast
my K&R book lists (cast) is op. the precedence list on chapter 2.

Also the switch condition also doesnt need parenthesis like return?
When you have an expression of array type (such as the name of an array
object), that expression is, *in most contexts*, immmediately and
implicitly converted to a pointer to (equivalently: the address of) the
first element of the array. The only exceptions to this are: (1) when
the array expression is the operand of a "sizeof" operator (so "sizeof
arr" gives you the size of the entire array, not the size of a pointer);
(2) when the array expression is the operand of a unary "&" (so "&arr"
gives you the address of the array, not of its first element); and (3)
when the array expression is a string literal used in an initializer for
an array object. The last case is slightly obscure; it means that this:
char s[] = "hello";
initializes the array s with { 'h', 'e', 'l', 'l', 'o' '\0' }, not with
a pointer value.

I didnt realise that string constants were expressions of pointer type
except with initialising arrays when its an array type. I though string
constants only existed in the source code...
Here's an interesting point: The rules for multidimensional arrays are a
direct consequence of this. The standard needn't have mentioned
multidimensional arrays at all. They're implied by the rules for
one-dimensional arrays, and for array-to-pointer conversion. Given:

int array_2d[10][20] = { ... };
int elem = array_2d[5][6];

Figuring out how array_2d[5][6] resolves to an element of the 2d array
given the rules I've described is an interesting exercise.

I will try. Please correct me if im wrong. Here in the assignment
statement array_2d doesnt come under one of the 3 rules you gave so it is
converted to a pointer to its first element then the offset 5 is added to
it and then the offset 6 is also added to derive the value. Like:

int elem= *((array_2d + 5) + 6);

i think im going wrong here but i wrote a program to test it. here is
code and o/p seems identical for both assignments:

#include <stdio.h>

int main()
{
int array_2d[10][20];
int elem, i0, i1;

for(i0= 0; i0 < 10; ++i0)
{
for(i1= 0; i1 < 20; ++i1)
{
array_2d[i0][i1]= i0 + i1;
}
}

for(i0= 0; i0 < 10; ++i0)
{
for(i1= 0; i1 < 20; ++i1)
{
elem= array_2d[i0][i1];
printf("[%d][%d] = %d ", i0, i1, elem);
elem= *(*(array_2d + i0) + i1);
printf("%d\n", elem);
}
}
return 0;
}

../a.out
[0][0] = 0 0
[0][1] = 1 1
[0][2] = 2 2
[0][3] = 3 3
[0][4] = 4 4
[0][5] = 5 5
[0][6] = 6 6
[0][7] = 7 7
[0][8] = 8 8
[0][9] = 9 9
[0][10] = 10 10
[0][11] = 11 11
[0][12] = 12 12
[0][13] = 13 13
[0][14] = 14 14
[0][15] = 15 15
[0][16] = 16 16
[0][17] = 17 17
[0][18] = 18 18
[0][19] = 19 19
[1][0] = 1 1
[1][1] = 2 2
[1][2] = 3 3
....
[9][19] = 28 28
Another rule (which, IMHO, just causes confusion) is that in a parameter
declaration, an array declaration is really a pointer declaration. This
isn't a run-time conversion, it's a compile-time re-interpretation. So
this:

void func(int arr[]);

really *means* this:

void func(int *arr);

Okay so does

void func(int arr[][]);

mean this?

void func(int *arr[]);

im having trouble scaling my understand of 1D arrays to 2D and above... :(
An excellent resource for this kind of thing is section 6 of the
comp.lang.c FAQ, <http://www.c-faq.com>.

Thanks. I will check it out.
 
K

Kapteyn's Star

Chris Torek writes:

Sorry that i have to delete most of your text but Pan shows a warning
about "post is mostly quoted text" and aioe.org bans my IP for 24 hours.
anyone know a solution??
The main thing the separate size argument does is cause fread() to
return a count of whole objects filled in, rather than a count of bytes,
saving you the division:

n_got = fread(base_of_array, n_desired, size_of_each, stream);

vs:

n_got =
fread(base_of_array, n_desired * size_of_each, 1, stream) /
size_of_each;

These two calls do exactly the same thing, but force you to write the
multiplication and division expressions.

Thanks, i now understand the advantage of the first method. Also if fread
() fails to read n_desired*size_of_each bytes in the second call it will
return 0 and 0/size_of_each will give divide_with_zero exception. :)
 
K

Kapteyn's Star

Flash Gordon writes:

delete because aioe.org refuse post of >80% quotes.
When you have a problem you should check the comp.lang.c FAQ at
http://c-faq.com/ to see if you can find the answer. If you cannot find
the answer, or find the right question but cannot understand the answer
then ask. This will save *you* time since you won't have to wait for
someone to see and have time to reply to your question!

Thanks for your explanation Flash. I will check out c-faq.com as soone as
I can.
 
K

Kapteyn's Star

Richard said:
Kapteyn's Star said:


It's a great habit to get into. One day, they might pay you huge amounts
of money to work on a W. To work on a Wi. A W. A <cough cough cough>
WINdows system. And on that system, the difference is real and
significant. When opening binary files under Linux or Unix there is no
harm in adding the "b" (the Standard requires it to be supported), so
for the sake of one extra letter you keep yourself in good shape for
when, some day, you have to get your code to run under some other
system.

Thanks Richard. Is it true that fread() and fwrite must only be used with
binary mode files, or can we use them with text files too as long as
understood that '\n' may be converted from more than one byte?
 
K

Kapteyn's Star

Richard said:
Kapteyn's Star said:
can i also do the below to get random real numbers?

float a[5];
fread(a, sizeof a[0], 5, dev_random);

Only if you can guarantee that every bit pattern represents a valid
float value (which you can't, because they don't, on most systems).

Okay then. I come up with another solution to get real nos. from /dev/
random.

float f;
int i= fread(&i, sizeof i, 1, dev_random); for(f= 2.0; i; ++f)
{
if(i % f)
{
f= i/f;
i= 0;
}
}

is this okay? Thank you.
 
B

Ben Bacarisse

Keith Thompson writes:
int array_2d[10][20] = { ... };
int elem = array_2d[5][6];

Figuring out how array_2d[5][6] resolves to an element of the 2d array
given the rules I've described is an interesting exercise.

I will try. Please correct me if im wrong. Here in the assignment
statement array_2d doesnt come under one of the 3 rules you gave so it is
converted to a pointer to its first element then the offset 5 is added to
it and then the offset 6 is also added to derive the value. Like:

int elem= *((array_2d + 5) + 6);

Not quite. You clearly get that fact that:

array_2d[5][6] is (array_2d[5])[6]

i.e. array_2d first has [5] "applied" and then the result of that is
sub-scripted again (with 6). Applying the definition of [] in terms
if adding and de-referencing, we get:

array_2d[5] is *(array_2d + 5)
(array_2d[5])[6] is *(*(array_2d + 5) + 6)


So, what is array_2d converted to here? It is converted to pointer to
its first element. That is an array of 20 ints -- array2d consists of
10 of these 20-elements arrays one after the other. Writing this
type is messy in C and does not help with this exposition[1].

Now 5 gets added to that pointer. This arithmetic is done is units of
the size of the things being pointer to, in this case, 20-element int
arrays. Thus the result is a pointer that points at the 6th set of 20
ints.

This pointer has type "pointer to array of 20 int", so applying the *
to it results in a value whose type is "array of 20 int". Again,
because this value is not used in one of the three special situations,
it is converted to a pointer to its first element: in this case an
int.

6 gets added to this int pointer, to give a pointer to the 7th
element in the 6th sub-array of array_2d. Applying the star, gives us
a modifiable lvalue that refers to this element (i.e. array_2d[5][6]
can be used like this: 'array_2d[5][6] = 42;' as well as like this:
'return array_2d[5][6] + 1;').

[1] It is 'int (*)[20]'.
 
B

Ben Bacarisse

Keith Thompson writes:
int array_2d[10][20] = { ... };
int elem = array_2d[5][6];

Figuring out how array_2d[5][6] resolves to an element of the 2d array
given the rules I've described is an interesting exercise.

I will try. Please correct me if im wrong. Here in the assignment
statement array_2d doesnt come under one of the 3 rules you gave so it is
converted to a pointer to its first element then the offset 5 is added to
it and then the offset 6 is also added to derive the value. Like:

int elem= *((array_2d + 5) + 6);

Not quite. You clearly get the that fact that:

array_2d[5][6] is (array_2d[5])[6]

i.e. array_2d first has [5] "applied" and then the result of that is
sub-scripted again (with 6). Applying the definition of [] in terms
if adding and de-referencing, we get:

array_2d[5] is *(array_2d + 5)
(array_2d[5])[6] is *(*(array_2d + 5) + 6)


So, what is array_2d converted to here? It is converted to pointer to
its first element. That is an array of 20 ints -- array2d consists of
10 of these 20-elements arrays one after the other. Writing this
type is messy in C and does not help with this exposition[1].

Now 5 gets added to that pointer. This arithmetic is done is units of
the size of the things being pointer to, in this case, 20-element int
arrays. Thus the result is a pointer that points at the 6th set of 20
ints.

[The standard does not describe it this way (in terms of sizes). It
simply says that adding /i/ to a pointer that points into an array
makes a pointer that points to the /i/th element. I described it my
way, because when that array is an array of arrays (as we have here)
the wording gets messy.]

This new pointer (array_2d + 5) has type "pointer to array of 20 int",
so applying the * to it results in a value whose type is "array of 20
int". Again, because this value is not used in one of the three
special situations, it is converted to a pointer to its first element:
in this case an int.

6 gets added to this int pointer, to give a pointer to the 7th
element in the 6th sub-array of array_2d. Applying the star, gives us
a modifiable lvalue that refers to this element (i.e. array_2d[5][6]
can be used like this: 'array_2d[5][6] = 42;' as well as like this:
'return array_2d[5][6] + 1;').

The tricky bit that array_2d[5] has array type. The value gets
converted to a pointer to array type and the arithmetic on the pointer
moves it about from one 20-element array to the next.

[1] It is 'int (*)[20]'.
 
K

Keith Thompson

Chris Torek said:
I believe this is wrong: fread() will, in this case, overwrite one
of the four bytes making up the fourth array element.

You're right, and I was wrong.

C99 7.19.8.1p2:

The fread function reads, into the array pointed to by ptr, up to
nmemb elements whose size is specified by size, from the stream
pointed to by stream. For each object, size calls are made to the
fgetc function and the results stored, in the order read, in an
array of unsigned char exactly overlaying the object.

This sequence of fgetc calls doesn't allow for avoiding partial
elements. And at the end of the same paragraph:

If a partial element is read, its value is indeterminate.
the C Standard permits this is to allow implementations to be
"lazy".

In fact, it nearly *requires* implementations to be lazy. It's
difficult to see how an implementation that reads each record into a
separate object before copying it to the target could meet the
requirement I quoted above, though the fact that the value of a
partial element is indeterminate *might* provide an escape hatch.

[snip]

Thanks for the correction!
 
K

Keith Thompson

Kapteyn's Star said:
Firstly thank you so much for your detailed advices Keith! I am not able
to understand now all you say but i have saved your post for reading
later. I hope you wont mind?

Of course not; why would I mind? But please save Chris Torek's
response as well; he corrects a major error I made.

[...]

I'll try to come back and respond to the rest of your post.
 
K

Keith Thompson

Richard Heathfield said:
Kapteyn's Star said:

No. Firstly, the word is "cast", not "typecast". :) Secondly, as I
explained earlier, no cast is required when converting between void * and
any other object pointer type, because an automatic conversion is
supplied.

And thirdly, fread() needn't be implemented in C.

It's likely that fread() is written in C in most implementations
(though not necessarily in portable C), and that it will implicitly
convert (not cast) the void* argument to unsigned char*.

[snip]
 
B

Barry Schwarz

But Windows doesn't have a /dev/random, so you'd have to modify the code
anyway...
/dev is a UNIXism (and /dev/radnam non portable at all), so it should be
safe to drop the b.

While /dev/random may have a special meaning for Unix, Windows has no
problem creating a folder named /dev and placing a file in it called
random. fopen is quite willing to take '/' as path separators. This
code worked fine on Windows XP SP3 Visual C 6.0.


#include <stdio.h>
#include <stdlib.h>

int main(void)
{
FILE *out = fopen("/dev/random", "w");
if (out==NULL)
{
puts("fopen failed");
exit(EXIT_FAILURE);
}
fputs("Hello World\n",out);
fclose(out);
return 0;
}




Remove del for email
 
V

vippstar

While /dev/random may have a special meaning for Unix, Windows has no
problem creating a folder named /dev and placing a file in it called
random. fopen is quite willing to take '/' as path separators. This
code worked fine on Windows XP SP3 Visual C 6.0.
FILE *out = fopen("/dev/random", "w");
<snip rest>

Of course the code worked, "/dev/random" is a perfectly valid string
to pass to fopen. There are two possible outcomes, fopen will return a
pointer or NULL. That's for any OS, hosted implementation, etc.
 
S

santosh

<snip rest>

Of course the code worked, "/dev/random" is a perfectly valid string
to pass to fopen. There are two possible outcomes, fopen will return a
pointer or NULL. That's for any OS, hosted implementation, etc.

<OT>

Under Windows won't you need to pass fopen "C:/dev/random" or "C
\\dev\\random" rather than "/dev/random"?

</OT>
 
L

lawrence.jones

santosh said:
Under Windows won't you need to pass fopen "C:/dev/random" or "C
\\dev\\random" rather than "/dev/random"?

No. Only the command processors insist on backslashes, the OS itself
accepts either.
 
S

santosh

rio said:
Chris Torek said:
so if i have
/* n_got = fread(base_of_array, n_desired, size_of_each, stream);*/
fread(b, 2, 1024*1024*10, sf);

why the implementation can not save the partial risults in the array
"b"? so if error why there is the need of preserve the array "b"?

No, storing a "partial result" is what fread does and what Chris Torek
said.
yes i read the book, fread is fundamentally buggy

No it's not. It works as per it's specification.
1) it not return the error that it find

"The error". There could be a number of *different* errors but fread, as
per it's definition, indicates only that there was some error. For more
control you can use feof or ferror after a call to fread, but that
still may not actually tell you *why* the read failed. Systems vary so
much that it's not practical for the Committee to specify separate
error codes for all possible errors. Your implementation might also set
errno to a useful value, though that's not required by the Standard. If
you want detailed diagnostics then use a platform specific read
function like POSIX open and Win32 ReadFile etc. For example open under
Linux/glibc can store upto 19 different error codes in errno upon
failure.
2) it return the number of obj and not the number of chars readed

You can calculate the latter from the former as Chris demonstrated.
 
S

santosh

rio said:
if fread not read all the last object than it has to reput the
fractional part of the last object in the stream

It cannot do this because the Standard does not guarantee a pushback of
more than one character.

<snip>

fread is specified as returning only a partial read if enough bytes are
not available, in which case bytes beyond the last completely read
object are left in an "indeterminate" state. Though the Standard
doesn't guarantee this, I think you will find that the partially read
bytes are indeed left in the buffer you supply to fread. No pushback is
done on the stream, because not all systems can guarantee sufficient
memory for such a pushback.

If you need such an ability you can always wrap the Standard functions
with your own I/O routines.
 
K

Kapteyn's Star

Richard said:
Kapteyn's Star said:
Richard said:
Kapteyn's Star said:
can i also do the below to get random real numbers?

float a[5];
fread(a, sizeof a[0], 5, dev_random);

Only if you can guarantee that every bit pattern represents a valid
float value (which you can't, because they don't, on most systems).

Okay then. I come up with another solution to get real nos. from
/dev/ random.

float f;
int i= fread(&i, sizeof i, 1, dev_random); for(f= 2.0; i; ++f)
{
if(i % f)
{
f= i/f;
i= 0;
}
}

is this okay? Thank you.

Well, you obviously didn't try it. Here is your technique, dressed up
as a full program:

#include <stdio.h>

float getrndfloat(FILE *dev_random)
{
float f;
int i= fread(&i, sizeof i, 1, dev_random);
for(f= 2.0; i; ++f)
{
if(i % f)
{
f= i/f;
i= 0;
}
}
return f;
}
int main(void)
{
FILE *fp = fopen("/dev/random", "rb");
if(fp != NULL)
{
float r = getrndfloat(fp);
printf("%f\n", r);
fclose(fp);
}
return 0;
}

foo.c: In function `getrndfloat':
foo.c:9: invalid operands to binary %

The modulo operator requires integer operands.

Will casting 'f' to int be okay? I only need whole number values so
truncation of the fraction part is all right.
But there's nothing to stop you reading, say, an unsigned long int
from your bit source, and dividing it by (ULONG_MAX + 1.0) - that
would give you a randomISH double in the range [0.0, 1.0)

I tried this and it works.

#include <stdio.h>

int main()
{
FILE *f= fopen("/dev/random", "rb");
unsigned long val= 0;
double fval= 0.0;

if(!f)
{
return 1;
}
if(0 == fread(&val, sizeof val, 1, f))
{
return 1;
}
if(val)
{
fval= val / ((unsigned long)-1 + 1.0);
printf("%lu\t%f\n", val, fval);
}
return 0;
}
 
K

Kapteyn's Star

Keith said:
Richard Heathfield said:
Kapteyn's Star said: [...]
can i also do the below to get random real numbers?

float a[5];
fread(a, sizeof a[0], 5, dev_random);

Only if you can guarantee that every bit pattern represents a valid
float value (which you can't, because they don't, on most systems).
is this also the same as?

fread(a, sizeof a, 1, dev_random);

Yes, and unfortunately it's equally broken. You're okay to do this
with ints, but not with floating point.

Strictly speaking, it's not safe with ints either. Integer types
(other than the character types), just like floating-point types, are
allowed to have trap representations. They're just less likely to do
so; on most systems, and quite possibly on all systems that have
/dev/random, all possible bit patterns represent valid and distinct
integer values.

To be safe, read data from /dev/random as a stream of unsigned char
values, and construct an integer value from the bytes (say, by
shifting and or'ing).

Thansk Keith. But i haven't studied bit operators yet. I will implement
your method when i have done so.
 
K

Kapteyn's Star

Ben said:
Keith Thompson writes:
int array_2d[10][20] = { ... };
int elem = array_2d[5][6];

Figuring out how array_2d[5][6] resolves to an element of the 2d
array given the rules I've described is an interesting exercise.

I will try. Please correct me if im wrong. Here in the assignment
statement array_2d doesnt come under one of the 3 rules you gave so
it is converted to a pointer to its first element then the offset 5
is added to it and then the offset 6 is also added to derive the
value. Like:

int elem= *((array_2d + 5) + 6);

Not quite. You clearly get the that fact that:

array_2d[5][6] is (array_2d[5])[6]

i.e. array_2d first has [5] "applied" and then the result of that is
sub-scripted again (with 6). Applying the definition of [] in terms
if adding and de-referencing, we get:

array_2d[5] is *(array_2d + 5)
(array_2d[5])[6] is *(*(array_2d + 5) + 6)


So, what is array_2d converted to here? It is converted to pointer to
its first element. That is an array of 20 ints

Im sorry if i don't understand but do you mean 200 ints when you say 20
above?
-- array2d consists of
10 of these 20-elements arrays one after the other.

okay, so in declaration:

int a[2][3];

the elements are so formatted in memory in ascending address from left
to right in page??

+===================+===================+
|+-----+-----+-----+|+-----+-----+-----+|
|| 0,0 | 0,1 | 0,2 ||| 1,0 | 1,1 | 1,2 ||
|+-----+-----+-----+|+-----+-----+-----+|
+=======================================+
Writing this
type is messy in C and does not help with this exposition[1].

As per your note[1] then *(array_2d + 5) is of type int (*)[20]?
Then what is type of array_2d + 5?
Now 5 gets added to that pointer. This arithmetic is done is units of
the size of the things being pointer to, in this case, 20-element int
arrays. Thus the result is a pointer that points at the 6th set of 20
ints.

[The standard does not describe it this way (in terms of sizes). It
simply says that adding /i/ to a pointer that points into an array
makes a pointer that points to the /i/th element. I described it my
way, because when that array is an array of arrays (as we have here)
the wording gets messy.]

This new pointer (array_2d + 5) has type "pointer to array of 20 int",
so applying the * to it results in a value whose type is "array of 20
int". Again, because this value is not used in one of the three
special situations, it is converted to a pointer to its first element:
in this case an int.

6 gets added to this int pointer, to give a pointer to the 7th
element in the 6th sub-array of array_2d. Applying the star, gives us
a modifiable lvalue that refers to this element (i.e. array_2d[5][6]
can be used like this: 'array_2d[5][6] = 42;' as well as like this:
'return array_2d[5][6] + 1;').

The tricky bit that array_2d[5] has array type. The value gets
converted to a pointer to array type and the arithmetic on the pointer
moves it about from one 20-element array to the next.

okay then what is the type of *(array_2d + 5) + 6? I hink it is int*?
Also what is type of just array_2d? is it int (*)[10][20]?
[1] It is 'int (*)[20]'.

Thank you very much Ben. Im not able to easily understand 2D arrays like
1D ones, but i'll keep reading your notes until i figure it.
 

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

Similar Threads


Members online

Forum statistics

Threads
474,145
Messages
2,570,827
Members
47,373
Latest member
Desiree036

Latest Threads

Top