Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > C Programming > compiling error

Reply
Thread Tools

compiling error

 
 
Kapteyn's Star
Guest
Posts: n/a
 
      07-16-2008
Keith Thompson writes:

> Kapteyn's Star <remove_digits_for_email_7Kapteyns3.Star@g0m8ai2l. 9com>
> writes: [...]
>> One small question. If fread() takes a void pointer then how does it
>> know that what I actually pass in an integer array? Will it figure it
>> out from the sizeof argument or is some magic going on??


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.


--
Kapteyn's Star
 
Reply With Quote
 
 
 
 
Kapteyn's Star
Guest
Posts: n/a
 
      07-16-2008
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.


--
Kapteyn's Star
 
Reply With Quote
 
 
 
 
Kapteyn's Star
Guest
Posts: n/a
 
      07-16-2008
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.


--
Kapteyn's Star
 
Reply With Quote
 
Kapteyn's Star
Guest
Posts: n/a
 
      07-16-2008
Richard Heathfield writes:

> Kapteyn's Star said:
>
>> Ben Bacarisse writes:
>>
>>> Kapteyn's Star <remove_digits_for_email_7Kapteyns3.Star@g0m8ai2l. 9com>
>>> writes:
>>> <snip>


>> I read in books that in Linux/UNIX there is no difference in text and
>> binary formats... that was why i left out the b. So i take it that b
>> must always be used??

>
> 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?


--
Kapteyn's Star
 
Reply With Quote
 
Kapteyn's Star
Guest
Posts: n/a
 
      07-16-2008
Richard Heathfield writes:

> 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.


--
Kapteyn's Star
 
Reply With Quote
 
Ben Bacarisse
Guest
Posts: n/a
 
      07-16-2008
Kapteyn's Star <remove_digits_for_email_7Kapteyns3.Star@g0m8ai2l. 9com>
writes:

> Keith Thompson writes:

<snip>
>> 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]'.

--
Ben.
 
Reply With Quote
 
Ben Bacarisse
Guest
Posts: n/a
 
      07-16-2008
Kapteyn's Star <remove_digits_for_email_7Kapteyns3.Star@g0m8ai2l. 9com>
writes:

> Keith Thompson writes:

<snip>
>> 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]'.

--
Ben.
 
Reply With Quote
 
Keith Thompson
Guest
Posts: n/a
 
      07-16-2008
Chris Torek <> writes:
> In article <>
> Keith Thompson <kst-> wrote:
>>(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.)

>
> 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!

--
Keith Thompson (The_Other_Keith) kst- <http://www.ghoti.net/~kst>
Nokia
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"
 
Reply With Quote
 
Keith Thompson
Guest
Posts: n/a
 
      07-16-2008
Kapteyn's Star <remove_digits_for_email_7Kapteyns3.Star@g0m8ai2l. 9com> writes:
> Keith Thompson writes:
>> Kapteyn's Star <remove_digits_for_email_7Kapteyns3.Star@g0m8ai2l. 9com>
>> writes: [...]
>>> One small question. If fread() takes a void pointer then how does it
>>> know that what I actually pass in an integer array? Will it figure it
>>> out from the sizeof argument or is some magic going on??

>
> 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.

--
Keith Thompson (The_Other_Keith) kst- <http://www.ghoti.net/~kst>
Nokia
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"
 
Reply With Quote
 
Keith Thompson
Guest
Posts: n/a
 
      07-16-2008
Richard Heathfield <> writes:
> Kapteyn's Star said:
>> Keith Thompson writes:

> <snip>
>>>
>>> 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?

>
> 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]

--
Keith Thompson (The_Other_Keith) kst- <http://www.ghoti.net/~kst>
Nokia
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"
 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
Re: Cross-compiling error when compiling 2.6.1... Garrett Cooper Python 0 02-24-2009 09:47 PM
Cross-compiling error when compiling 2.6.1... Garrett Cooper Python 0 02-24-2009 08:55 PM
Problems with ld: Unresolved error C++ compiling error stevenruiz@gmail.com C++ 2 02-13-2007 09:04 PM
Problem with C++ Compiling Error ld: Unresolved Error stevenruiz@gmail.com C++ 2 02-13-2007 12:01 AM
Compiling when libedit is in path Is there a trick to compiling Ruby when libedit must exist in the search path? Can you statically link to readline 5.0 in some manner? -- Lon Baker Lon Baker Ruby 1 03-21-2005 08:57 AM



Advertisments
 



1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57