Discussion:
correct way to create dynamically function pointers
Add Reply
Hello World
2017-04-11 17:20:05 UTC
Reply
Permalink
Raw Message
Hi all,

I am learning C but I don't understand certain topics with much clarity.
I came to know that normally it is better to use dynamic memory allocation, so I tried to make a c program that will dynamically allocate memory for function pointers. I wrote this

#include <stdio.h>
#include <stdlib.h>

int sum(int a, int b);
int subt(int a, int b);
int mul(int a, int b);
int dive(int a, int b);

int (*p)(int a, int b);



int sum(int a, int b)
{
return a+b;
}

int subtract(int a, int b)
{
return a-b;
}

int mul(int a, int b)
{
return a*b;
}

int dive(int a, int b)
{
return a/b;
}

int main(void)
{
p = malloc(sizeof(p)*4);
p[0] = sum;
p[1] = subt;
p[2] = mul;
p[3] = dive;
printf("p[0](4, 6) = %d\n",(*p[0])(4, 6));
printf("p[1](4, 6) = %d\n",(*p[1])(4, 6));
printf("p[2](4, 6) = %d\n",(*p[2])(4, 6));
printf("p[3](4, 6) = %d\n",(*p[3])(4, 6));
free(p);
return 0;
}

}

However I get an error

warning: ISO C forbids assignment between function pointer and ‘void *’ [-Wpedantic]
p = malloc(sizeof(p)*4);
^

It looks like that function pointer is a different kind of pointer.
What am I missing?
Scott Lurndal
2017-04-11 17:34:19 UTC
Reply
Permalink
Raw Message
Hi all,=20
I am learning C but I don't understand certain topics with much clarity.
I came to know that normally it is better to use dynamic memory allocation,=
so I tried to make a c program that will dynamically allocate memory for f=
unction pointers. I wrote this
However I get an error
warning: ISO C forbids assignment between function pointer and =E2=80=98voi=
d *=E2=80=99 [-Wpedantic]
p =3D malloc(sizeof(p)*4);
^
ISO C forbids that because on some architectures, a function pointer
may require more bits than a void pointer contains.[*]
What am I missing?
a cast. (puts on flameproof suit).

[*] On one segmented architecture I used to use, a function pointer required 10-bytes,
whereas a data pointer was 4-bytes.
Hello World
2017-04-11 17:42:44 UTC
Reply
Permalink
Raw Message
Post by Scott Lurndal
Hi all,=20
I am learning C but I don't understand certain topics with much clarity.
I came to know that normally it is better to use dynamic memory allocation,=
so I tried to make a c program that will dynamically allocate memory for f=
unction pointers. I wrote this
However I get an error
warning: ISO C forbids assignment between function pointer and =E2=80=98voi=
d *=E2=80=99 [-Wpedantic]
p =3D malloc(sizeof(p)*4);
^
ISO C forbids that because on some architectures, a function pointer
may require more bits than a void pointer contains.[*]
What am I missing?
a cast. (puts on flameproof suit).
[*] On one segmented architecture I used to use, a function pointer required 10-bytes,
whereas a data pointer was 4-bytes.
As far as I know pointer variable have same size in an architecure.
Scott Lurndal
2017-04-11 17:48:48 UTC
Reply
Permalink
Raw Message
Post by Hello World
Post by Scott Lurndal
Hi all,=20
I am learning C but I don't understand certain topics with much clarity.
I came to know that normally it is better to use dynamic memory allocation,=
so I tried to make a c program that will dynamically allocate memory for f=
unction pointers. I wrote this
However I get an error
warning: ISO C forbids assignment between function pointer and =E2=80=98voi=
d *=E2=80=99 [-Wpedantic]
p =3D malloc(sizeof(p)*4);
^
ISO C forbids that because on some architectures, a function pointer
may require more bits than a void pointer contains.[*]
What am I missing?
a cast. (puts on flameproof suit).
[*] On one segmented architecture I used to use, a function pointer required 10-bytes,
whereas a data pointer was 4-bytes.
As far as I know pointer variable have same size in an architecure.
Well, it's clear that your knowledge base is incomplete.
Hello World
2017-04-11 17:55:37 UTC
Reply
Permalink
Raw Message
Post by Scott Lurndal
Post by Hello World
Post by Scott Lurndal
Hi all,=20
I am learning C but I don't understand certain topics with much clarity.
I came to know that normally it is better to use dynamic memory allocation,=
so I tried to make a c program that will dynamically allocate memory for f=
unction pointers. I wrote this
However I get an error
warning: ISO C forbids assignment between function pointer and =E2=80=98voi=
d *=E2=80=99 [-Wpedantic]
p =3D malloc(sizeof(p)*4);
^
ISO C forbids that because on some architectures, a function pointer
may require more bits than a void pointer contains.[*]
What am I missing?
a cast. (puts on flameproof suit).
[*] On one segmented architecture I used to use, a function pointer required 10-bytes,
whereas a data pointer was 4-bytes.
As far as I know pointer variable have same size in an architecure.
Well, it's clear that your knowledge base is incomplete.
Learn answering skills, before answering. Your answer is too obscure to give a complete picture as what you meant. No reference given to look and increase knowledge base too.
Ben Bacarisse
2017-04-11 18:06:58 UTC
Reply
Permalink
Raw Message
Post by Hello World
Post by Scott Lurndal
Hi all,=20
I am learning C but I don't understand certain topics with much clarity.
I came to know that normally it is better to use dynamic memory allocation,=
so I tried to make a c program that will dynamically allocate memory for f=
unction pointers. I wrote this
However I get an error
warning: ISO C forbids assignment between function pointer and =E2=80=98voi=
d *=E2=80=99 [-Wpedantic]
p =3D malloc(sizeof(p)*4);
^
ISO C forbids that because on some architectures, a function pointer
may require more bits than a void pointer contains.[*]
What am I missing?
a cast. (puts on flameproof suit).
[*] On one segmented architecture I used to use, a function pointer required 10-bytes,
whereas a data pointer was 4-bytes.
As far as I know pointer variable have same size in an architecure.
Please don't get distracted by this. It makes no difference how large
the pointers are -- you just have a pointer of the wrong type. See my
other reply to you.
--
Ben.
James R. Kuyper
2017-04-11 18:23:19 UTC
Reply
Permalink
Raw Message
...
Post by Hello World
Post by Scott Lurndal
[*] On one segmented architecture I used to use, a function pointer required 10-bytes,
whereas a data pointer was 4-bytes.
As far as I know pointer variable have same size in an architecure.
That depends entirely on the architecture. The standard imposes no
requirements on the size of pointers other than those implied by the
fact that "same representation" necessarily implies "same size", and the
only cases where it requires that pointers have the same representation
are the following:

