Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > C Programming > Function pointer assignment and memset'ing - What's happening here?

Reply
Thread Tools

Function pointer assignment and memset'ing - What's happening here?

 
 
Eric Sosman
Guest
Posts: n/a
 
      02-11-2013
On 2/11/2013 4:54 PM, Eric Sosman wrote:
> [...]
> *( (int*)(data+curr_reloc->r_address) ) = (int*)puts;


Oops.

*( (int*)(data+curr_reloc->r_address) ) = (int)puts;

Sorry about that, Chief.

--
Eric Sosman
http://www.velocityreviews.com/forums/(E-Mail Removed)d
 
Reply With Quote
 
 
 
 
army1987
Guest
Posts: n/a
 
      02-12-2013
On Mon, 11 Feb 2013 12:47:45 -0800, Testing Tester wrote:

> I was kind of confused on how "*puts", "&puts" and "puts"
> produced the same result


From N1570, §6.3.2.1p2:

"A function designator is an expression that has function type. Except
when it is the operand of the sizeof operator, the _Alignof operator, 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'."

(This has the funny effect that
int main(void) { ***************puts("hello, world"); return 0; }
works.)

--
[ T H I S S P A C E I S F O R R E N T ]
Troppo poca cultura ci rende ignoranti, troppa ci rende folli.
-- fathermckenzie di it.cultura.linguistica.italiano
<http://xkcd.com/397/>
 
Reply With Quote
 
 
 
 
army1987
Guest
Posts: n/a
 
      02-12-2013
On Tue, 12 Feb 2013 00:08:32 +0000, army1987 wrote:

[snip]

And of course I should have noticed Ben Bacarisse making the exact same
point a few hours earlier. :-/

--
[ T H I S S P A C E I S F O R R E N T ]
Troppo poca cultura ci rende ignoranti, troppa ci rende folli.
-- fathermckenzie di it.cultura.linguistica.italiano
<http://xkcd.com/397/>
 
Reply With Quote
 
Ben Bacarisse
Guest
Posts: n/a
 
      02-12-2013
army1987 <(E-Mail Removed)> writes:

> On Mon, 11 Feb 2013 12:47:45 -0800, Testing Tester wrote:
>
>> I was kind of confused on how "*puts", "&puts" and "puts"
>> produced the same result

>
> From N1570, §6.3.2.1p2:
>
> "A function designator is an expression that has function type. Except
> when it is the operand of the sizeof operator, the _Alignof operator, 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'."
>
> (This has the funny effect that
> int main(void) { ***************puts("hello, world"); return 0; }
> works.)


No, because the operand of the right-most * is a function call whose
return type is int. You meant to type (***************puts)("hello, world").

--
Ben.
 
Reply With Quote
 
Ben Bacarisse
Guest
Posts: n/a
 
      02-12-2013
Testing Tester <(E-Mail Removed)> writes:

>> * * *What problem are you trying to solve?

>
> First thank you for the explanation. I'm on x86-32, and doing
> something that's very specific and so I'm almost sure there's no way
> to stay 'portable'. I'm loading an a.out file on memory, subjected to
> some constraints, and I do need to write the 4 byte-address of (say)
> puts function in a certain memory location. My code does work as
> expected using the following line:
>
> *((int *)(data+curr_reloc->r_address)) = puts;
>
> , but when I tried to replace it with a less ugly one and wasn't
> successful and I was kind of confused on how "*puts", "&puts" and
> "puts" produced the same result when trying to replace this line and
> specially on how I couldn't find an equivalent line using memcpy.


A couple of points...

First, I don't think memcpy has any advantage here -- you may as well
stick with something similar to what you have right now.

The second point is about tidying that up. You know now to include a
cast on the right hand side to get the implementation-defined conversion
from a pointer to an int:

*((int *)(data+curr_reloc->r_address)) = (int)puts;

but it may better convey your intent to use a function pointer type
instead. I'd use typedef for this. If you are not averse to hiding a
pointer type behind a typedef it might look like this:

typedef void (*code_ptr)(void);
...
*((code_ptr *)(data+curr_reloc->r_address)) = (code_ptr)puts;

If you prefer to make all the pointers explicit it will look fussier.

That might convey your meaning more clearly, unless the use of int to
hold addresses is important to the program in some other way.

--
Ben.
 
Reply With Quote
 
Keith Thompson
Guest
Posts: n/a
 
      02-12-2013
Keith Thompson <(E-Mail Removed)> writes:
[...]

[Context: `int a; a = puts;`]

> In fact, `a = puts;` is not merely implementation-defined or undefined
> behavior, it's a constraint violation. There is no implicit conversion
> from function pointers to integers. The assignment violates the
> constraint specified in N1570 6.5.16.1 regarding the permitted operands
> of a simple assignment.
>
> After issuing the required diagnostic, an implementation *may* choose to
> generate code equivalent to a conversion, as if you had written:
>
> a = (int)puts;
>
> But that conversion has undefined behavior, simply because the standard
> does not define the behavior of such a conversion.


Oops, my mistake. The result of a conversion from a function pointer to
an integer, or vice versa, is implementation-defined, not undefined.
See N1570 6.3.2.3 paragraphs 5 and 6.

A conversion from a function pointer to an object pointer, or vice
versa, does have undefined behavior.

