sizeof() confusion
Chris Torek
chris at mimsy.umd.edu
Mon Nov 5 18:38:01 AEST 1990
In article <9156 at latcs1.oz.au> jacob at latcs1.oz.au (Jacob L. Cybulski)
asks why, given the quoted code, sizeof(Pattern) != sizeof(x):
>typedef unsigned char Pattern[8];
>void foo(Pattern x) {
>/* 0 */ printf("%d\n", sizeof(Pattern); /* prints 8 */
>/* 1 */ printf("%d\n", sizeof(x)); /* prints 4 */
>The intuition says that sizeof(Pattern) = sizeof(x) regardless of the
>Pattern definition.
Almost true---but *not* regardless of the `x' definition. (Incidentally,
your example is clearly not out of a working program, as it has a missing
close parenthesis.)
>Well, not in C, if Pattern is an array then it is implemented as a
>pointer so sizeof(x) is a pointer length ....
Bad referent for `it' (core dumped) :-)
In C, there is no such thing as an array parameter. In a language much
like C, but more strict, compilers would be required to reject any
parameter declaration whose type is `array N of T', for any N and T.
But the C language grants explicit rope with which you may hang yourself:
you may declare any parameter as an array, and the compiler will say
`Oh, that's not an array N of T, that's a pointer to T. I'll just tidy
up here and pretend you wrote ``pointer to T''.'
But there *are* array objects, and any other declaration of type
`array N of T' really does mean `array N of T'.
Since `typedef' does not make a new type, but rather a synonym for an
old type, `typedef unsigned char Pattern[8];' simply makes `Pattern'
a synonym for `array 8 of unsigned char'. The compiler sees your
function definition as
Declare foo as a function returning void, in which
there is one argument whose type is `array 8 of unsigned
char'. Define the function with the contents of the block.
The compiler does its bit with the type of the argument and changes
this to:
Declare foo as a function returning void, in which
there is one argument whose type is `pointer to unsigned
char'.
Thus, you have not actually written `void foo(Pattern x)'. You have
actually written `void foo(unsigned char *x)'.
>/* 2 */ printf("%d\n", sizeof(*x)); /* prints 1 */
>*x is an address of the first array element so it's length is that
>of its elements
No: `x' is `pointer to unsigned char', so `*x' is `unsigned char', and
sizeof(unsigned char) is 1.
>/* 3 */ printf("%d\n", sizeof((Pattern) x); /* illegal */
>the cast of x into its type is illegal possibly because x is
>implicitly defined as a (Pattern *)
No, the cast is illegal because there is no such thing an an array value,
and the result of a cast is a value, not an object. It is therefore
illegal to use an array type (such as `array 8 of unsigned char', aka
`Pattern') in a cast.
>/* 4 */ printf("%d\n", sizeof(*((Pattern *) x)); /* prints 8 */
>finally a convoluted casting and redirection gives you the right answer
Sort of. `x' is a pointer to array 8 of unsigned char, and can be cast
to a different pointer type (with implementation-defined semantics for
the actual value produced, although here the value is not used and must
be generated by the compiler). `Pattern *' is another name for
`pointer to array 8 of unsigned char'. Indirecting (the first unary `*'
above) produces an object---the result of an indirection is always an
object, much as the result of a cast or address-of operator is never an
object---of type `array 8 of unsigned char'. In a value context, this
object would be transformed into a value of type `pointer to unsigned
char', but unlike an actual function parameter, sizeof() does not call
for a value. Thus, the object is in object context and remains an array,
and hence has size 8*sizeof(unsigned char) or 8*1 or 8.
>Any answers?
Never use array parameters. :-)
More seriously: for fixed opaque types that happen to be implementable
as an array, you are often better off making the type be a structure
whose only member is an array. Instead of
typedef unsigned char Pattern[8];
write
typedef struct Pattern { unsigned char p_foo[8]; } Pattern;
You now have a compound object which acts more like simple objects,
rather than one that displays the peculiarity of changing type (and
hence also value) whenever it appears in a value context.
--
In-Real-Life: Chris Torek, Univ of MD Comp Sci Dept (+1 301 405 2750)
Domain: chris at cs.umd.edu Path: uunet!mimsy!chris
More information about the Comp.lang.c
mailing list