Address of array and function, & is superfluous
Author |
Message |
Mark A. Odel #1 / 22
|
 Address of array and function, & is superfluous
I mistakenly passed a pointer to a function to a function by putting an & on it as shown below: #include <stdio.h> void callback(void) { return; } void func(void (*pCallback)(void)) { pCallback(); Quote: }
int main(void) { func(&callback); /* This works. */ func(callback); /* This works. */ return 0; Quote: }
I see why it works, it just confused me for a moment. Please verify that I haven't missed something. Same goes for an array. -- - Mark A. Odell - Embedded Firmware Design, Inc. - http://www.*-*-*.com/
|
Sun, 14 Mar 2004 22:32:18 GMT |
|
 |
Tak-Shing Cha #2 / 22
|
 Address of array and function, & is superfluous
Quote: > I mistakenly passed a pointer to a function to a function by putting an & > on it as shown below: > #include <stdio.h> > void callback(void) { return; } > void func(void (*pCallback)(void)) > { > pCallback(); > } > int main(void) > { > func(&callback); /* This works. */ > func(callback); /* This works. */ > return 0; > } > I see why it works, it just confused me for a moment. Please verify that I > haven't missed something. Same goes for an array.
callback (without &) is converted to an expression that has type pointer to function returning void (C99 6.3.2.1 #4). Tak-Shing
|
Mon, 15 Mar 2004 00:06:33 GMT |
|
 |
Christian Ba #3 / 22
|
 Address of array and function, & is superfluous
Quote:
> I mistakenly passed a pointer to a function to a function by putting an & > on it as shown below: > #include <stdio.h> > void callback(void) { return; } > void func(void (*pCallback)(void)) > { > pCallback(); > } > int main(void) > { > func(&callback); /* This works. */ > func(callback); /* This works. */ > return 0; > } > I see why it works, it just confused me for a moment. Please verify that I > haven't missed something. Same goes for an array.
As part of an expression, the name of a function like "func" or "callback" is something called a "function designator". And in some situations a "function designator" is converted to a function pointer: If the address operator & is applied to it, or if it is followed by an expression list in brackets, or if it is evaluated on its own. In the call func(callback), callback is converted to a function pointer, and func is evaluated to a function pointer. As with arrays, this conversion does NOT happen if a "function designator" is the operand of a sizeof operator. The difference is that arrays are allowed as operands of the sizeof operator, but function designators aren't. So if you also have int a [10]; then sizeof (&callback) -> size of a function pointer, often four or eight sizeof (callback) -> not allowed sizeof (&a) -> size of a pointer to an array of 10 integers, often four or eight sizeof (a) -> size of an array of 10 integers, often 20, 40 or 80
|
Mon, 15 Mar 2004 00:18:29 GMT |
|
 |
Dan P #4 / 22
|
 Address of array and function, & is superfluous
Quote: >I mistakenly passed a pointer to a function to a function by putting an & >on it as shown below: >#include <stdio.h> >void callback(void) { return; } >void func(void (*pCallback)(void)) >{ > pCallback(); >} >int main(void) >{ > func(&callback); /* This works. */ > func(callback); /* This works. */ > return 0; >} >I see why it works, it just confused me for a moment. Please verify that I >haven't missed something.
It works, the & operator is superfluous in this context. Quote: >Same goes for an array.
With arrays things are more subtle: char arr[10]; Except when used as the argument of sizeof, arr is a pointer to the first char of an array of 10 char's. &arr is a pointer to an array of 10 char's. They have different types and cannot be used interchangeably, even if they express the same address: ues5:~/tmp 27> cat -n test.c 1 void foo(char *bar) {} 2 3 int main() 4 { 5 char arr[10]; 6 foo(arr); 7 foo(&arr); 8 return 0; 9 } ues5:~/tmp 28> gcc test.c test.c: In function `main': test.c:7: warning: passing arg 1 of `foo' from incompatible pointer type Dan -- Dan Pop CERN, IT Division
Mail: CERN - IT, Bat. 31 1-014, CH-1211 Geneve 23, Switzerland
|
Sun, 14 Mar 2004 23:30:01 GMT |
|
 |
Mark A. Odel #5 / 22
|
 Address of array and function, & is superfluous
Thank you Dan, et al. I appreciate your answers. -- - Mark A. Odell - Embedded Firmware Design, Inc. - http://www.embeddedfw.com
|
Mon, 15 Mar 2004 00:18:39 GMT |
|
 |
ralmi #6 / 22
|
 Address of array and function, & is superfluous
Quote:
> Except when used as the argument of sizeof, arr is a pointer to the > first char of an array of 10 char's. &arr is a pointer to an array of > 10 char's. They have different types and cannot be used interchangeably, > even if they express the same address:
I was thinking about how to correctly use &arr which has type "pointer to array 10 of char". #include <stdio.h> /* declare foo as function (pointer to array 2 of int) * returning pointer to array 2 of int */ int (*foo(int (*)[2]))[2]; int main (void) { int a[2] = {3, 4}; int (*b)[2]; b = foo (&a); printf ("(*b)[0] = %i, (*b)[1] = %i\n", (*b)[0], (*b)[1]); return 0; Quote: }
int (*foo(int (*bar)[2]))[2] { ++(*bar)[0]; --(*bar)[1]; return bar; Quote: }
Ralmin.
|
Mon, 15 Mar 2004 00:28:37 GMT |
|
 |
Gergo Baran #7 / 22
|
 Address of array and function, & is superfluous
Quote: > I mistakenly passed a pointer to a function to a function by putting an & > on it as shown below: > [snip] > func(&callback); /* This works. */ > func(callback); /* This works. */ > I see why it works, it just confused me for a moment. Please verify that I > haven't missed something.
You haven't. When it is *not* the operand of the unary & (address-of) operator, a function designator is converted to a pointer to the function it designates. If it *is* the operand of the address-of operator, this implicit conversion doesn't take place, but the same conversion is done by the & operator. It's the same thing. Note that while a single & operator is redundant here, you cannot use more than one because the "decayed" function pointer is not an lvalue. Quote: > Same goes for an array.
Nope. Consider int arr[10]; If this is not the operand of sizeof or unary &, it is implicitly converted into a pointer (int *) to the first array element. If it is the operand of the & operator, that operator converts it into a pointer of type (int (*)[10]) to the *whole* array. Gergo -- "I don't need to fight to prove I'm right." -- Pete Townshend
|
Sun, 14 Mar 2004 23:08:46 GMT |
|
 |
-hs #8 / 22
|
 Address of array and function, & is superfluous
Quote: > #include <stdio.h> > void callback(void) { return; } > void func(void (*pCallback)(void)) > { > pCallback(); > } > int main(void) > { > func(&callback); /* This works. */ > func(callback); /* This works. */ > return 0; > } > I see why it works, it just confused me for a moment. Please verify > that I haven't missed something. Same goes for an array.
They both are correct. On Borland C, the first case produces a warning "superflous & with function" -- -hs- emdel at noos.fr "support Afghans against Talebans" "Car les bandits qui sont cause des guerres N'en meurent jamais, on n'tue qu'les innocents." Gaston Monthus -- La Butte Rouge
|
Mon, 15 Mar 2004 03:15:33 GMT |
|
 |
Dann Corbi #9 / 22
|
 Address of array and function, & is superfluous
Quote:
> > #include <stdio.h> > > void callback(void) { return; } > > void func(void (*pCallback)(void)) > > { > > pCallback(); > > } > > int main(void) > > { > > func(&callback); /* This works. */ > > func(callback); /* This works. */ > > return 0; > > } > > I see why it works, it just confused me for a moment. Please verify > > that I haven't missed something. Same goes for an array. > They both are correct. On Borland C, the first case produces a warning > "superflous & with function"
They are not the same thing. Only func(callback) is the correct form. Similarly for an array. For example: void string_munger(char *s) { /* whatever */ Quote: }
int main(int argc, char **argv) { if (argc) { char *s = argv[0]; string_munger(s); /* Normal sort of call */ string_munger(&s[0]);/* This one is exactly equivalent */ string_munger(&s); /* This is wrong. It has the wrong level of indirection. */ Quote: } return 0; }
From the previous question about functions: Quote: > > func(&callback); /* This works. */
By accident. Here func() is called with the address of the function pointer (which is already an address). I have seen this "work" too, but it isn't the right way to do it. Again, this is being called with the address of a function pointer, which is the wrong level of indirection. Quote: > > func(callback); /* This works. */
As well it should. -- C-FAQ: http://www.eskimo.com/~scs/C-faq/top.html "The C-FAQ Book" ISBN 0-201-84519-9 C.A.P. FAQ: ftp://cap.connx.com/pub/Chess%20Analysis%20Project%20FAQ.htm
|
Mon, 15 Mar 2004 04:52:52 GMT |
|
 |
Tak-Shing Cha #10 / 22
|
 Address of array and function, & is superfluous
Quote:
> the right way to do it. Again, this is being called with the address of a > function pointer, which is the wrong level of indirection.
Not so. See C99 6.3.2.1 #4. Tak-Shing
|
Mon, 15 Mar 2004 06:00:10 GMT |
|
 |
Kaz Kylhe #11 / 22
|
 Address of array and function, & is superfluous
Quote:
>> > #include <stdio.h> >> > void callback(void) { return; } >> > void func(void (*pCallback)(void)) >> > { >> > pCallback(); >> > }
[ snip ] Quote: >From the previous question about functions: >> > func(&callback); /* This works. */ >By accident. Here func() is called with the address of the function pointer >(which is already an address).
callback is a function designator, which will ``decay'' to a pointer when evaluated. It's not evaluated when it's the operand of &; in that case, & will take the address of the function designator to obtain a pointer. Arrays are different, because & will yield a pointer to the whole array, while the decay yields a pointer to the first element. In the case of functions, & and decay yield the same thing.
|
Mon, 15 Mar 2004 06:16:06 GMT |
|
 |
Dann Corbi #12 / 22
|
 Address of array and function, & is superfluous
Quote:
> > the right way to do it. Again, this is being called with the address of a > > function pointer, which is the wrong level of indirection. > Not so. See C99 6.3.2.1 #4.
"4 A function designator is an expression that has function type. Except when it is the operand of the sizeof operator 54) or the unary & operator, a function designator with type ''function returning type'' is converted to an expression that has type ''pointer to function returning type''." The above said "*Except* when it is the operand of .. or the unary & operator ... is converted to an expression that has type ''pointer to function returning type'' which indicates to me that it will NOT yield a pointer to function returning type when the & operator is applied. Rather, it would yield the address of that pointer [well, that's what I would expect]. My question is (therefore) to the gurus who inhabit the high halls of
Are these two calls [exhibit A and exhibit B] equivalent: #include <stdio.h> typedef void (*ftype) (void); void foo(void) { puts("hi."); Quote: }
void f(ftype a) { a(); Quote: }
int main(void) { /* Exhibit A: */ f(foo); /* Exhibit B: */ f(&foo); return 0; Quote: }
/* ** Inquiring minds want to know. ** Please quote chapter and verse, so I may see where I went off. */ -- C-FAQ: http://www.eskimo.com/~scs/C-faq/top.html "The C-FAQ Book" ISBN 0-201-84519-9 C.A.P. FAQ: ftp://cap.connx.com/pub/Chess%20Analysis%20Project%20FAQ.htm
|
Mon, 15 Mar 2004 07:08:24 GMT |
|
 |
Barry Margoli #13 / 22
|
 Address of array and function, & is superfluous
Quote:
>> > the right way to do it. Again, this is being called with the address of >a >> > function pointer, which is the wrong level of indirection. >> Not so. See C99 6.3.2.1 #4. >"4 A function designator is an expression that has function type. Except >when it is the operand of the sizeof operator 54) or the unary & operator, a >function designator with type ''function returning type'' is converted to an >expression that has type ''pointer to function returning type''." >The above said "*Except* when it is the operand of .. or the unary & >operator ... is converted to an expression that has type ''pointer to >function returning type'' which indicates to me that it will NOT yield a >pointer to function returning type when the & operator is applied. Rather, >it would yield the address of that pointer [well, that's what I would >expect].
The point that the "except when..." clause is making is that you don't convert the function designator to a pointer before applying the & operator to it. However, the & operator, applied to an object of type T, always returns a value of type 'pointer to T'. So, &<function designator> returns a value of type 'pointer to function'. Without that exception, the value of &<function designator> would be of type 'pointer to pointer to function'. Quote: >My question is (therefore) to the gurus who inhabit the high halls of
>Are these two calls [exhibit A and exhibit B] equivalent:
Yes. In Exhibit A, foo is converted to a pointer due to the normal conversion. In Exchibit B, foo designates the function itself, and the & operator returns the function's address. Quote: >#include <stdio.h> >typedef void (*ftype) (void); >void foo(void) >{ > puts("hi."); >} >void f(ftype a) >{ > a(); >} >int main(void) >{ >/* Exhibit A: */ > f(foo); >/* Exhibit B: */ > f(&foo); > return 0; >}
--
Genuity, Woburn, MA *** DON'T SEND TECHNICAL QUESTIONS DIRECTLY TO ME, post them to newsgroups. Please DON'T copy followups to me -- I'll assume it wasn't posted to the group.
|
Mon, 15 Mar 2004 08:00:47 GMT |
|
 |
Greg Come #14 / 22
|
 Address of array and function, & is superfluous
Quote:
>> > the right way to do it. Again, this is being called with the >> > address of a function pointer, which is the wrong level of indirection. >> Not so. See C99 6.3.2.1 #4. >"4 A function designator is an expression that has function type. Except >when it is the operand of the sizeof operator 54) or the unary & operator, a >function designator with type ''function returning type'' is converted to an >expression that has type ''pointer to function returning type''."
Ok. Quote: >The above said "*Except* when it is the operand of .. or the unary & >operator ... is converted to an expression that has type ''pointer to >function returning type'' which indicates to me that it will NOT yield a >pointer to function returning type when the & operator is applied. Rather, >it would yield the address of that pointer [well, that's what I would >expect].
Either way it yields an address, via an (rvalue) pointer, the question is what is the type of the address. The thing is that the above talks about when it is not &'d. So, IOWs, notwithstanding sizeof, in "T1 foo(T2);", foo has type "T1(T2)", which if you don't & it, becomes through the above conversion type "T1(*)(T2)" Now, if you do & the foo, the conversion doesn't take place. However, there is a conversion defined for &. As per 6.5.3.2 in C99: "The unary & operator returns the address of its operand. If the operand has type 'type', the result has type 'pointer to type'." Therefore &foo is a pointer to a "T1(T2)" which is also a "T1(*)(T2)". Of course in the former, the function designator "itself" is converted, whereas in the latter, the value of the expression is. Quote: >My question is (therefore) to the gurus who inhabit the high halls of
>Are these two calls [exhibit A and exhibit B] equivalent: >#include <stdio.h> >typedef void (*ftype) (void); >void foo(void) >{ > puts("hi."); >} >void f(ftype a) >{ > a(); >} >int main(void) >{ >/* Exhibit A: */ > f(foo); >/* Exhibit B: */ > f(&foo); > return 0; >} >/* >** Inquiring minds want to know. >** Please quote chapter and verse, so I may see where I went off. >*/
As per above, 6.5.3.2p3. -- Greg Comeau export ETA: Dec 1 10% "End of Summer" Offer Comeau C/C++ ONLINE ==> http://www.comeaucomputing.com/tryitout World Class Compilers: Breathtaking C++, Amazing C99, Fabulous C90. Comeau C/C++ with Dinkumware's Libraries... Have you tried it?
|
Mon, 15 Mar 2004 11:22:58 GMT |
|
 |
Douglas A. Gwy #15 / 22
|
 Address of array and function, & is superfluous
Quote:
> So, IOWs, notwithstanding sizeof, in "T1 foo(T2);", foo > has type "T1(T2)", which if you don't & it, becomes through > the above conversion type "T1(*)(T2)"
Actually it has, before conversion, the abstract type (T1()(T2)). (The inner parentheses are important, as a placeholder.) Otherwise, the analysis was correct.
|
Tue, 16 Mar 2004 02:24:15 GMT |
|
|
Page 1 of 2
|
[ 22 post ] |
|
Go to page:
[1]
[2] |
|