void pointer

E

eotcl

Dear Group!

Is it possible to dereference the void pointer to function pointer,
and refer to this pointer later as if it was a function.

Thanks.
 
N

Nick Keighley

Is it possible to dereference the void pointer to function pointer,
and refer to this pointer later as if it was a function.

you can't store a function pointer in an object pointer (eg. void*).
Some implementaions may let you do this but they aren't supposed to.

On the other hand all function pointers are "compatible"
in that any function pointer value will "fit" in any
function. Any call must use the correct type

typedef void (*FuncP) (void);

void f (void)
{}

int g (int)
{}

int main (void)
{
FuncP fp1;
FuncP fp2;
void *vp;

fp1 = f; /* ok */
fp2 = (FuncP)g; /* ok */
vp = (FuncP)g; /* BAD! */

fp1(); /* ok */
((int(*)(int))fp2)(1); /* ok- assuming I got the syntax right!
*/

fp2(); /* BAD */
}
 
R

Richard Bos

eotcl said:
Is it possible to dereference the void pointer to function pointer,
and refer to this pointer later as if it was a function.

By "dereference", I suppose you mean "convert"? The two are very
different actions, both involving pointers, but "dereference" doesn't
make sense the way you use it.
If so, no, and read the FAQ: <http://c-faq.com/ptrs/generic.html>.

Richard
 
J

James Kuyper

eotcl said:
Dear Group!

Is it possible to dereference the void pointer to function pointer,
and refer to this pointer later as if it was a function.

I believe that the term you're looking for is "convert", not
"dereference". The standard allows a null pointer of any type to be
converted into a function pointer, but it becomes a null pointer of the
function pointer type, which cannot be used to call a function. The
standard does not describe any other way in which a void* can be
converted to a function pointer type, though many implementations allow
this as an extension.

Note that any pointer to a function type can be converted to any other
pointer to function type, and back again; the resulting pointer value is
equivalent to the original. Therefore, you can use any particular
pointer to function type as a generic pointer to function type, in the
same sense that void* is a generic pointer to object type. I generally
use void(*)() for such purposes, because its the absolute minimally
complicated pointer type.

If you need to use a single object that can point to either objects or
functions, use an object of the following type:

union generic_pointer {
void *pobj;
void (*pfunc)();
};

As with all unions, make sure that you keep track of which member of the
union is currently in use. Use the wrong member, and very bad things
could happen. However, this is no different from the rule for void*
itself: you must somehow keep track of which type it should be converted
back to.
 
R

raxit

Dear Group!

Is it possible to dereference the void pointer to function pointer,
and refer to this pointer later as if it was a function.

Thanks.

Can you please explain what you wanted to do ?

-Raxit
 
E

eotcl

If you need to use a single object that can point to either >objects or
functions, use an object of the following type:
union generic_pointer {
void *pobj;
void (*pfunc)();

};
Thanks for this!
Can you please explain what you wanted to do ?

At the moment I am at the point of choosing the language
for my future programming projects. I was wandering between
C and C++ for quite a long time. What I am doing now is creating
the list of built-in C language tools, which would enable
abstraction.
My list includes :

1. void pointers.
2. function pointers.
3. variable-length argument lists.
4. structures.

If anyone could extend this list further, I would be grateful.

Thanks.
 
N

Nick Keighley

At the moment I am at the point of choosing the language
for my future programming projects. I was wandering between
C and C++ for quite a long time. What I am doing now is creating
the list of built-in C language tools, which would enable
abstraction.
My list includes :

1. void pointers.
2. function pointers.
3. variable-length argument lists.
4. structures.

If anyone could extend this list further, I would be grateful.

I'm not sure what you gain above just reading K&R.
Also note C is-almost-a-subset-of C++, all the language
features of C are available in C++.

Some C language features:

1. unions
2. preprocessor
3. arrays
4. setjmp/longjmp
5. signal
6. malloc and playmates
7. typedefs
8. assert

whilst in C++ you have exceptions, generic containers,
constructors/destructors, templates, namespaces, polymorphism,
operator overloading and I'm sure a slew of stuff I missed.

Rather than spend a long time evaluating, start programming
in one of them!

C is a smaller language. C++ has more features.


--
Nick Keighley

"If you think C++ is not overly complicated, just what is a protected
abstract virtual base pure virtual private destructor, and when
was the last time you needed one?"
-- Tom Cargil, C++ Journal.
 
V

viza

On 1 Oct, 13:47, eotcl <[email protected]> wrote:
whilst in C++ you have ... operator overloading

C has operator overloading:

int i= 2;
int j= 3;
double x= 2.0;
double y= 3.0;

