Re: AU - CW code gen problems - solved!
Re: AU - CW code gen problems - solved!
- Subject: Re: AU - CW code gen problems - solved!
- From: Brian Willoughby <email@hidden>
- Date: Sat, 29 Mar 2003 13:19:59 -0800
Hi folks,
Here is my pedantic contribution to the discussion :-)
The Apple code indeed has a bug - you can see an inconsistency between the
type of the expression provided as a parameter and the cast applied to it.
EventHandlerRef theHandlers[count];
CFDictionaryGetKeysAndValues(mHandlers, NULL, (const void **)&theHandlers);
However, the explanation is what gets tricky.
In C, arrays do not degenerate to pointers (when passed to a function),
because they are already the same as a pointer. Despite how low level standard
C is, it does have some types which are merely for the benefit of us humans.
There is no difference between an unsized array of a given type and a pointer
to the same type. They can be used interchangeably. So there is no difference
between the following two lines:
EventHandlerRef theHandlers[];
EventHandlerRef *theHandlers;
Arrays, of course, have the benefit of allowing the programmer to allocate
some memory without a system call. theHandlers[12] is different from
theHandlers[]
The real explanation (pertaining to Apple's bug above) is that the effective
address of an array is identical to the address of the first item in the array.
The first item in an array is "array[0]" while the address of the first item
in the array "&array[0]" and the address of the array itself "array" are
identical. It's actually nonsense to ask for "&array" because you're already
getting the address of the array with just "array".
It would be nice if compilers produced a warning when "&array" is encountered,
since its meaning is undefined (impossible to define). At least "-Wall",
which should turn on all warnings, does not complain. Perhaps the CodeWarrior
compiler should issue a warning in this case, since it does not produce the
same result for this undefined situation as more standard compilers.
You can, however, get the address of a pointer, because it is stored
somewhere. The address of an array is simply known by the compiler and used
where needed, but never stored during program execution (except in registers)
unless you copy it to a variable.
I have some example code, but I'm not really sure if it truly illustrates the
difference between the two explanations offered so far. Here it is anyway:
#include <stdio.h>
typedef struct
{
long value;
float number;
} opaqueType;
int main(int argc, char *argv[])
{
opaqueType theArray[12];
opaqueType anArray[12];
// there is no warning for the next line, even without a cast
opaqueType *thePointer = anArray; // the types are interchangeable
// theArray is the same as &theArray[0]
printf("theArray %#p, &theArray[0] %#p, &theArray %#p\n", theArray,
&theArray[0], &theArray);
// thePointer can be used just like anArray, as in thePointer[0]
printf("thePointer %#p, &thePointer[0] %#p, &thePointer %#p\n",
thePointer, &thePointer[0], &thePointer);
// thePointer[0] is also the same as *thePointer
return 0;
}
compiled with gcc 2.5.8 gives the output:
theArray 0x3fffbbc, &theArray[0] 0x3fffbbc, &theArray 0x3fffbbc
thePointer 0x3fffb5c, &thePointer[0] 0x3fffb5c, &thePointer 0x3fffb58
See the Kernighan and Ritchie C Programming Language book's chapter on
Pointers and Arrays. The old-school obfuscated C programming contests are also
a fun way to learn C inside and out.
Brian Willoughby
Sound Consulting
Begin forwarded message:
I can try to explain the problem. This is due to the "confusion" made
in C between a pointer and an array.
If you declare an array variable, eg:
EventHandlerRef theHandlers[12] ;
and if you pass this variable to a function, it degenerates to a
EventHandlerRef * type. When you apply the & operator to the variable
theHandlers, you get the address of the variable theHandlers ie the
address of the array. That's why you will obtain the same result if you
execute:
printf ("theHandlers 0x%x", theHandlers) ;
or:
printf ("theHandlers 0x%x", &theHandlers) ;
Now if you declare a pointer variable, eg:
EventHandlerRef * theHandlers ;
then passing theHandlers to a function does not degenerates its type.
This means that theHandlers will be the value of the pointer, and &
theHandlers will be the **address** of the pointer theHandlers. Not
exactly the same.
This little piece of code
int main (int argc, char* argv[])
{
EventHandlerRef theHandlers[12] ;
printf("theHandlers 0x%x, &theHandlers 0x%x\n", theHandlers,
&theHandlers) ;
EventHandlerRef* theHandlers_ = new EventHandlerRef[12] ;
printf("theHandlers_ 0x%x, &theHandlers_ 0x%x\n", theHandlers_,
&theHandlers_) ;
}
compiled with CW gives the output:
theHandlers 0xbffffc98, &theHandlers 0xbffffc98
theHandlers_ 0x54ff0, &theHandlers 0xbffffc90
_______________________________________________
coreaudio-api mailing list | email@hidden
Help/Unsubscribe/Archives:
http://www.lists.apple.com/mailman/listinfo/coreaudio-api
Do not post admin requests to the list. They will be ignored.