0

I'm new in C programming and I try to create a struct containing a char and a function pointer, and that is the problem.

I want to change that code:

switch (flag) {
    case 'd':
    case 'i':
    return (my_put_nbr(va_arg(ap, int)));
    case 'p':
    return (my_putstr("0x") + my_l_base_changer(va_arg(ap, char *),
    16));
    case 'u':
    return (my_put_unbr(va_arg(ap, unsigned int)));
    case 'b':
    return (my_u_base_changer(va_arg(ap, unsigned int), 2, 0));
    case 'o':
    return (my_u_base_changer(va_arg(ap, unsigned int), 8, 0));
    case 'x':
    return (my_u_base_changer(va_arg(ap, unsigned int), 16, 0));
    case 'X':
    return (my_u_base_changer(va_arg(ap, unsigned int), 16, 1));
    default:
    return (0);
}

in that kind of code:

typedef struct fptr
{
   char op;
   int (*ptr)(va_list);
} fptr;

fptr  fptrs[]=
{
   { 's', ft_print_nb_spec },
   { 'S', ft_print_nb_up },
   { 0, NULL }
};
  int i = 0;
  while (fptrs[i++].op != flag && fptrs[i].op != 0);
  if (fptrs[i].op != 0)
  {
     fptrs[i].ptr();
  } 

And my struct contain a function pointer to functions who get differents prototypes

My struct is like that :

typedef struct action {
    char flag;
    void *function;
} action;

And my code who bug like that :

action registers[] = {
    { 'd', (int *)(*my_put_nbr)(int) },
    { 'i', (int)(*my_put_nbr)(va_arg(ap, int)) },
    { 'p', (int)(*my_print_ptr)(va_list ap) },
    { 'u', (int)(*my_put_unbr)(va_arg(ap, unsigned int)) },
    { 'b', (int)(*my_u_base_changer)(va_arg(ap, unsigned int), 2, 0) },
    { 'o', (int)(*my_u_base_changer)(va_arg(ap, unsigned int), 8, 0) },
    { 'x', (int)(*my_u_base_changer)(va_arg(ap, unsigned int), 8, 0) },
    { 'X', (int)(*my_u_base_changer)(va_arg(ap, unsigned int), 8, 1) },
    { 0, NULL }
};

And when I run gcc got that:

flag_nbr.c:13:28: error: expected expression before ‘int’
{ 'd', (int)(my_put_nbr)(int) },
                         ^~~
flag_nbr.c:13:28: error: missing initializer for field ‘function’ of ‘printf_action {aka struct <anonymous>}’ [-Werror=missing-field-initializers]
In file included from flag_nbr.c:8:0:
../include/my.h:21:8: note: ‘function’ declared here
void *function;
      ^~~~~~~~
flag_nbr.c:14:10: error: initialization makes pointer from integer without a cast [-Werror=int-conversion]
{ 'i', (int)(my_put_nbr)(va_arg(ap, int)) },
        ^

And I don't understand that error...

  • 6
    `action *registers[]` --> `action registers[]` – dbush Nov 17 '17 at 15:42
  • What you have as function pointers actually look more like function calls. When assigning a function pointer, you only specify the name of the function. Perhaps you should explain exactly what you're trying to accomplish by doing this. – dbush Nov 17 '17 at 16:08
  • I want a list of structs that contains a flag and the pointer to the function related to the flag, so with that use I want to "emule" a switch case or a forest of if, with only ONE while and ONE if, like that: int i = -1; while (fptrs[++i].op != flag && fptrs[i].op != 0); if (fptrs[i].op != 0) { fptrs[i].ptr(); } – Pierre MARTY Nov 17 '17 at 16:13
  • You can't call a function through a `void *`. You need to know exactly what the function signature is to call it, and you need to pass it parameters. You're better of using a `switch` statement to determine what to call and how. – dbush Nov 17 '17 at 16:17
  • What you have currently is clear and concise. I would recommend leaving it as without trying to overcomplicate things with function pointers. – dbush Nov 17 '17 at 16:37
  • By doing that I'd want to understand how the function pointers works ^^ And overall function pointers permites to get a more maintainable code – Pierre MARTY Nov 17 '17 at 17:06

2 Answers2

2

When in doubt, check the data types!!

You define the variable as an array of pointers to the action type.

What you pass in the initializers are the brace enclosed list which is certainly no match for a pointer to the action type.

In other words, you try to pass a brace enclosed list while a pointer was expected. Now, an initializer for a pointer is supposed to be a singular value (or scalar, as you may call it), so a brace enclosure is not MANDATORY.

While this is perfectly valid, most of the times, this may be caused by an issue where you write something you did not intend to write (example: your case!!) and thus, gcc produces a warning for this.

You may want to change your array type to hold structures of type action, not pointers to them.

Sourav Ghosh
  • 133,132
  • 16
  • 183
  • 261
0

You're using typedef to give a name to structure which already has the same name,check that. This may not be the main cause.

Prawin
  • 59
  • 5