2016-08-17 6 views
1

ETAを渡す:これは、malloc関数()、またはメモリの割り当てに関するものではありませんように、それは、パラメータとしてタイプを渡すことについてです簡単な例。をパラメータとしてタイプ

これは愚かな質問かもしれません、またはおそらく私は何かが不足しています。

いくつかのメモリを割り当てる単純な関数を書きたいとしましょう。特定の種類のメモリではなく、より柔軟なものを割り当てることを考えてみましょう。

同様に、1,000個の文字が割り当てられて返されたかったとします。だから私はこのように呼び出すことができる関数をしたいと思います:

ptr = getMem(char, 1000); 

実際の型をパラメータとして使用すると便利です。

は今、私はのva_argのようなマクロは()これを行うことができます知っている:

fprintf(stdout, "%s\n", va_arg(l, char)); 

だから私はそれがすべてかなり曖昧だし、そこに少し見えました。私はこれを見つけた:

type va_arg(va_list ap, type) 

パラメータ

ap − This is the object of type va_list with information about the additional arguments and their retrieval state. This object should be initialized by an initial call to va_start before the first call to va_arg. 

type − This is a type name. This type name is used as the type of the expression, this macro expands to. 

あなたが最初のパラメータのタイプはva_list、 が、2番目のパラメータとして定義されているクリアリー見ることができ、私が興味を持っています1 in - は単にtypeと指定されています。

だから、それはバグに私を始め、私はこのようなお尻のコードをいじりてきた:

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

void *getMem(type, int size) { 
    return malloc(sizeof(type) * size); 
} 

int main(void) 
{ 
    void *mem; 

    mem = getMem(1000, char); 

    if (mem == NULL) { 
     perror("malloc()"); 
     exit(EXIT_FAILURE); 
    } 

    fprintf(stdout, "Memory allocated successfully!\n"); 
    free(mem); 

    exit(EXIT_SUCCESS); 
} 

私の周りスニッフィングしてきたこれを理解しようとしているファイルを含むが、無駄に、そこにあります私はこれを行うことができますか?

申し訳ありませんが少し曖昧または無意味ですが、もしva_arg()がそれを行うことができれば、私もできるはずです。

多くの義務があります。

+1

プリプロセッサマクロを使用する必要があります。例えば、 '#define getMem(type、size)malloc((size)* sizeof(type))' –

+0

あなたの意見は分かりましたが、私はそれのためのより多くの使用があると確信しています。 – Nunchy

+1

"ある種類のメモリではなく、もっと柔軟なものを割り当てる単純な関数を書くとしましょう。" - あなたは 'malloc'のようなものを意味しますか? – Olaf

答えて

2

CPPマクロでこれを行います。

#define getMem(type, size) \ 
    malloc(sizeof(type) * size) 

をしかし、個人的に、私はこれを好む:

#define getMemOf(ptr, size) \ 
    ptr = malloc(sizeof(*ptr) * size) 

// invoke with: 
    getMemOf(ptr, 1000); 
+1

これは、LHSポインタのオブジェクトを使用してサイズを計算する一般的な推奨事項に反しています。そしてそれは多くの入力を惜しまない。 – Olaf

+1

まさに私が探していたものです。ちょうど反復するために、私の最初の例は私の質問を説明するための手段でした。私はいくつかのmalloc()ラッパーを書くためにこれを使いたくない。とても有難い。 – Nunchy

+0

マクロで代入を行うと、多くの情報が隠され、読みにくく理解しにくいコードになります。まあ、一般的にマクロはそれをする傾向がありますが、割り当ては本当に悪いIMOです。 –

0

malloc()は、ちょうどサイズうまく動作するタイプを知る必要はありません。タイプの。

サイズ計算でオーバーフローが発生しないことを保証したい場合は、チェックを行うことができます。

void *getMem(size_t element_count, size_t type_size) { 
    if (element_count > SIZE_MAX/type_size) return NULL; 
    return malloc(element_count * size); 
} 

// usage example 
size_t element_count, 
void * p = getMem(element_count, sizeof (char)); 

1は、ゼロ編メモリ、簡単な使用を希望する場合calloc()

// usage example 
size_t element_count, 
void * p = calloc(element_count, sizeof (char)); 

は、そのコードがvoid *ポインターを使用して個別にcharのような形を表現しないことをお勧めします。代わりに、非voidタイプのポインタを宣言してください。

#define ALLOCATE_ASSIGN(addr_ptr, count) (*(addr_ptr)=malloc(sizeof **(addr_ptr) * count)) 

some_type *mem; 
ALLOCATE_ASSIGN(&mem, element_count); 
+0

真剣に:どのような利点がありますか? (私はエラーチェックを理解することができましたが、これは?) – Olaf

0

とにかくsizeofでこれを行うことになります。私はVisual Studioでこれをチェックしました。マイクロソフトでは(いくつかの定義を超えて)それを定義しています。

#define _INTSIZEOF(n) ((sizeof(n) + sizeof(int) - 1) & ~(sizeof(int) - 1)) 
#define _crt_va_arg(ap,t) (*(t *)((ap += _INTSIZEOF(t)) - _INTSIZEOF(t))) 
#define va_arg _crt_va_arg 

これらはvadefs.hで見つけることができます。長い話を簡単に言えば、あなたはどこかでsizeofを使用することから離れるつもりはないので、最もシンプルなところでそれをやってください。個人的には、サイズの代わりにgetMemにサイズを渡すだけで、長い目で見ればもっと頭がおかしくなりません。

+0

私は入力を感謝します。malloc()についてではなく、パラメータとしての型の使用についてです。とても感謝しております。 – Nunchy

2

_Generic C99 C11はOPの必要性に近いものを提供するかもしれない。

例:コードでは、共通整数型の最大値を割り当てたいとします。

#define integer_max(X) _Generic((X), \ 
    unsigned long long: ULLONG_MAX, \ 
    long long: LLONG_MAX, \ 
    unsigned long: ULONG_MAX, \ 
    long: LONG_MAX, \ 
    unsigned: UINT_MAX, \ 
    int: INT_MAX, \ 
    unsigned short: USHRT_MAX, \ 
    short: SHRT_MAX, \ 
    unsigned char: UCHAR_MAX, \ 
    signed char: SCHAR_MAX, \ 
    char: CHAR_MAX, \ 
    _Bool: 1, \ 
    default: 1/0 \ 
) 

    // Here the _type_ of `x` is used by integer_max(), not its value. 
    some_integer_type x = integer_max(x); 
+0

Eh ... C11、そうですか? C99でそれを見つけることができません。 –

+0

@Daniel Jour同意、回答が修正されました。 – chux

関連する問題