0

Cでは、戻り値の型を配列にすることはできませんか? オペレーティング システムのコースでポインターについて学び始めたところ、2 つの配列をパラメーターとして取り、両方のパラメーター配列に含まれる要素のみを含む配列を返す関数を作成する必要があります。

これは、配列を返す C 関数のこれまでの内容です。

#include <stdio.h>



main() 
{
    printf("Hello world");

    int array1[4] = {1, 2, 3, 4};
    int array2[4] = {3, 4, 5, 6};

    int* inter = intersection(array1, array2);

printf(inter); // <-- also, I don't know how I could get this to work for testing


    //freezes program so it doesn't terminate immediately upon running:
    getchar();
}





int* intersection(int array1[], int array2[])
{       
    int arrayReturn[sizeof(array1) + sizeof(array2)];
    int count = 0;

    for(int i = 0; i < 4; i++)
    {
        for(int j = 0; j < 4; j++)
        {
            if(array1[i]==array2[j])
            {

                arrayReturn[count] = array1[i];
                count = count + 1;

            }
        }
    }

    return arrayReturn;
}

もう 1 つの質問は、printf() ステートメントを使用して main() メソッドでこの関数をテストするにはどうすればよいかということです。

私がこれを行う必要がある理由は、プロセスとメモリ割り当てについて学習しているためであり、ポインタは OS 開発で大きな役割を果たすからです。私の教授は、ポインターを理解するのが非常に難しいため、多くのプログラミング言語からポインターを除外していると私に言いました。

4

2 に答える 2

1

さあ行こう

#include <stdio.h>

/* declare function, you need to capture array size as well, and also allow 
   to get result target pointer, result space info and pointer to place where the
   size of result will be captured */
int* intersection(int * array1, int a1len , int * array2, int a2len, int* result, int *resultsize, int resultspace);

main()
{
    printf("Hello world\n");

    int array1[4] = {1, 2, 3, 4};
    int array2[4] = {3, 4, 5, 6};
    int arrayr[32]; /*result will be in this table */
    int resultsize;
    int resultspace = 32;

    int i;
    /* here comes confusion - int resultsize means it will be read as integer,
       so we need to write &resultsize to get the pointer,
       array declaration like int arrayr[number] is actually understood by system
       as a pointer to an integer, pointing to first element of array,
       allowing you to use indexes 
       so arrayr[3] actually means *(arrayr + 3 * sizeof(int))
    */

    int* inter = intersection(array1, 4, array2, 4, arrayr, &resultsize, resultspace);
    /* inter is now a pointer to arrayr */
    for (i = 0; i<resultsize; i=i+1) {
                printf("%d\n", inter[i]);
        }


    //freezes program so it doesn't terminate immediately upon running:
    getchar();
}





int* intersection(int * array1, int a1len , int * array2, int a2len, int* result, int *resultsize, int resultspace)
{
    /* as we received a pointer to resultsize (*resultsize)
       we need to de-reference it using "*" to get or set the actual value */

    *resultsize = 0;

    int i, j;
    for(i = 0; i < a1len; i++)
    {
        for(j = 0; j < a2len; j++)
        {
            if(array1[i]==array2[j])
            {

                result[*resultsize] = array1[i];
                *resultsize = *resultsize + 1;
                if (resultspace == *resultsize)
                        return result;
            }
        }
    }

    return result;
}
于 2013-02-21T00:25:53.833 に答える
1

Cでは、戻り値の型を配列にすることはできませんか?

いいえ。配列とポインターを区別する特徴のいくつかは次のとおりです。

  1. sizeof arraynn * sizeof *arrayはポインタのサイズではなく、要素の数です。
  2. &arrayポインターへのポインターではなく、配列へのポインターとして評価されます。
  3. 配列を使用して配列を初期化し、ポインターを初期化できます。int *ptr = (int[]){ 1, 2, 3, 4 };、しかし、ポインタを使用して配列を初期化することはできません。int array[4] = ptr;.
  4. たとえば、配列に割り当てることはできません。int array[4]; array = (int[]){ 1, 2, 3, 4 };、ただし、ポインターに割り当てることができます: int *ptr; ptr = (int[]){ 1, 2, 3, 4 };、ポインターが int への const ポインターとして宣言されている場合を除きます。int * const ptr = NULL; ptr = (int[]){ 1, 2, 3, 4 };

オペレーティング システムのコースでポインターについて学び始めたところ、2 つの配列をパラメーターとして取り、両方のパラメーター配列に含まれる要素のみを含む配列を返す関数を作成する必要があります。

これは不可能です。まず、配列引数は実際にはポインター引数です。と を見てsizeof array1くださいsizeof array2。それらを使用して配列を初期化してみてください。それらに割り当ててみてください。上記のテストのうち、それらがポインターであることを示していると思われるテストはいくつありますか? 配列を関数に渡すと、配列式は配列の最初の要素へのポインターに評価されます。おそらく、配列へのポインターを受け入れるように関数を宣言する必要があります。たとえば、次のようになります。

int *intersection(size_t sz1, int (*array1)[sz1], // array1 is a pointer to int[sz1]
                  size_t sz2, int (*array2)[sz2]) // array2 is a pointer to int[sz2]
{ ... }

第二に、あなたの関数は明らかに配列ではなくポインタ値を返します。その戻り値に関して、arrayReturn は、intersection 内で自動保存期間を持つ配列として宣言されているため、intersection が戻るときに破棄されます。main がその値を使用しようとすると、破棄された配列を使用しようとします。自動保存期間を使用して配列を返すことはできません。自動ストレージ期間を使用して固定サイズの構造体を返すことは可能ですが、戻り値のサイズが動的である必要があるため、これは問題には役に立ちません。

もう 1 つの質問は、printf() ステートメントを使用して main() メソッドでこの関数をテストするにはどうすればよいかということです。

破棄されたオブジェクトを使用することは未定義の動作であるため、その関数の戻り値では何もできません。

私がこれを行う必要がある理由は、プロセスとメモリ割り当てについて学習しているためであり、ポインタは OS 開発で大きな役割を果たすからです。

C プログラミング言語は、OS の実装に依存しません。OS が自動保存期間でオブジェクトの破棄を遅らせるかどうかは問題ではありません。破棄されたオブジェクトを使用すると、未定義の動作が呼び出されます。

私の教授は、ポインターを理解するのが非常に難しいため、多くのプログラミング言語からポインターを除外していると私に言いました。

彼/彼女は自分のレッスンプランを書きましたか? そうでない場合は、改善を確認できる重要なポイントを見逃しています。彼/彼女の書面による授業計画は、過去にどの程度成功しましたか? 100% 成功した場合、「難しい」などの言葉を使用しても意味がありません。学生の圧倒的な感情を不必要に引き起こしたいのはなぜですか? パーツが複雑すぎる場合は、それらのパーツを特定して「難しい」と指定するよりも、それらのパーツを特定して明確にする方が理にかなっています。また、C に関するコースで他のプログラミング言語について言及しても意味がありません。

教授の授業計画がかなり成功すると、それを本として出版することが可能になります。1 つの例は、K&R の「The C Programming Language, Second Edition」です。本はありますか?

于 2013-02-21T03:01:30.277 に答える