"A pointer to void shall have the same representation and alignment
requirements as a pointer to a character type.48) Similarly, pointers to
qualified or unqualified versions of compatible types shall have the
same representation and alignment requirements. All pointers to
structure types shall have the same representation and alignment
requirements as each other. All pointers to union types shall have the
same representation and alignment requirements as each other. Pointers
to other types need not have the same representation or alignment
requirements." (6.2.5p28)

Real world computers with different sizes for data pointers and pointers
to code are relatively common. Computers where pointers to different
data types can have different sizes are less common, but they do exist.
The most common case involves systems where the hardware word size is
too large to be used as the byte size. On such a system, a pointer to a
word-aligned data type need only identify the starting word for the
object it points at. For data types with byte alignment, the pointer
also needs to identify which byte within a word the object starts at. On
some systems storing that extra information requires that pointers to
byte-aligned types be bigger than pointers to word-aligned types.
Ben Bacarisse
2017-04-11 18:05:44 UTC
Reply
Permalink
Raw Message
Post by Scott Lurndal
Post by Hello World
I am learning C but I don't understand certain topics with much clarity.
I came to know that normally it is better to use dynamic memory allocation,=
so I tried to make a c program that will dynamically allocate memory for f=
unction pointers. I wrote this
However I get an error
warning: ISO C forbids assignment between function pointer and =E2=80=98voi=
d *=E2=80=99 [-Wpedantic]
p =3D malloc(sizeof(p)*4);
^
ISO C forbids that because on some architectures, a function pointer
may require more bits than a void pointer contains.[*]
Post by Hello World
What am I missing?
a cast. (puts on flameproof suit).
No! The OP just needs a pointer of the right type. A pointer to a
pointer to a function is a plain object pointer pointer type and void *
can be assigned to such a thing without a cast.
--
Ben.
James R. Kuyper
2017-04-11 18:11:09 UTC
Reply
Permalink
Raw Message
...
Post by Scott Lurndal
warning: ISO C forbids assignment between function pointer and =E2=80=98voi=
d *=E2=80=99 [-Wpedantic]
p =3D malloc(sizeof(p)*4);
^
ISO C forbids that because on some architectures, a function pointer
may require more bits than a void pointer contains.[*]
It's a more fundamental problem than that: functions and objects are two
completely different types of things, and pointers to functions are
therefore fundamentally incompatible with pointers to objects.
Post by Scott Lurndal
What am I missing?
a cast. (puts on flameproof suit).
You'll need that suit when the nasal demons come to hunt you down. Where
would you find the definition of the behavior of such a cast?
6.3.2.3 contains no such definition, which is the place where I'd expect
it to be if the behavior were defined.

