Path: utzoo!utgpu!watserv1!watmath!att!ima!ima.isc.com From: karl@ima.isc.com (Karl Heuer) Newsgroups: comp.lang.c Subject: Re: sizeof() confusion Message-ID: <5238@ima.ima.isc.com> Date: 5 Nov 90 06:08:50 GMT References: <9156@latcs1.oz.au> Sender: karl@ima.ima.isc.com Reply-To: karl@ima.isc.com (Karl Heuer) Organization: Interactive Systems Lines: 56 Supersedes: <1990Nov05.054851.6933@dirtydog.ima.isc.com> In article <9156@latcs1.oz.au> jacob@latcs1.oz.au (Jacob L. Cybulski) writes: > typedef unsigned char Pattern[8]; > void foo (Pattern x) { ... } This is related to the pointer-vs-array stuff in the FAQ, which you should read if you haven't already, but I'll post this answer which is in terms of your specific example. The typedef just disguises things; this is equivalent to void foo(unsigned char x[8]) { ... } which, it can be argued, is logically incorrect since C does not allow arrays to be passed by value. However, tradition and the ANSI Standard say that this should be accepted anyway, and *silently rewritten* as void foo(unsigned char *x) { ... } since that's `probably' what the user really meant. (A better alternative, in my opinion, would have been to simply forbid array-parameter declarations in function prototypes until such time as array copy is legalized.) >the cast of x into its type is illegal possibly because x is implicitly >defined as a (Pattern *) (case 3), No, there are no `Pattern *' expressions in your code. The type of x is `unsigned char *' even if you thought you declared it as `Pattern'. (This rewrite is *only* true of formal parameters, and does not apply to any other kind of declaration.) You get an error because it's illegal to cast anything to an array type. To avoid this type of confusion, I recommend: (a) *NEVER* declare formal arguments of array type; always use pointer syntax. (Some people like to use pointer vs. array syntax to distinguish how they intend to use the object, but this causes more confusion than it's worth, and besides it doesn't generalize to non-parameter declarations.) (b) If you want to use opaque types via typedefs, pass them in by reference (`Pattern *x' would have produced more consistent results, and is one of the few reasonable uses for a pointer-to-entire-array). (c) If you might have to port to a pre-ANSI implementation that doesn't believe in array pointers, then don't use arrays in typedefs either. Enclose it in a struct first: typedef struct { unsigned char c[8]; } Pattern; ... x->c[i]; ... /* was x[i] */ >Now is it the fault of my compiler (THINK C) to give me such a hard time, >is it my bad C programming style, or is it the ANSI standard which has some >gaping semantic holes? The compiler is innocent. I can't really call your style `bad' without insulting several expert contributors to this group who also happen to use it, but I always disrecommend it since it does lead to this common pitfall. I would classify it as a mistake in Classic C, a botch which X3J11 unfortunately chose to repeat rather than fix. (For more details on a possible fix, see alt.lang.cfutures.) Karl W. Z. Heuer (karl@ima.isc.com or uunet!ima!karl), The Walking Lint