3

I just came to C from C# and was looking for a way to define generic functions like those in C#. I came across this post but when I tried to compile it I get a bunch of errors ("`n' undeclared here (not in a function)", " syntax error before "array" ", etc.) Here's my code:

#include<conio.h>
#include<stdlib.h>

#define MAKE_PRINTEACH(TYPE)\
void printeach_##TYPE (TYPE[n] array, int n, void(*f)(TYPE)){\
  int i;\
  for(i = 0; i < n; i++) {\
    f(array[i]);\
  }\
}

MAKE_PRINTEACH(int)
MAKE_PRINTEACH(float)

void printInt(int x)
{
     printf("got %d\n",x);
}

void printFloat(float x)
{
     printf("got %f\n",x);
}

int main()
{
    int[5] ia = {34,61,3,6,76};
    float[6] fa = {2.4,0.5,55.2,22.0,6.76,3.14159265};

    printeach_int(ia, 5, printInt);
    printeach_float(fa,6,printFloat);

    getch();
}

What am I doing wrong here? I am using DevC++ if that makes a difference.

Community
  • 1
  • 1
Zak Gambrell
  • 45
  • 1
  • 5
  • Hmm, I thought `function` would be a more appropriate tag than `functional programming`, but now I'm not sure. Feel free to roll back if you disagree. – Matt Fenwick Oct 12 '12 at 16:40
  • What is the meaning of the `n` within brackets on the second line of the macro definition? Should you perhaps omit it? – supercat Oct 12 '12 at 16:43
  • 2
    When debugging a macro like this, it's often useful to just feed your program to the C pre-processor and see what pops out. `gcc -E program.c` – Clinton Pierce Oct 12 '12 at 16:44

2 Answers2

2

A correct version would look like this

#define MAKE_PRINTEACH(TYPE)                                     \
void printeach_##TYPE (size_t n, TYPE array[n], void(*f)(TYPE)){ \
  for(size_t i = 0; i < n; i++) {                                \
    f(array[i]);                                                 \
  }                                                              \
}

to summarize what went wrong with your version:

  • n must be declared before it is used
  • the array bounds come after the identifier
  • the semantically correct type for array sizes and things like that is size_t
  • C since C99 also has local variables for for loops.
Jens Gustedt
  • 76,821
  • 6
  • 102
  • 177
0

You might try this variation:

#define MAKE_PRINTEACH(TYPE)\
void printeach_##TYPE (TYPE * array, int n, void(*f)(TYPE)){\
  int i;\
  for(i = 0; i < n; i++) {\
    f(array[i]);\
  }\
}

The TYPE[n] array implies the compiler supports VLA (Variable Length Array) and I do not know whether your compiler does.

For gcc adding the command line option -std=c99 would make the original code compile.

Update: Corrections applied as by Jens's comment.

The solution I propose is to simply pass a pointer to a variable of the type which the array (as proposed in the OP) would have contained. Doing so, is the way arrays are passed to a function. They are passed by reference.

Also Jens mentions several other warnings/errors. As there are:

1 conio.h is not a standard C include, stdio.h whould be appropriate here

2 Arrays are declared by adding the array's size to the variable name, not to the type. It has to be: int ia[5]not int[5] ia

3 main() returns int, the OP does not return anything.

4 The prototype for getch() is missing. One might like to include curses.h

alk
  • 69,737
  • 10
  • 105
  • 255
  • -1, no the original code has several errors and would not compile with `-std=c99`. You really should teach Zak what went wrong it his version, and not just how to avoid the problem. – Jens Gustedt Oct 12 '12 at 21:40
  • Thanks your correction. I should have listened to the inner voice wispering that what I was writing regarding VLAs was nonsense. @JensGustedt – alk Oct 13 '12 at 11:03