Furthermore, since p is a pointer to a function, once you've allocated
such memory, you'd have to fill it in with a function. Not a pointer to
a function, as in the OP's code, but an actual function. How would you
go about doing that? Hint: attempting to memcpy() a function into that
memory would fail for the same reason that the assignment above failed.
Richard Heathfield
2017-04-12 07:27:52 UTC
Reply
Permalink
Raw Message
Post by James R. Kuyper
...
Post by Scott Lurndal
warning: ISO C forbids assignment between function pointer and =E2=80=98voi=
d *=E2=80=99 [-Wpedantic]
p =3D malloc(sizeof(p)*4);
^
ISO C forbids that because on some architectures, a function pointer
may require more bits than a void pointer contains.[*]
It's a more fundamental problem than that: functions and objects are two
completely different types of things, and pointers to functions are
therefore fundamentally incompatible with pointers to objects.
Post by Scott Lurndal
What am I missing?
a cast. (puts on flameproof suit).
You'll need that suit when the nasal demons come to hunt you down. Where
would you find the definition of the behavior of such a cast?
6.3.2.3 contains no such definition, which is the place where I'd expect
it to be if the behavior were defined.
Furthermore, since p is a pointer to a function, once you've allocated
such memory, you'd have to fill it in with a function. Not a pointer to
a function, as in the OP's code, but an actual function. How would you
go about doing that? Hint: attempting to memcpy() a function into that
memory would fail for the same reason that the assignment above failed.
You and Scott have, between you, managed to make this question terribly
complicated. It was a simple question with a simple, positive answer.
(In fact, it got the same simple, positive answer more than once,
because I didn't spot Ben's reply before posting my own.

I suppose, however, that if the simple, positive answer ("yes, it CAN be
done, and yes, you're NEARLY there, and you just need to tweak THIS
bit") has been given, we might as well plough a few more furrows in ISO
9899.

There is one technical point I'd like to make in support of your claim
that functions and objects are two completely different kinds of things,
and my point is simply to draw our attention to the existence of this
well-known software engineering problem:

Objects do, but functions don't.
--
Richard Heathfield
Email: rjh at cpax dot org dot uk
"Usenet is a strange place" - dmr 29 July 1999
Sig line 4 vacant - apply within
James R. Kuyper
2017-04-12 17:31:37 UTC
Reply
Permalink
Raw Message
On 04/12/2017 03:27 AM, Richard Heathfield wrote:
...
Post by Richard Heathfield
You and Scott have, between you, managed to make this question terribly
complicated. It was a simple question with a simple, positive answer.
You know my style: my answers tend to be as complete and as accurate as
I can make them, rather than simple. Someone who succeeds in fully
understanding my answer will have learned a lot more than someone who
understands your answer - but on the other hand, they're more likely to
understand your answer than mine.

When my kids get to the point of asking me why the sky is blue, I'm
likely to end up trying to explain Rayleigh scattering in terms of
quantum mechanics to them. They may end up wishing they'd asked someone
else. :-(
Richard Heathfield
2017-04-12 22:05:30 UTC
Reply
Permalink
Raw Message
On 12/04/17 18:31, James R. Kuyper wrote:
<snip>
Post by James R. Kuyper
When my kids get to the point of asking me why the sky is blue, I'm
likely to end up trying to explain Rayleigh scattering in terms of
quantum mechanics to them. They may end up wishing they'd asked someone
else. :-(
Nah, it's because air is blue.

Cf <https://www.xkcd.com/1818/>
--
Richard Heathfield
Email: rjh at cpax dot org dot uk
"Usenet is a strange place" - dmr 29 July 1999
Sig line 4 vacant - apply within
Stefan Ram
2017-04-11 17:51:22 UTC
Reply
Permalink
Raw Message
Post by Hello World
I came to know that normally it is better to use dynamic
memory allocation, so I tried to make a c program that will
dynamically allocate memory for function pointers.
The premise that »to use dynamic memory allocation« is
"better" is wrong.

Programming usually starts from a requirement specification;
»dynamically allocate memory for function pointers« is not a
requirement specification. It's ok as an exercise, however.
Post by Hello World
return a+b;
If »dynamic memory allocation« is "better", then why not:

int * sum( int a, int b )
{ p = malloc( sizeof( int ));
if( p )*p = a + b;
return p; }

?
Post by Hello World
What am I missing?
For one thing, you declare p as a function pointer,
Post by Hello World
int (*p)(int a, int b);
but then use it like an array.
Post by Hello World
p[0] = sum;
Ben Bacarisse
2017-04-11 18:03:47 UTC
Reply
Permalink
Raw Message
Post by Hello World
I am learning C but I don't understand certain topics with much clarity.
I came to know that normally it is better to use dynamic memory
allocation, so I tried to make a c program that will dynamically
allocate memory for function pointers. I wrote this
#include <stdio.h>
#include <stdlib.h>
int sum(int a, int b);
int subt(int a, int b);
int mul(int a, int b);
int dive(int a, int b);
You don't define some of these. In fact you don't need the declarations
at all since you refer to the function only after their definitions.
Post by Hello World
int (*p)(int a, int b);
Eek! A "global variable"! No!
Post by Hello World
int sum(int a, int b)
{
return a+b;
}
int subtract(int a, int b)
{
return a-b;
}
int mul(int a, int b)
{
return a*b;
}
int dive(int a, int b)
{
return a/b;
}
int main(void)
{
p = malloc(sizeof(p)*4);
p[0] = sum;
p[1] = subt;
p[2] = mul;
p[3] = dive;
printf("p[0](4, 6) = %d\n",(*p[0])(4, 6));
printf("p[1](4, 6) = %d\n",(*p[1])(4, 6));
printf("p[2](4, 6) = %d\n",(*p[2])(4, 6));
printf("p[3](4, 6) = %d\n",(*p[3])(4, 6));
free(p);
return 0;
}
}
However I get an error
warning: ISO C forbids assignment between function pointer and ‘void *’ [-Wpedantic]
p = malloc(sizeof(p)*4);
^
It looks like that function pointer is a different kind of pointer.
What am I missing?
When you allocate space of something of type T you get back a pointer
that you store in a variable of type T *. E.g. you allocate ten ints
and you put the result into a int *:

int *ints = malloc(10 * sizeof *ints);

The same goes for 4 function pointers. You need to take the result and
put it a variable of type pointer to function pointer.

These things are simpler with a typedef:

typedef int operation(int, int);

Now you can make a pointer to a pointer to an "operation" function like
this:

operation **oplist = malloc(4 * sizeof *oplist);

Some people make the typedef a pointer-to-function type, but I don't
like to hide pointer types behind typedefs and, what's more, this way
you get to declare the functions more easily too:

operation add, subtract, multiply, divide;
--
Ben.
James R. Kuyper
2017-04-11 18:05:27 UTC
Reply
Permalink
Raw Message
Post by Hello World
Hi all,
I am learning C but I don't understand certain topics with much clarity.
I came to know that normally it is better to use dynamic memory
allocation, ...
That's not really the case. A C object can have any one of four
different storage durations: static, thread, automatic, and dynamic.
Each storage duration had it's own advantages and disadvantages. You
need to learn what those advantages and disadvantages are, and decide
for each object which storage duration it should have. Assuming that any
one storage duration is always best is a mistake that you should avoid
making.

In particular, one disadvantage of dynamic storage duration is that it
can be significantly slower than the other types. Another disadvantage
is that you need to store a pointer to the dynamically allocated memory.
For both of those reasons, it seldom makes sense to dynamically allocate
small amounts of memory. I wouldn't ordinarily use it store anything as
small as four function pointers.
Post by Hello World
... so I tried to make a c program that will dynamically
allocate memory for function pointers. I wrote this
#include <stdio.h>
#include <stdlib.h>
int sum(int a, int b);
int subt(int a, int b);
int mul(int a, int b);
int dive(int a, int b);
int (*p)(int a, int b);
You're trying to create a dynamically allocated array of pointers to
functions. That declares p to be a single pointer to a function. What
you need is:

int (**p)(int a, int b);
Post by Hello World
int sum(int a, int b)
{
return a+b;
}
int subtract(int a, int b)
{
return a-b;
}
int mul(int a, int b)
{
return a*b;
}
int dive(int a, int b)
{
return a/b;
}
int main(void)
{
p = malloc(sizeof(p)*4);
Attempting to assign a pointer to void to an object containing a pointer
to a function type is a constraint violation - such an assignment
doesn't match any of the permitted options listed in 6.5.16.1p1. You
can't get around this problem by casting the pointer into a pointer to a
function type, because such a conversion has undefined behavior, because
the standard doesn't define the behavior of such a conversion. The
definition (if there were any) would be expected to appear in 6.3.2.3,
and there is no such definition (except in the special case where the
pointer being converted is a null pointer - in which case p would
contain a null pointer to a function. However, if malloc() returns a
null pointer, no memory has been allocated).

With your original definition, p is a pointer to a function type, and
the above assignment expression is therefore a constraint violation.
With my revised definition, p is a pointer to an object type. The object
it points at is a pointer to a function, but p itself can safely be used
to store the result returned by a call to malloc. However, the call
should be done differently than you did above:

p = malloc(4 * sizeof *p);

I changed the order around to avoid any confusion between the two
different uses of *. malloc(sizeof *p * 4) is perfectly legal, and has
exactly the same meaning, but is more confusing.

malloc() can fail. If it does, it will return a null pointer. If you
make any attempt to dereference a null pointer, the behavior is
undefined. Therefore, every time you call malloc(), you should check for
the possibility it failed - if it did, you need to skip any code which
attempts to access the memory that was not, in fact, allocated:

if(p)
{
Post by Hello World
p[0] = sum;
p[1] = subt;
p[2] = mul;
p[3] = dive;
printf("p[0](4, 6) = %d\n",(*p[0])(4, 6));
printf("p[1](4, 6) = %d\n",(*p[1])(4, 6));
printf("p[2](4, 6) = %d\n",(*p[2])(4, 6));
printf("p[3](4, 6) = %d\n",(*p[3])(4, 6));
free(p);
}

You could move the free() outside the if()-statement, if you wished. One
of the few things you can safely do with a null pointer is pass it to
free() - where it will do absolutely nothing. However, there's no point
in calling free() unless the malloc() call succeeded, so you should
generally put the free inside the if() statement.
Post by Hello World
return 0;
}
}
However I get an error
warning: ISO C forbids assignment between function pointer and ‘void *’ [-Wpedantic]
p = malloc(sizeof(p)*4);
^
It looks like that function pointer is a different kind of pointer.
That is exactly correct.
Post by Hello World
What am I missing?
One level of indirection: you needed a pointer to a pointer to a
function, not just a pointer to a function.
Jorgen Grahn
2017-04-15 10:19:16 UTC
Reply
Permalink
Raw Message
Post by James R. Kuyper
Post by Hello World
Hi all,
I am learning C but I don't understand certain topics with much clarity.
I came to know that normally it is better to use dynamic memory
allocation, ...
That's not really the case. A C object can have any one of four
different storage durations: static, thread, automatic, and dynamic.
Each storage duration had it's own advantages and disadvantages. You
need to learn what those advantages and disadvantages are, and decide
for each object which storage duration it should have. Assuming that any
one storage duration is always best is a mistake that you should avoid
making.
In particular, one disadvantage of dynamic storage duration is that it
can be significantly slower than the other types. Another disadvantage
is that you need to store a pointer to the dynamically allocated memory.
For both of those reasons, it seldom makes sense to dynamically allocate
small amounts of memory. I wouldn't ordinarily use it store anything as
small as four function pointers.
The worst part about dynamic allocation is IMO the bugs you'll
introduce if you don't plan very carefully: memory leaks, crashes,
use-after-free ... My rule is "when I have to use it, I use it, not
otherwise".

/Jorgen
--
// Jorgen Grahn <grahn@ Oo o. . .
\X/ snipabacken.se> O o .
a***@gmail.com
2017-04-15 12:09:37 UTC
Reply
Permalink
Raw Message
Dinamic allocation it is all but static allocation;
When someone write
f(){int x;...
That x even if not call malloc it is a "dynamically allocated" object
because it not has a fixed address
in time...
Barry Schwarz
2017-04-11 22:13:44 UTC
Reply
Permalink
Raw Message
On Tue, 11 Apr 2017 10:20:05 -0700 (PDT), Hello World
Post by Hello World
Hi all,
I am learning C but I don't understand certain topics with much clarity.
I came to know that normally it is better to use dynamic memory allocation, so I tried to make a c program that will dynamically allocate memory for function pointers. I wrote this
It's not what you don't know that hurts you; it's what you know that
ain't so.
--
Remove del for email
Richard Heathfield
2017-04-12 07:28:21 UTC
Reply
Permalink
Raw Message
Post by Barry Schwarz
On Tue, 11 Apr 2017 10:20:05 -0700 (PDT), Hello World
Post by Hello World
Hi all,
I am learning C but I don't understand certain topics with much clarity.
I came to know that normally it is better to use dynamic memory allocation, so I tried to make a c program that will dynamically allocate memory for function pointers. I wrote this
It's not what you don't know that hurts you; it's what you know that
ain't so.
What you don't know can be pretty damn deadly too.
--
Richard Heathfield
Email: rjh at cpax dot org dot uk
"Usenet is a strange place" - dmr 29 July 1999
Sig line 4 vacant - apply within
Richard Heathfield
2017-04-12 07:19:00 UTC
Reply
Permalink
Raw Message
Post by Hello World
Hi all,
I am learning C but I don't understand certain topics with much
clarity. I came to know that normally it is better to use dynamic
memory allocation, so I tried to make a c program that will
dynamically allocate memory for function pointers. I wrote this
Okay, so presumably you effectively want an array of function pointers.
(Otherwise, why bother with dynamic allocation?)
Post by Hello World
#include <stdio.h>
#include <stdlib.h>
int sum(int a, int b);
int subt(int a, int b);
int mul(int a, int b);
int dive(int a, int b);
int (*p)(int a, int b);
I'm going to use a typedef here, just to keep things tidy (and later on,
I'll take it out again):

typedef int ft_arithmetic(int, int);

This means: "ft_arithmetic is now a synonym for the /type/ of a function
that takes two ints and returns int".

We could, in theory, now do this:

ft_arithmetic sum, subt, mul, dive;

but of course we're not going to.

The other things I'm going to do are:

* remove p from file scope. It has no business being there;
* fix p's type;
* fix the malloc argument, which is broken.
Post by Hello World
int sum(int a, int b) { return a+b; }
(One-lined only for Usenet brevity, not out of any kind of stylistic
recommendation!)
Post by Hello World
int subtract(int a, int b) { return a-b; }
You prototyped this as 'subt', and you identify it by 'subt' in main(),
so I presume you meant 'subt', not 'subtract'.
Post by Hello World
int mul(int a, int b) { return a*b; }
int dive(int a, int b) { return a/b; }
int main(void)
{
p = malloc(sizeof(p)*4);
Okay, there are several problems here. First, p has the wrong type, and
secondly, the allocation is wrong.

Note that we could simply write:

ft_arithmetic *p[4] = { sum, subt, mul, dive };

But of course you want /dynamic/ allocation. So we want:

ft_arithmetic **p = malloc(4 * sizeof *p);

Translation: p is a pointer. To what /type/ does it point? Let's analogise:

char * ............ points to char
char ** ........... points to char *
int * ............. points to int
int ** ............ points to int *
ft_arithmetic * ... points to ft_arithmetic
ft_arithmetic ** .. points to ft_arithmetic *

So p is a pointer, and the kinds of things it points to are themselves
pointers (function pointers).

sizeof *p therefore calculates the number of bytes we need for storing a
pointer to a function of type int(int, int), and 4 * sizeof *p therefore
gives us the number of bytes we need for storing four such pointers.

The rest of your code was fine.

Here is the code with the typedef in place:

#include <stdio.h>
#include <stdlib.h>

int sum(int a, int b);
int subt(int a, int b);
int mul(int a, int b);
int dive(int a, int b);

typedef int ft_arithmetic(int, int);

int sum(int a, int b) { return a+b; }
int subt(int a, int b) { return a-b; }
int mul(int a, int b) { return a*b; }
int dive(int a, int b) { return a/b; }

int main(void)
{
ft_arithmetic **p = malloc(4 * sizeof *p);
if(p != NULL)
{
p[0] = sum;
p[1] = subt;
p[2] = mul;
p[3] = dive;
printf("p[0](4, 6) = %d\n",(*p[0])(4, 6));
printf("p[1](4, 6) = %d\n",(*p[1])(4, 6));
printf("p[2](4, 6) = %d\n",(*p[2])(4, 6));
printf("p[3](4, 6) = %d\n",(*p[3])(4, 6));
free(p);
}
return 0;
}

And here it is again, without the typedef, in case you're the kind of
person who doesn't like typedefs:

#include <stdio.h>
#include <stdlib.h>

int sum(int a, int b);
int subt(int a, int b);
int mul(int a, int b);
int dive(int a, int b);

int sum(int a, int b) { return a+b; }
int subt(int a, int b) { return a-b; }
int mul(int a, int b) { return a*b; }
int dive(int a, int b) { return a/b; }

int main(void)
{
int (**p)(int, int) = malloc(4 * sizeof *p);
if(p != NULL)
{
p[0] = sum;
p[1] = subt;
p[2] = mul;
p[3] = dive;
printf("p[0](4, 6) = %d\n",(*p[0])(4, 6));
printf("p[1](4, 6) = %d\n",(*p[1])(4, 6));
printf("p[2](4, 6) = %d\n",(*p[2])(4, 6));
printf("p[3](4, 6) = %d\n",(*p[3])(4, 6));
free(p);
}
return 0;
}
--
Richard Heathfield
Email: rjh at cpax dot org dot uk
"Usenet is a strange place" - dmr 29 July 1999
Sig line 4 vacant - apply within
Spiros Bousbouras
2017-04-12 21:17:26 UTC
Reply
Permalink
Raw Message
On Wed, 12 Apr 2017 08:19:00 +0100
Post by Hello World
#include <stdio.h>
#include <stdlib.h>
int sum(int a, int b);
int subt(int a, int b);
int mul(int a, int b);
int dive(int a, int b);
typedef int ft_arithmetic(int, int);
int sum(int a, int b) { return a+b; }
int subt(int a, int b) { return a-b; }
int mul(int a, int b) { return a*b; }
int dive(int a, int b) { return a/b; }
int main(void)
{
ft_arithmetic **p = malloc(4 * sizeof *p);
if(p != NULL)
{
p[0] = sum;
p[1] = subt;
p[2] = mul;
p[3] = dive;
printf("p[0](4, 6) = %d\n",(*p[0])(4, 6));
Or more simply
printf("p[0](4, 6) = %d\n",p[0](4, 6));

which actually agrees with the message printed and that's already true
in the OP's code. Same for the other 3 calls.
Post by Hello World
printf("p[1](4, 6) = %d\n",(*p[1])(4, 6));
printf("p[2](4, 6) = %d\n",(*p[2])(4, 6));
printf("p[3](4, 6) = %d\n",(*p[3])(4, 6));
free(p);
}
return 0;
}
Richard Heathfield
2017-04-12 22:11:13 UTC
Reply
Permalink
Raw Message
Post by Spiros Bousbouras
On Wed, 12 Apr 2017 08:19:00 +0100
Post by Hello World
#include <stdio.h>
#include <stdlib.h>
int sum(int a, int b);
int subt(int a, int b);
int mul(int a, int b);
int dive(int a, int b);
typedef int ft_arithmetic(int, int);
int sum(int a, int b) { return a+b; }
int subt(int a, int b) { return a-b; }
int mul(int a, int b) { return a*b; }
int dive(int a, int b) { return a/b; }
int main(void)
{
ft_arithmetic **p = malloc(4 * sizeof *p);
if(p != NULL)
{
p[0] = sum;
p[1] = subt;
p[2] = mul;
p[3] = dive;
printf("p[0](4, 6) = %d\n",(*p[0])(4, 6));
Or more simply
printf("p[0](4, 6) = %d\n",p[0](4, 6));
I disagree that it's necessarily simpler. It's /shorter/, yes.

But (*p[0]) tells us something useful - i.e. it reminds us that p[0] is
a pointer, not a function. Now, okay, I realise that p[0] can't be the
name of a function! Nevertheless, in the general case I prefer to use
parentheses (*p)() rather than p() when a function pointer is being
used, as a little reminder that there's no point in going looking for a
function p.

(And yes, just to reiterate, I do realise that nobody in their right
mind is going to try to find a function by the name p[0]. So I find your
point to be more persuasive in this case than I would in the general case.)
Post by Spiros Bousbouras
which actually agrees with the message printed and that's already true
in the OP's code. Same for the other 3 calls.
Post by Hello World
printf("p[1](4, 6) = %d\n",(*p[1])(4, 6));
printf("p[2](4, 6) = %d\n",(*p[2])(4, 6));
printf("p[3](4, 6) = %d\n",(*p[3])(4, 6));
free(p);
}
return 0;
}
While we're at it, why not:

for(i = 0; i < 4; i++)
{
printf("p[%d](4, 6) = %d\n", i, (*p[i])(4, 6));
}
--
Richard Heathfield
Email: rjh at cpax dot org dot uk
"Usenet is a strange place" - dmr 29 July 1999
Sig line 4 vacant - apply within
Keith Thompson
2017-04-12 23:36:37 UTC
Reply
Permalink
Raw Message
Post by Richard Heathfield
Post by Spiros Bousbouras
On Wed, 12 Apr 2017 08:19:00 +0100
[...]
Post by Richard Heathfield
Post by Spiros Bousbouras
Post by Hello World
printf("p[0](4, 6) = %d\n",(*p[0])(4, 6));
Or more simply
printf("p[0](4, 6) = %d\n",p[0](4, 6));
I disagree that it's necessarily simpler. It's /shorter/, yes.
In any case, it would be nice for the expression in the format string to
match the function call.
Post by Richard Heathfield
But (*p[0]) tells us something useful - i.e. it reminds us that p[0] is
a pointer, not a function. Now, okay, I realise that p[0] can't be the
name of a function! Nevertheless, in the general case I prefer to use
parentheses (*p)() rather than p() when a function pointer is being
used, as a little reminder that there's no point in going looking for a
function p.
I agree that it's a useful reminder. On the other hand, the prefix to a
function call is *always* a expression of pointer-to-function type, so
if one were being deliberately perverse, one could cause great confusion
by inverting the convention:

void func(void) {
/* ... */
}

void (*funcptr)(void) = func;

int main(void) {
(*func)();
funcptr();
}

Not that I'd ever doing such a thing, of course.
--
Keith Thompson (The_Other_Keith) kst-***@mib.org <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"
John Bode
2017-04-12 17:04:50 UTC
Reply
Permalink
Raw Message
Post by Hello World
Hi all,
I am learning C but I don't understand certain topics with much clarity.
I came to know that normally it is better to use dynamic memory allocation, so I tried to make a c program that will dynamically allocate memory for function pointers. I wrote this
#include <stdio.h>
#include <stdlib.h>
int sum(int a, int b);
int subt(int a, int b);
int mul(int a, int b);
int dive(int a, int b);
int (*p)(int a, int b);
int sum(int a, int b)
{
return a+b;
}
int subtract(int a, int b)
{
return a-b;
}
int mul(int a, int b)
{
return a*b;
}
int dive(int a, int b)
{
return a/b;
}
int main(void)
{
p = malloc(sizeof(p)*4);
p[0] = sum;
p[1] = subt;
p[2] = mul;
p[3] = dive;
printf("p[0](4, 6) = %d\n",(*p[0])(4, 6));
printf("p[1](4, 6) = %d\n",(*p[1])(4, 6));
printf("p[2](4, 6) = %d\n",(*p[2])(4, 6));
printf("p[3](4, 6) = %d\n",(*p[3])(4, 6));
free(p);
return 0;
}
}
However I get an error
warning: ISO C forbids assignment between function pointer and ‘void *’ [-Wpedantic]
p = malloc(sizeof(p)*4);
^
It looks like that function pointer is a different kind of pointer.
What am I missing?
Let's start from the beginning. If you want to dynamically allocate an
N-element array of any type T, you'd write:

T *p = malloc( N * sizeof *p );

or

T *p = NULL;
...
p = malloc( N * sizeof *p );

After this, each p[i] contains a value of type T.

Now, let's replace T with a pointer type, P * - you want to allocate an
N-element array of *pointers* to P:

P **p = malloc( N * sizeof *p );

or

P **p = NULL;
...
p = malloc( N * sizeof *p );

After this, each p[i] contains a value of type P *, and the expression
*p[i] has type P. Basically, you've added an extra level of indirection
on p.

Now, replace P * with the function pointer type int (*)(int, int):

int (**p)(int, int) = malloc( N * sizeof *p );

or

int (**p)(int, int) = NULL;
...
p = malloc( N * sizeof *p );

After this, each p[i] contains a value of type int (*)(int, int).

So, basically, you were just missing one level of indirection on your
declaration of p.
Ben Bacarisse
2017-04-12 18:28:06 UTC
Reply
Permalink
Raw Message
John Bode <***@gmail.com> writes:
<snip>
Post by John Bode
Let's start from the beginning. If you want to dynamically allocate an
T *p = malloc( N * sizeof *p );
or
T *p = NULL;
...
p = malloc( N * sizeof *p );
After this, each p[i] contains a value of type T.
s/contains/can contain/

After the malloc call each p[i] has indeterminate value. That value
can't be used in any way. All you can do is use p[i] as somewhere to
put a value of type T
Post by John Bode
Now, let's replace T with a pointer type, P * - you want to allocate an
P **p = malloc( N * sizeof *p );
or
P **p = NULL;
...
p = malloc( N * sizeof *p );
After this, each p[i] contains a value of type P *,
Same here. True only once you've put something determinate in p[i].

<snip>
--
Ben.
Tim Rentsch
2017-04-17 12:50:04 UTC
Reply
Permalink
Raw Message
Post by John Bode
[...] I tried to make a c program that will dynamically
allocate memory for function pointers. I wrote this
[...]
int (*p)(int a, int b);
[...]
int main(void)
{
p = malloc(sizeof(p)*4);
[...]
}
However I get an error [...]
It looks like that function pointer is a different kind of pointer.
What am I missing?
Let's start from the beginning. If you want to dynamically allocate an
T *p = malloc( N * sizeof *p );
or
T *p = NULL;
...
p = malloc( N * sizeof *p );
After this, each p[i] contains a value of type T.
Now, let's replace T with a pointer type, P * [..elaborate on this..]
Excellent explanation. I thought this reply the best of the ones
I saw.
Post by John Bode
So, basically, you were just missing one level of indirection on your
declaration of p.
One suggestion: here it would have been good to point out the
OP's code that incorrectly follows the malloc() pattern

[from OP] p = malloc(sizeof(p)*4);

and give again the correction for that, especially since if this
line had been written

p = malloc(sizeof(*p)*4);

the resulting error message might have been enough for OP
to fix the problem without further help.

Loading...