*Assigning* an integer to a pointer (object or function), or vice versa
(except for the special case of a null pointer constant) is a constraint
violation; there is no such *implicit* conversion.

> It's very likely that your compiler copies the representation of a
> pointer to puts, or a part of it, into a. But (a) you shouldn't depend
> on that, and (b) there's very little you can usefully do with the result
> anyway.
>
> The memcpy() calls are likewise constraint violations, because there's
> no implicit conversion from a function pointer to void*.


--
Keith Thompson (The_Other_Keith) (E-Mail Removed) <http://www.ghoti.net/~kst>
Working, but not speaking, for JetHead Development, Inc.
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"
 
Reply With Quote
 
Rosario1903
Guest
Posts: n/a
 
      02-12-2013
On Mon, 11 Feb 2013 11:58:44 -0800 (PST), (E-Mail Removed)
wrote:

>What's exactly is happening in the following example?
>/*******************/
>#include <stdio.h>
>#include <stdlib.h>
>int main()
>{
> int a;


i image:
1) unsigned puts=(unsigned) AddressWherePutsIs;
2) puts is the immediate address of function

> a = puts;
> printf("%d\n", a); /* outputs 4201472 here */


1)ok
2)ok

> a = &puts;
> printf("%d\n", a); /* outputs 4201472 here */


1)this would not be with the same address
it would be the address of puts variable
2)not has address

> a = *puts;
> printf("%d\n", a); /* outputs 4201472 here */


1)this would not be
2)this would not be

if C say different, they have not one model of machine
i would say that C impose if f() is a function: f=&f=*f
i don't know why...
than i'm agains your ieee float point model
and for fixed point model
 
Reply With Quote
 
Tim Rentsch
Guest
Posts: n/a
 
      02-12-2013
Testing Tester <(E-Mail Removed)> writes:

>> What problem are you trying to solve?

>
> First thank you for the explanation. I'm on x86-32, and doing
> something that's very specific and so I'm almost sure there's no
> way to stay 'portable'. I'm loading an a.out file on memory,
> subjected to some constraints, and I do need to write the 4
> byte-address of (say) puts function in a certain memory location.
> My code does work as expected using the following line:
>
> *((int *)(data+curr_reloc->r_address)) = puts;
>
> , but when I tried to replace it with a less ugly one and wasn't
> successful and I was kind of confused on how "*puts", "&puts" and
> "puts" produced the same result when trying to replace this line
> and specially on how I couldn't find an equivalent line using
> memcpy.


It's almost always a really bad idea to cast an expression to a
pointer type and then store through the resulting pointer value.
Presumably one or the other of 'data' and 'curr_reloc->r_address'
is a pointer, probably a pointer to a character type, and the
other is of integer type. If so it's probably better to use
memcpy, eg,

int (*f)() = puts;
memcpy( &data[curr_reloc->r_address], &f, sizeof f );

or similar, perhaps written inside an inline function of some
sort if reuse is expected.

Having said that, if you are intent on using the pointer casting
technique, one, at least make it clear that an address is what's
being casted, and two, simply use (a pointer to) the type of the
value being assigned. Thus,

* (int(**)()) &data[curr_reloc->r_address] = puts;

(again under the assumption that the LHS subexpressions' types
are suitable) is a cleaner way of writing a direct assignment.
 
Reply With Quote
 
Tim Rentsch
Guest
Posts: n/a
 
      02-12-2013
James Kuyper <(E-Mail Removed)> writes:

> On 02/11/2013 02:58 PM, (E-Mail Removed) wrote:
>> [snip]
>>

> Getting back to your message:
>> printf("%d\n", a); /* outputs 4201472 here */
>>
>> memcpy(&a, puts, sizeof(int));

>
> This behavior of memcpy() is defined only when both of its
> first two arguments point at objects. The expression "puts"
> points at a function, so the behavior of this code is
> undefined. [snip elaboration[


More importantly it has a constraint violation, and must
elicit a diagnostic when compiled.
 
Reply With Quote
 
Tim Rentsch
Guest
Posts: n/a
 
      02-12-2013
Eric Sosman <(E-Mail Removed)> writes:

> C's data pointers and function pointers need not resemble each
> other at all: That's why C doesn't define any way to convert a
> function pointer to or from `void*'. In principle, functions
> and data might occupy entirely different kinds of memory with
> different characteristics and addressing modes (some embedded
> processors, I'm told, are built this way). Even when executable
> code inhabits the same kind of memory that data does, function
> pointers may be more complicated values than data pointers: I
> understand that on some systems function pointers encode not
> only the address of a function's preamble, but information about
> its signature.


In C the word is type. Some other languages (notably Russell,
which coined the term) have signatures; what C has is types.
 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
function pointer and pointer to function prashant.khade1623@gmail.com C Programming 3 04-11-2008 07:30 AM
Hash assignment (what's happening?) Hector Quiroz Ruby 2 10-05-2007 02:25 PM
diffrence between "function pointer" and "pointer to a function" murgan C Programming 6 12-21-2005 06:01 AM
pointer to member function and pointer to constant member function Fraser Ross C++ 4 08-14-2004 06:00 PM
function pointer and member function pointer question glen stark C++ 2 10-10-2003 01:41 PM



Advertisments