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-15-2008
Hi newsgroup

The program here given is refused by GCC with a error i cannot
understand. It says
rnd00.c: In function ‘main’:
rnd00.c:26: error: expected expression before ‘]’ token

How to make it compile? I also tried buf[10] but that gives "segmentation
fault". Thanks in advanced.

/* scanf 10 random integers from /dev/random */
#include <stdio.h>

void open_file(FILE *f)
{
f= fopen("/dev/random", "r");
}

void read_values(FILE *f, int buf[], int count)
{
do
{
--count;
fread((void*)&buf[count], sizeof(int), 1, f);
}
while(count > 0);
}

int main()
{
int buf[10];
int count= 10;
FILE *f;

open_file(f);
read_values(f, buf[], count);
do
{
--count;
printf("%d ", buf[count]);
}
while(count > 0);
return 0;
}


--
Kapteyn's Star
 
Reply With Quote
 
 
 
 
Ben Bacarisse
Guest
Posts: n/a
 
      07-15-2008
Kapteyn's Star <remove_digits_for_email_7Kapteyns3.Star@g0m8ai2l. 9com>
writes:
<snip>
> void open_file(FILE *f)
> {
> f= fopen("/dev/random", "r");
> }


In addition to the other comments, that should be "rb".

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

> Kapteyn's Star said:
>
>> Hi newsgroup
>>
>> The program here given is refused by GCC with a error i cannot
>> understand. It says
>> rnd00.c: In function ?main?:
>> rnd00.c:26: error: expected expression before ?]? token
>>
>> How to make it compile? I also tried buf[10] but that gives
>> "segmentation fault". Thanks in advanced.
>>
>> /* scanf 10 random integers from /dev/random */ #include <stdio.h>
>>
>> void open_file(FILE *f)
>> {
>> f= fopen("/dev/random", "r");

>
> This won't do what you think. If you want a function to change the value
> of an object, you must pass to that function the address of the object.
> Alternatively, you can get the function to return the new value of the
> object, and pick it up in the caller, as shown:
>
> FILE *open_file()
> {
> return fopen("/dev/random", "r");
> }
>
> usage: fp = open_file();
>
> If you want to do it the parameter way, you need to do this:
>
> void open_file(FILE **f)
> {
> *f = fopen("/dev/random", "r");
> }
>
> Usage: open_file(&fp);


oops I forget constantly that C does pass by value for functions, curse
of having learned Pascal in school

> Remember that fopen will return a null pointer if it fails to open the
> file.


Okay. I ommited checking fopen() because /dev/random exists here. But i
see your point, it might be absent under older kernels.

>> }
>>
>> void read_values(FILE *f, int buf[], int count) {
>> do
>> {
>> --count;
>> fread((void*)&buf[count], sizeof(int), 1, f);

>
> Simpler:
> fread(&buf[count], sizeof buf[count], 1, f);


I thought that a typecast is needed when converting between different
typed pointers...

> or even
> fread(buf + count, sizeof buf[count], 1, f);


This is neat! I still not getting the hang of pointer arithmetics.
But sizeof without parenthesis just feels weird. I thought it wont
compile but it does! So much to learn in c...

> <snip>
>
>> int main()
>> {
>> int buf[10];
>> int count= 10;
>> FILE *f;
>>
>> open_file(f);
>> read_values(f, buf[], count);

>
> This should be: read_values(f, buf, count);


Okay arrays when passed to function should not have the index but the
index is needed when in the prototype? Noted.

Thanx to you and Ben... program works now!

--
Kapteyn's Star
 
Reply With Quote
 
Kapteyn's Star
Guest
Posts: n/a
 
      07-15-2008
Ben Bacarisse writes:

> Kapteyn's Star <remove_digits_for_email_7Kapteyns3.Star@g0m8ai2l. 9com>
> writes:
> <snip>
>> void open_file(FILE *f)
>> {
>> f= fopen("/dev/random", "r");
>> }

>
> In addition to the other comments, that should be "rb".


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?? Thanx Ben.

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

> Kapteyn's Star said:
>
>> Richard Heathfield writes:
>>
>>> Kapteyn's Star said:
>>>
>>>> }
>>>>
>>>> void read_values(FILE *f, int buf[], int count) {
>>>> do
>>>> {
>>>> --count;
>>>> fread((void*)&buf[count], sizeof(int), 1, f);
>>>
>>> Simpler:
>>> fread(&buf[count], sizeof buf[count], 1, f);

>>
>> I thought that a typecast is needed when converting between different
>> typed pointers...

>
> If you need a cast, the chances are good that the conversion isn't
> appropriate anyway. In this case, fread takes void * for the first arg,
> and the language guarantees that a conversion will be provided between
> void * and any object-pointer type, in either direction, so you don't
> need the cast at all.


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

> If you specify a type - sizeof(int) - you need the parentheses, but
> specifying a type is almost always the Wrong Thing. Types can change.
> Using sizeof on an expression is far better, because if/when you change
> the type, you don't have to worry about the sizeof because it will
> already "know", so to speak. If you did sizeof(int), however, and later
> switched to, say, double, you'd have had to change the sizeof to
> sizeof(double) - a maintenance task that is easily overlooked by
> mistake.


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.

> You can't pass an array to a function. But when you try, what actually
> happens is that C interprets the array name as if it were a pointer to
> the first element of the array. This is because C is pass-by-value, and
> arrays don't have values as such. In practice, it's exactly what you
> want, most of the time, so no harm done.


I think i can understand... so arrays are not copied on the stack when we
give them as args to a function but a pointer to it is passed instead. So
given:

int arr[5];
func(arr);

in func() *arr is the same as arr[0] and &arr == &arr[0]?

>> should not have the index but the
>> index is needed when in the prototype? Noted.

>
> Yes, the type decoration for arrays is required in the declaration,
> whether it's a function declaration or object declaration or whatever.
> (Of course, in a function declaration it isn't really an array - T foo[]
> is understood by the compiler to mean T *foo, which is a little
> confusing in my opinion, but that's C for you.)


which usage is better in function declarations T *arr or T arr[]? but
there is no difference in actual functions right? That is, everything I
can do with func(T arr[]); can be done with func(T *arr); also??

> But in usage, you just need the name of the object, plus any operators
> that you want to apply to that object. Note that, sometimes, you do want
> the [] operator, e.g. if you are accessing a value in the array, you
> need to know which value you are accessing: as in...
>
> printf("%d\n", buf[count]);
>
> Note that this is precisely equivalent to:
>
> printf("%d\n", *(buf + count));
>
> A relatively obscure equivalence, but it should bring home to you that
> buf doesn't need to have a [] constantly nailed to its behind.


Okay I think im getting the hang of all this. six months back I tried to
learn C from Teach Yourself C in 24 hours but it was too boring Now I
have got The C Programming Language which was highly recommanded in this
group...the problems are very interesting but some are tough also!

Thanks for your response.

--
Kapteyn's Star
 
Reply With Quote
 
Kapteyn's Star
Guest
Posts: n/a
 
      07-15-2008
A small thing confuses me. man urandom says

When read, the /dev/random device will only return random bytes...

So is it correct of me to read from /dev/random int values? Or i should
have read instaed of 10 int 40 char values and then cast them to 10 ints??

can i also do the below to get random real numbers?

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

is this also the same as?

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

are these all okay?

thanks for any help.


--
Kapteyn's Star
 
Reply With Quote
 
Keith Thompson
Guest
Posts: n/a
 
      07-15-2008
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??


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.

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

And of course the fourth specifies the stream you want to read from.

>> If you specify a type - sizeof(int) - you need the parentheses, but
>> specifying a type is almost always the Wrong Thing. Types can change.
>> Using sizeof on an expression is far better, because if/when you change
>> the type, you don't have to worry about the sizeof because it will
>> already "know", so to speak. If you did sizeof(int), however, and later
>> switched to, say, double, you'd have had to change the sizeof to
>> sizeof(double) - a maintenance task that is easily overlooked by
>> mistake.

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

And as for "sizeof" without parentheses looking funny, think of it
this way. "sizeof" is an operator, not a function. It happens to be
the only operator in C whose symbol is a keyword (which looks like an
identifier, which looks like it could be a function name) rather than
one or more punctuation marks. Operators don't require parentheses on
their operands (you can write -x, you don't have to write -(x)). The
sizeof operator is no different; you can write sizeof x; you don't
have to write sizeof(x). Though you can add parentheses if you like,
and in some cases it might be necessary for disambiguation.

It's similar in this way to the return statement. You can write
"return x;" rather than "return(x);", because "return" isn't a
function. (It's not an operator either; it's a special form of
statement.) You can write "return(x);" if you really want to, but the
parentheses are just part of an ordinary parenthesized expression, not
part of the syntax of the return statement.

*But* there's another form of the "sizeof" operator, one whose operand
is a type name rather than an expression. This form of "sizeof" is
what's weird and exceptional. The type name is enclosed in
parentheses, but the parentheses aren't the same as the parentheses
you see on a function call; they're specified by an entirely different
syntax rule. And they're necessary to avoid ambiguity. You can think
of ``sizeof ( type-name )'' as a special distinct form of expression
-- and one that you really don't need to use very often. (The use of
parentheses on a cast is a similar case of surrounding a type name
used in an expression with parentheses to avoid ambiguity.)

>> You can't pass an array to a function. But when you try, what actually
>> happens is that C interprets the array name as if it were a pointer to
>> the first element of the array. This is because C is pass-by-value, and
>> arrays don't have values as such. In practice, it's exactly what you
>> want, most of the time, so no harm done.

>
> I think i can understand... so arrays are not copied on the stack when we
> give them as args to a function but a pointer to it is passed instead.


Almost, but not quite. I think it's time to bring out (drum roll)
The Rule.

You *can't* give an array as an argument to a function. You can try,
but it's just not possible in C. (Well, you can wrap the array in a
struct and pass the struct, but we'll ignore that; you can't do it
directly.)

Let's forget about functions, parameters, and arguments for a moment,
and just talk about arrays and pointers.

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.

So, when you call a function like:

> given:
>
> int arr[5];
> func(arr);


the expression "arr" is of array type, and its context isn't one of
the three exceptions, so it's implicitly converted to the address of
arr[0], of type int*. This conversion has nothing to do with the fact
that it's a function argument; the same thing would happen in any
context other than the Big Three.

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.

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);

The "[]" form can be used to document the fact that you expect to be
passing (the address of the first element of) an array to the
function. But I prefer the "*" form, since it says what it really
means.

An excellent resource for this kind of thing is section 6 of the
comp.lang.c FAQ, <http://www.c-faq.com>.

> in func() *arr is the same as arr[0] and &arr == &arr[0]?


Assuming func's parameter was declared as "int *arr" or "int arr[]",
then yes, *arr is the same as arr[0]. But &arr and &arr[0] are not
the same thing. Remember that, inside func, arr is a pointer object
(a parameter); &arr is the address of that pointer object. &arr[0];
is the address of the first (zeroth?) element of the array to whose
first element arr points.

arr == &arr[0] is correct, though.

And remember that the address of an array and the address of its first
element are two different things. They both refer to the same
location in memory, but they're of different types.

[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
 
Harald van Dijk
Guest
Posts: n/a
 
      07-15-2008
On Tue, 15 Jul 2008 10:01:53 -0700, Keith Thompson wrote:
> You *can't* give an array as an argument to a function. You can try,
> but it's just not possible in C.


Are you allowed to pass an array rvalue to a variadic function in C90?
 
Reply With Quote
 
Keith Thompson
Guest
Posts: n/a
 
      07-15-2008
Harald van Dijk <> writes:
> On Tue, 15 Jul 2008 10:01:53 -0700, Keith Thompson wrote:
>> You *can't* give an array as an argument to a function. You can try,
>> but it's just not possible in C.

>
> Are you allowed to pass an array rvalue to a variadic function in C90?


No, it's still converted to a pointer value.

--
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
 
Harald van Dijk
Guest
Posts: n/a
 
      07-15-2008
On Tue, 15 Jul 2008 10:28:29 -0700, Keith Thompson wrote:
> Harald van Dijk <> writes:
>> On Tue, 15 Jul 2008 10:01:53 -0700, Keith Thompson wrote:
>>> You *can't* give an array as an argument to a function. You can try,
>>> but it's just not possible in C.

>>
>> Are you allowed to pass an array rvalue to a variadic function in C90?

>
> No, it's still converted to a pointer value.


As far as I was aware, array rvalues are never converted to pointers in
C90, and that conversion is one of the changes C99 made. If you say that
the conversion does exist in C90, could you also say in what other
contexts it can be performed?
 
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