i * j;
x * y;

two completely different machine operations overloaded onto the same
operator because it is easy to think of them as doing the same thing.

C++ however has _extensible_ operator overloading.

(I used to curse C++ for overloading until it was pointed out to me that
I was already using it in C!)
 
V

viza

union generic_pointer {
void *pobj;
void (*pfunc)();
};

What is better about this than just casting a void pointer to the desired
function pointer type?

void *foo= FOO;

( (void(*)(int)) foo )( 7 );

Both are not allowed by the standard, and both work for me(tm), but are
there cases where a union works where a cast doesn't or is preferable for
some other reason?
 
B

Ben Bacarisse

viza said:
What is better about this than just casting a void pointer to the desired
function pointer type?

void *foo= FOO;

( (void(*)(int)) foo )( 7 );

The conversion is not guaranteed to work.
Both are not allowed by the standard, and both work for me(tm), but are
there cases where a union works where a cast doesn't or is preferable for
some other reason?

In the worst case, a function pointer might be bigger than a void *
and while this does not mean that the conversion to void * must loose
information it very often does.

[Aside: I knew one system where every function was compiled into a
separate segment, so while all pointers were 32 bits with 16 for a
segment address and 16 for an offset, function pointers were, in
effect, smaller than object pointers since you could, if you needed
to, discard the offset.]
 
J

jameskuyper

viza said:
What is better about this than just casting a void pointer to the desired
function pointer type?

void *foo= FOO;

( (void(*)(int)) foo )( 7 );

Both are not allowed by the standard,

Your code has undefined behavior, but what does the standard say to
"disallow" the following code?:

void Foo(int);
union generic_pointer gp;

