1

ねえ、私はこのタイプの何かを持っています

eph_t *a;

ご覧のとおり、タイプは eph_t です。Cの配列ですが、配列のサイズも配列の最後の要素もわかりません。配列内のすべての要素の値を何かに割り当てたいので、配列全体を調べる方法はありますか。

考慮すべきオプションは何ですか? 質問の内容を理解できなかった場合は、お知らせできるようにコメントしてください。

4

4 に答える 4

7

配列のサイズがわからない場合、反復処理は安全ではありません。最後の要素を超えて要素を読み取ろうとするたびに、未定義の動作が発生します。配列のサイズがわからない限り、安全にできることは何もありません。

于 2013-08-28T10:26:34.017 に答える
5

他の人が言ったように、配列の終わりがわからない場合、配列を反復処理するのは安全ではありません。これは、多くの場合、次の方法で回避されます。

  1. たとえば、配列宣言( )にアクセスできる場合int a[10];。演算子を使用してsizeof、配列のサイズを決定できます。配列へのポインターを関数に渡す場合、これは機能しないことに注意してください。
  2. 配列を使用する関数は、多くの場合、関数への追加パラメーターとして直接サイズまたはサイズを推測する何らかの方法を取ります (memsetは良い例です)。
  3. 配列には、それを超えて反復できないことを意味する場合に、特別なターミネーター要素 (通常は最後に NULL または 0 要素) が含まれる場合があります (C 文字列が良い例です)。

したがって、配列をパラメーターとして受け取る関数を設計している場合は、上記のパターンを使用してください。上記のパターンのいずれも使用しない関数を使用している場合は、問題をバグとしてライブラリ設計者に報告してください。

于 2013-08-28T10:37:47.617 に答える
1

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モジュールがあります。より使いやすいプログラミング言語に切り替えることができます。

于 2013-08-28T10:26:41.173 に答える
1

サイズを格納するために配列の最初の要素を予約できます

#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;
}
于 2013-08-28T12:17:46.540 に答える