ねえ、私はこのタイプの何かを持っています
eph_t *a;
ご覧のとおり、タイプは eph_t です。Cの配列ですが、配列のサイズも配列の最後の要素もわかりません。配列内のすべての要素の値を何かに割り当てたいので、配列全体を調べる方法はありますか。
考慮すべきオプションは何ですか? 質問の内容を理解できなかった場合は、お知らせできるようにコメントしてください。
配列のサイズがわからない場合、反復処理は安全ではありません。最後の要素を超えて要素を読み取ろうとするたびに、未定義の動作が発生します。配列のサイズがわからない限り、安全にできることは何もありません。
他の人が言ったように、配列の終わりがわからない場合、配列を反復処理するのは安全ではありません。これは、多くの場合、次の方法で回避されます。
int a[10];
。演算子を使用してsizeof
、配列のサイズを決定できます。配列へのポインターを関数に渡す場合、これは機能しないことに注意してください。memset
は良い例です)。したがって、配列をパラメーターとして受け取る関数を設計している場合は、上記のパターンを使用してください。上記のパターンのいずれも使用しない関数を使用している場合は、問題をバグとしてライブラリ設計者に報告してください。
Cのポインターは単なるアドレスです。配列として使用する場合、配列の長さを (他の方法で) 把握する必要があります。
配列を扱う多くのライブラリには、配列へのポインタとそのサイズの両方を受け入れる関数があります。たとえば、qsort(3)nmemb
は、ソートされる配列base
( の最初の引数) の要素数を指定する 2 番目の引数をqsort
必要とします。
または、ポインターだけを渡す代わりに、柔軟な配列メンバー(C99) を使用して、次のような構造体へのポインターを渡す (および関連する場合は返す)ことができます。
struct eph_tuple_st {
unsigned len;
eph_t* ptrtab[];
};
柔軟な配列ptrtab
フィールドにはlen
要素があるという慣例に従います。
最後に、他の人が示唆したように、センチネル値 (つまり、null ワード) を使用して配列を終了することができます。通常、私はそれをお勧めしません (バッファ オーバーフローのリスク、実際のサイズを計算する時間の複雑さ)。
FWIW、最近の C++ にはstd::dynarray (C++2014) とstd::vectorがあり、Ocaml にはArrayモジュールがあります。より使いやすいプログラミング言語に切り替えることができます。
サイズを格納するために配列の最初の要素を予約できます
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct {
int x, y;
double z;
} eph_t;
static void temp(eph_t *a)
{
size_t n;
memcpy(&n, a - 1, sizeof(size_t)); /* get size (stored in a - 1) */
printf("Count = %zu\n", n);
}
int main(void)
{
const size_t n = 5;
eph_t a[n + 1]; /* allocate space for 1 more element */
memcpy(&a[0], &n, sizeof(size_t)); /* now the first element contains n */
temp(a + 1); /* skip first element */
return 0;
}