gp.pfunc = (void(*)()) Foo;
(((void(*)(int))gp.pfunc)(7);
 
K

Keith Thompson

Richard Heathfield said:
Nick Keighley said:

On the contrary, the Standard grants permission to do this (but does not
mandate it), both generally (1.7 COMPLIANCE "A conforming implementation
may have extensions (including additional library functions), provided
they do not alter the behavior of any strictly conforming program") and
explicitly (A.6.5.7 Function pointer casts "A pointer to an object or to
void may be cast to a pointer to a function, allowing data to be invoked
as a function ($3.3.4). A pointer to a function may be cast to a pointer
to an object or to void, allowing a function to be inspected or modified
(for example, by a debugger) ($3.3.4)").

Note that the second reference is non-normative.

C99 cross-refs: 4(6), with identical wording, and Annex J, 5.7(1) and (2),
again with identical wording modulo parenthesised cross-refs. (Again, the
more specific reference is non-normative.)

A diagnostic message is required, however.

Why is a diagnostic message required? What constraint is violated?
 
J

jameskuyper

Eric said:
Looks all right to me. Is it what you meant to write? (I notice
that the union-ness of gp is not used at all here; did you intend to
make a point about the pobj member or something?)

I was just writing the code that would be analogous to the code viza
presented. If you want to see the "unionness" used, just add the
following:

int i;
gp.pobj = &i;
*(int*)gp.pobj = 7;

Thus, as advertised, gp can be used to point at either an object or a
function (but not both at the same time). The implicit conversions for
void* make the pobj member easier to use than the pfunc member. Just
as with void*, you have to keep track somehow of what type the pointer
actually points at, in order to safely dereference it. Unlike void*,
you have to keep track of whether it's a function or a object pointer,
before you can compare it for equality with another "union
generic_pointer" object.
 
K

Keith Thompson

Richard Heathfield said:
Keith Thompson said:

What makes you think a diagnostic message is required?

Maybe your plans have something to do with this.

[...]
 
P

Peter Nilsson

[OT and somewhat rhetorical reply, so f-ups set to
comp.programming.]

viza said:
C++ however has _extensible_ operator overloading.

(I used to curse C++ for overloading until it was
pointed out to me that I was already using it in C!)

So the bit where it's all but required to make any
practical use of C++ didn't sway you to begin with...?

I can't think of many languages that don't have
syntactical overloading for arithmetic operators.
[Though Forth springs to mind and there are probably
hundreds I haven't realised (or know of.)]
 
M

Martien Verbruggen

Nick Keighley said:


On the contrary, the Standard grants permission to do this (but does not
mandate it), both generally (1.7 COMPLIANCE "A conforming implementation
may have extensions (including additional library functions), provided
they do not alter the behavior of any strictly conforming program") and
explicitly (A.6.5.7 Function pointer casts "A pointer to an object or to
void may be cast to a pointer to a function, allowing data to be invoked
as a function ($3.3.4). A pointer to a function may be cast to a pointer
to an object or to void, allowing a function to be inspected or modified
(for example, by a debugger) ($3.3.4)").

Note that the second reference is non-normative.

C99 cross-refs: 4(6), with identical wording, and Annex J, 5.7(1) and (2),
again with identical wording modulo parenthesised cross-refs. (Again, the
more specific reference is non-normative.)

A diagnostic message is required, however.

Why do you say that a diagnostic message is required? Can you give C&V
for that?

Martien
 
N

Nick Keighley

Nick Keighley said:


On the contrary, the Standard grants permission to do this (but does not
mandate it), both generally (1.7 COMPLIANCE "A conforming implementation
may have extensions (including additional library functions), provided
they do not alter the behavior of any strictly conforming program")

you then go on the quote from the "Common Extensions" section. Which
starts "The following extensions are widely used in amny systems, but
are
are not portable to all implementaions"

Is this a strictly conforming program?

int main (void)
{
int fortran = 1;
int asm = 2;
return 0;
}

if it is then certain common extensions will break it.

You seem to be takinh the opposite stance from the thread
that argues

void main(void)
{
return 0;
}

is "correct" (presumably for small values of correct)
 
N

Nick Keighley

Nick Keighley said:


Not necessarily. An implementation that offers fortran and asm as keywords
might nevertheless be "bright" enough to recognise such situations and
deal with them appropriately.

I think your "bright enough" compiler would be a candidate for
passing
the Turing test.

typedef long fortran

fortran int big_math_calculation (void)
{
C IT'S A LONG TIME SINCE I WROTE ANY FORTRAN

FOR I = 1 TO 100000 DO
J = 99 ** 99

RETURN J
}

so does that function return long int? It's harder to craft an asm
example. Ah!

typedef int load;

int main(void)
{
int i;
asm (load i);
return 0;
}

Hmm. asm seems to need a character string literal. That makes things
easier:-

int main(void)
{
asm ("refrog z-reg;");
}

not that taking different sides in an argument is wrong
(I'm descended from lawyers, so I would say that).
(presumably for small values of correct)

Vanishingly small, and I don't think we have a sufficiently powerful
microscope.

Oh I agree! It seemed to involve defining "correct" as "wrong"
and "mandatory" as "optional". A career in marketing seems certain.
 
B

Ben Bacarisse

Nick Keighley said:
I think your "bright enough" compiler would be a candidate for
passing
the Turing test.

You are using "the Turing test" as code for something but I am not
sure what. Do you mean that the only way to disambiguate uses of a
keyword that might also be an identifier must use AI rather than
convention parsing techniques?

If so, I disagree. It is possible to add a keyword to C that does not
interfere with it use as an identifier if the designer makes the right
language choices. I am not talking about simply picking a keyword
that is in the implementation name-space (i.e. _Fortran). It is
possible to design the syntax so that 'fortran' is a legal identifier
but also acts like a keyword in the right context. I am not sure it
is a good idea, but it is possible.

[I snipped your examples because they seemed to be using a particular
bad design as an argument against a general point.]
 
B

Ben Bacarisse

Nick Keighley said:
pretty close to, yes



yes, but we are talking about the "Common Extensions" part of the
standard. Richard Heathfield argued that it was legitimate to cast
a function pointer to an object pointer because this appeared in
Common Extensions (which *I* call Section F.5). I argue that CEs
are not allowed in a conforming compiler precisly becuase it breaks
things. asm and fortran are keywords listed in CE.

I had missed that you were assuming a particular syntax. Section J.5
talks about fortran being a "keyword" and the asm(<string literal>);
syntax. The asm syntax looks like a function call so I can't see how
it can "break things". Not unless you also say that open() or fork()
are not allowed in a conforming compiler.
are you sure.

Am I sure that it is possible? Yes (if I get to define all the terms!).
[I snipped your examples because they seemed to be using a particular
bad design as an argument against a general point.]

I thought my examples quite relevent. I think it is difficult
for fortran and asm to be both language words and identifiers.
Not the standard doesn't expect you to do it with other keywords.

We may be talking at cross purposes or at least be having a
definitional disagreement. If you make fortran a keyword in the
traditional sense then it is forbidden as an identifier. I did not
think this is what you meant because no amount of cleverness in the
compiler can alter this. The trick is to define the syntax so that
you can tell how the word is being used.
int main (int long, char *char[])
{
int int;
int return = 0;
for (int = 0; int < long; int++)
fortran();
return return;
}

Well, I won't snip it this time, but I don't see how a single example
helps make a case that to parse this requires AI-like cleverness in
the compiler.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
474,181
Messages
2,570,970
Members
47,537
Latest member
BellCorone

Latest Threads

Top