3

私は C# から C に来たばかりで、C# のような汎用関数を定義する方法を探していました。この投稿に出くわしましたが、コンパイルしようとすると、たくさんのエラーが発生します (「`n' はここでは宣言されていません (関数内ではありません)」、「「配列」の前の構文エラー」など)。これが私のコードです。

#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();
}

ここで何が間違っていますか?それが違いを生む場合、私はDevC ++を使用しています。

4

2 に答える 2

2

正しいバージョンは次のようになります

#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]);                                                 \
  }                                                              \
}

バージョンの問題点を要約するには:

  • n使用する前に宣言する必要があります
  • 配列境界は識別子の後に来ます
  • 配列サイズなどの意味的に正しい型はsize_t
  • C99以降のCには、forループ用のローカル変数もあります。
于 2012-10-12T21:38:50.260 に答える
0

このバリエーションを試すことができます:

#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]);\
  }\
}

これTYPE[n] arrayは、コンパイラが VLA (Variable Length Array) をサポートしていることを意味しますが、コンパイラがサポートしているかどうかはわかりません。

gccコマンドラインオプションを追加すると、-std=c99元のコードがコンパイルされます。

更新: Jens のコメントに従って修正が適用されました。

私が提案する解決策は、(OPで提案されているように)配列に含まれる型の変数へのポインタを単純に渡すことです。そうすることが、配列が関数に渡される方法です。それらは参照によって渡されます。

また、Jens は他のいくつかの警告/エラーについて言及しています。あるように:

1conio.hは標準の C インクルードではありませんstdio.h

2 配列は、配列のサイズを型ではなく変数名に追加することによって宣言されます。そうでなければならない:そうでint ia[5]はないint[5] ia

3をmain()返しますint。OP は何も返しません。

4 のプロトタイプがgetch()ありません。含めたいと思うかもしれませんcurses.h

于 2012-10-12T16:41:49.570 に答える