Velocity Reviews

Velocity Reviews (http://www.velocityreviews.com/forums/index.php)
-   C Programming (http://www.velocityreviews.com/forums/f42-c-programming.html)
-   -   Inconsistent (http://www.velocityreviews.com/forums/t440581-inconsistent.html)

jimbo 12-17-2005 08:11 PM

Inconsistent
 
Could someone comment on this code please.

1. Are the comments in it correct?

2. Why does sizeof(arr) not work consistently in C? In someFunction()
sizeof(arr) means sizeof(&arr[0]) in main. The compiler knows how big arr
is, so why the difference - esp. as it would be v.useful if sizeof(arr)
worked in someFunction as it does in main - so you could use sizeof(arr) in
the conditional bit of,say, a for loop in someFunction for example?

3. Why doesn't C allow testFunction to be declared char [] testFunction -
seems to me that if it did you could get away with knowing less about
pointers, and it seems as though again that C is incosistent, i.e., you
don't have to declare testFunction's parameter as char *. Surely, the
compiler should know that char [] someFunction actually means char *
someFunction??

char * testFunction(char []);

int main(void)
{
/* Lie to the compiler. Should be ok though as the compiler knows how
big the array really is.*/
char arr[7] = "0123456789";

/* Ouput the sizeof the array. And the size of a pointer to it. */
printf("main() sizeof arr = %d\n", sizeof(arr));
printf("main() sizeof arr = %d\n", sizeof(&arr[0]));

/* Pass it on to the function where we'll do some other emaningless
things.*/
testFunction(arr);
return 0;
}


/* Can't declare testFunction as char [] testF...() - even though the
compiler knows that array's are passed by address.*/

/* The size is ignored - and can't be checked anyway.*/
char * testFunction(char arr[500])
{
int n;

/* Same sizeof line of code that was in main() - note here that it
output the size of a pointer!*/
printf("sizeof arr = %d\n", sizeof(arr));

return arr;
}



Flash Gordon 12-17-2005 09:07 PM

Re: Inconsistent
 
jimbo wrote:
> Could someone comment on this code please.
>
> 1. Are the comments in it correct?
>
> 2. Why does sizeof(arr) not work consistently in C?


It *does* work consistently.

> In someFunction()
> sizeof(arr) means sizeof(&arr[0]) in main.


This is the problem, you haven't understood that you don't actually pass
the array (C is not Pascal) what you pass is a pointer to the first
element of the array. This is a FAQ, see
http://www.eskimo.com/~scs/C-faq/q6.21.html and
http://www.eskimo.com/~scs/C-faq/q6.21.html

> The compiler knows how big arr
> is, so why the difference - esp. as it would be v.useful if sizeof(arr)
> worked in someFunction as it does in main - so you could use sizeof(arr) in
> the conditional bit of,say, a for loop in someFunction for example?


It can't know in general, because you might write the function in one
translation unit and the, 25 years later, write another translation unit
that calls the first passing it an array of a different size.

> 3. Why doesn't C allow testFunction to be declared char [] testFunction -


Because that is the way it is defined.

> seems to me that if it did you could get away with knowing less about
> pointers,


For good or ill programming in C really requires an understanding of
pointers, because for the vast majority of non-trivial problems you will
end up using them.

> and it seems as though again that C is incosistent, i.e., you
> don't have to declare testFunction's parameter as char *. Surely, the
> compiler should know that char [] someFunction actually means char *
> someFunction??


If both were valid they would mean different things. One would mean
returning an array, which C does not allow, whilst the other does mean
returning a pointer to char.

> char * testFunction(char []);
>
> int main(void)
> {
> /* Lie to the compiler. Should be ok though as the compiler knows how
> big the array really is.*/
> char arr[7] = "0123456789";


Never lie to the compiler. It *will* get its revenge one day, possibly
by causing your application to fail miserable in front of a massive
potential customer causing your company not to get the contract it was
relying on, with the result of you being sacked for incompetence. In
this case I believe it is a constraint violation, because the standard says:
| No initializer shall attempt to provide a value for an object not
| contained within the entity being initialized.
So the compiler is *required* to complain at you, and if the compiler
chooses to produce an executable after complaining the program is
allowed to do anything at all since it is *not* a valid C program.

> /* Ouput the sizeof the array. And the size of a pointer to it. */
> printf("main() sizeof arr = %d\n", sizeof(arr));


If you are going to use printf you should include stdio.h because
varidac functions *require* a prototype to be in scope when you call
them or you invoke undefined behaviour and the program is allowed to do
anything at all. (you can provide a prototype manually, but that would
be a very stupid thing to do).

> printf("main() sizeof arr = %d\n", sizeof(&arr[0]));
>
> /* Pass it on to the function where we'll do some other emaningless
> things.*/
> testFunction(arr);
> return 0;
> }
>
>
> /* Can't declare testFunction as char [] testF...() - even though the
> compiler knows that array's are passed by address.*/


No, this is wrong. Arrays are not passed at all, a pointer to the first
element is passed.

> /* The size is ignored - and can't be checked anyway.*/
> char * testFunction(char arr[500])
> {
> int n;
>
> /* Same sizeof line of code that was in main() - note here that it
> output the size of a pointer!*/
> printf("sizeof arr = %d\n", sizeof(arr));


That is because it *is* outputting the size of a pointer.

> return arr;


Here you are *not* returning an array, you are returning a pointer.

> }

--
Flash Gordon
Living in interesting times.
Although my email address says spam, it is real and I read it.

Christopher Benson-Manica 12-17-2005 09:28 PM

Re: Inconsistent
 
jimbo <jimbo@gmail.com> wrote:

> 1. Are the comments in it correct?


You forgot the part about "Never do this."

> 2. Why does sizeof(arr) not work consistently in C?


Because it doesn't work the way you seem to think it does.

> In someFunction()
> sizeof(arr) means sizeof(&arr[0]) in main. The compiler knows how big arr
> is, so why the difference - esp. as it would be v.useful if sizeof(arr)
> worked in someFunction as it does in main - so you could use sizeof(arr) in
> the conditional bit of,say, a for loop in someFunction for example?


Because the 500 in

> char * testFunction(char arr[500])


is completely meaningless. arr is a pointer to a char; the compiler
has no idea how many it points to. That's your job.

> 3. Why doesn't C allow testFunction to be declared char [] testFunction -


Because char[] and char * are not the same. IIRC, char [] is an array
of pointers of unspecified size.

> seems to me that if it did you could get away with knowing less about
> pointers,


Thus further burying the secrets of how to use them correctly...

--
Christopher Benson-Manica | I *should* know what I'm talking about - if I
ataru(at)cyberspace.org | don't, I need to know. Flames welcome.

Mark McIntyre 12-17-2005 09:54 PM

Re: Inconsistent
 
On Sat, 17 Dec 2005 20:11:41 GMT, in comp.lang.c , "jimbo"
<jimbo@gmail.com> wrote:

>2. Why does sizeof(arr) not work consistently in C?


It does. Please read the documentation on it carefully, understand the
difrference between a pointer and an array, and understand what
happens to arrays when passed as parameters to functions.

> /* Lie to the compiler. Should be ok though as the compiler knows how
>big the array really is.*/
> char arr[7] = "0123456789";


No, its disastrous. You just overwrote memory that doesn't belong to
you.

Never lie to the compiler. Like your grandmother, it will find you out
and beat you with a willow twig.

----== Posted via Newsfeeds.Com - Unlimited-Unrestricted-Secure Usenet News==----
http://www.newsfeeds.com The #1 Newsgroup Service in the World! 120,000+ Newsgroups
----= East and West-Coast Server Farms - Total Privacy via Encryption =----

Emmanuel Delahaye 12-17-2005 10:07 PM

Re: Inconsistent
 
jimbo a écrit :
> Could someone comment on this code please.


First of all, you should learn to tune your compiler in a better way.

Compiling: main.c
main.c: In function `main_':
main.c:7: warning: initializer-string for array of chars is too long
main.c:10: error: implicit declaration of function `printf'
main.c:10: warning: nested extern declaration of `printf'
<internal>:0: warning: redundant redeclaration of 'printf'
main.c: In function `testFunction':
main.c:30: warning: nested extern declaration of `printf'
<internal>:0: warning: redundant redeclaration of 'printf'
main.c:26: warning: unused variable `n'
main.c:33:3: warning: no newline at end of file
Process terminated with status 1 (0 minutes, 0 seconds)
1 errors, 5 warnings

> 1. Are the comments in it correct?


/* -ed-
missing header for printf()
(a prototype in scope is mandatory for variadics functions)
*/
#include <stdio.h>

char * testFunction(char []);

int main(void)
{
/* Lie to the compiler. Should be ok though as the compiler knows how
big the array really is.*/
char arr[7] = "0123456789";

/* -ed- I have this (gcc/mingw):

main.c:19: warning: initializer-string for array of chars is too long

sounds enough to me.

On another compiler (BC 3.1), I have a compile error.
*/

/* Ouput the sizeof the array. And the size of a pointer to it. */
printf("main() sizeof arr = %d\n", sizeof(arr));
printf("main() sizeof arr = %d\n", sizeof(&arr[0]));

/* Pass it on to the function where we'll do some other emaningless
things.*/
testFunction(arr);
return 0;
}

/* Can't declare testFunction as char [] testF...() - even though the
compiler knows that array's are passed by address.*/
/* -ed- What's wrong with

char * testF...()

which is exactly the reflect of the truth ?
*/

/* The size is ignored - and can't be checked anyway.*/
/* -ed-
True. This is because of the type you used (pointer to an element).
Try 'pointer to an array' and it will be different. (But hard to
maintain).
The pointer to element way is simple and dynamic.
Just add a nb_of_elements parameter.
*/
char * testFunction(char arr[500])
{
int n;
/* -ed- never used...

main.c:38: warning: unused variable `n'

*/

/* Same sizeof line of code that was in main() - note here that it
output the size of a pointer!*/
printf("sizeof arr = %d\n", sizeof(arr));
/* -ed-
Undefined behaviour. sizeof returns a size_t. You want

printf("sizeof arr = %zu\n", sizeof(arr));

or

printf("sizeof arr = %lu\n", (unsigned long) sizeof arr);

but keep in mind that 'arr' is just another pointer.
You will have the sizeof a a pointer, not to the pointed array.
An extra parameter is required for that
(all the difference between gets() and fgets()).

Note that the parens are not required with objects.

*/
return arr;
}

> 2. Why does sizeof(arr) not work consistently in C?


It does. Just don't mix arrays and pointers.

--
A+

Emmanuel Delahaye

Emmanuel Delahaye 12-17-2005 10:43 PM

Re: Inconsistent
 
Flash Gordon a écrit :
> Here you are *not* returning an array, you are returning a pointer.
>
>> }

Or more likely, an address...

--
A+

Emmanuel Delahaye

Flash Gordon 12-17-2005 11:10 PM

Re: Inconsistent
 
Emmanuel Delahaye wrote:
> Flash Gordon a écrit :
>> Here you are *not* returning an array, you are returning a pointer.
>>
>>> }

> Or more likely, an address...


The last time I looked the null pointer was not an address, although I
will happily accept correction if someone can point out something in the
standard that says otherwise. So I think it more accurate to talk of
returning a pointer than an address.
--
Flash Gordon
Living in interesting times.
Although my email address says spam, it is real and I read it.

Keith Thompson 12-18-2005 01:10 AM

Re: Inconsistent
 
"jimbo" <jimbo@gmail.com> writes:
> Could someone comment on this code please.
>
> 1. Are the comments in it correct?
>
> 2. Why does sizeof(arr) not work consistently in C? In someFunction()
> sizeof(arr) means sizeof(&arr[0]) in main. The compiler knows how big arr
> is, so why the difference - esp. as it would be v.useful if sizeof(arr)
> worked in someFunction as it does in main - so you could use sizeof(arr) in
> the conditional bit of,say, a for loop in someFunction for example?
>
> 3. Why doesn't C allow testFunction to be declared char [] testFunction -
> seems to me that if it did you could get away with knowing less about
> pointers, and it seems as though again that C is incosistent, i.e., you
> don't have to declare testFunction's parameter as char *. Surely, the
> compiler should know that char [] someFunction actually means char *
> someFunction??
>
> char * testFunction(char []);
>
> int main(void)
> {
> /* Lie to the compiler. Should be ok though as the compiler knows how
> big the array really is.*/
> char arr[7] = "0123456789";


What do you mean "should be ok"? To handle this, the compiler would
either have to make arr bigger than you asked, or ignore part of the
initializer; neither is a sensible thing to expect.

I'm not sure whether this is a constraint violation or undefined
behavior, but it's certainly a bad idea (as lying to the compiler
always is). Don't do that.

(If the initializer were too short, the remaining elements would be
initialized to zero.)

As for the rest of your questions, C's treatment of arrays and
pointers is actually (mostly) consistent, though it can be confusing.
Section 6 of the comp.lang.c FAQ has a lot of good information; you
can find it at <http://www.eskimo.com/~scs/C-faq/top.html>.

To summarize:

Arrays are arrays. Pointers are pointers. Arrays are not pointers.
Pointers are not arrays. Anyone who tells you otherwise is mistaken.

An expression of array type, in most contexts, is implicitly converted
to a pointer to the array's first element; this conversion does not
happen for the operand of a unary "&" or "sizeof" operator, or for a
string literal used to initialize an array. (Thus you can initialize
an array object with a string literal, but you can't *assign* a string
literal to an array object.)

As a special case, a parameter declaration such as
void func(SOME_TYPE *param);
can be written as
void func(SOME_TYPE param[]);
These are equivalent; the latter really declares a pointer, not an
array. This makes it slightly easier to ignore the distinction
between pointers and arrays. In my opinion, it was a mistake to have
this feature in the language. This equivalence applies only to
function parameters; in particular, it does not apply to function
return types. (It's been argued that the param[] form is useful to
document the intent that the argument should be an array, but the
compiler doesn't check this. If you want to document something that
the compiler can't check, you can use a comment.)

The indexing operator x[y], takes two operands, a pointer and an
integer (*not* an array and an integer). Typically, the pointer
operand is going to be an array name, which will be implicitly
converted to a pointer before the indexing operator sees its value.
x[y] is by definition equivalent to *(x+y). (Because addition is
commutative, x[y] can be written as [y]x; this odd little quirk is in
no way useful.)

--
Keith Thompson (The_Other_Keith) kst-u@mib.org <http://www.ghoti.net/~kst>
San Diego Supercomputer Center <*> <http://users.sdsc.edu/~kst>
We must do something. This is something. Therefore, we must do this.

Simon Biber 12-18-2005 01:17 AM

Re: Inconsistent
 
Christopher Benson-Manica wrote:
> jimbo <jimbo@gmail.com> wrote:
>>3. Why doesn't C allow testFunction to be declared char [] testFunction -

>
>
> Because char[] and char * are not the same. IIRC, char [] is an array
> of pointers of unspecified size.


You remember incorrectly. In the parameter list of a function, char[]
and char* are exactly the same. In any other declaration they are
different. char[] is never an array of pointers. It can represent an
array of char, of unspecified size. If an initialiser is provided, it
represents an array of char, of the size required to contain the
initialiser. For example,

$ cat foo.c

#include <stdio.h>

/*
The following line declares an array of char of unspecified size. It
is OK to use this array, but not to ask the compiler about its size
within this translation unit.
*/
extern char bar[];

void print_bar(void)
{
puts(bar);
}

$ cat bar.c

/*
The following line defines an array of char whose size is inferred
from the initialiser given, so it will be 13 chars long. It is OK
to both use this array and ask the compiler about its size within
this translation unit.
*/
char bar[] = "hello, world";

void print_bar(void);

int main(void)
{
print_bar();
return 0;
}

$ c99 -pedantic -Wall -W -O2 -c foo.c
$ c99 -pedantic -Wall -W -O2 -c bar.c
$ c99 foo.o bar.o -o foobar
$ ./foobar
hello, world

--
Simon.

Keith Thompson 12-18-2005 01:22 AM

Re: Inconsistent
 
Emmanuel Delahaye <emdel@YOURBRAnoos.fr> writes:
> Flash Gordon a écrit :
>> Here you are *not* returning an array, you are returning a pointer.
>>
>>> }

> Or more likely, an address...


Is this the old argument about the meanings of the terms "pointer" and
"address"?

It's reasonable, IMHO, to use the term "pointer" only to refer to an
object of pointer type, and the term "address" to refer to a *value*
of pointer type. Thus the value of a pointer object is an address. I
generally try to use the terms this way myself.

But the standard doesn't make this distinction, at least not
consistently. For example, the malloc() function "returns either a
null pointer or a pointer to the allocated space".

I think we have to accept that referring to a pointer value, such as
"returning a pointer", is acceptable.

If that wasn't your point, wha was?

--
Keith Thompson (The_Other_Keith) kst-u@mib.org <http://www.ghoti.net/~kst>
San Diego Supercomputer Center <*> <http://users.sdsc.edu/~kst>
We must do something. This is something. Therefore, we must do this.


All times are GMT. The time now is 02:53 PM.

Powered by vBulletin®. Copyright ©2000 - 2014, vBulletin Solutions, Inc.
SEO by vBSEO ©2010, Crawlability, Inc.