関数へのパラメーターの受け渡しとキャスト

マイケル

私はC言語に不慣れで、次の演習で誤解があります。

void printAllStrings(const char** arr[])
{
    while(*arr!=NULL)
    {
        char** ptr=(char**)*arr;
        while(*ptr!=NULL)
        {
            printf("%s\n",*ptr);
            ptr++;
        }
        arr++;
    }
}

int main()
{
    char* arrP1[]={"father","mother",NULL};
    char* arrP2[]={"sister","brother","grandfather",NULL};
    char* arrP3[]={"grandmother",NULL};
    char* arrP4[]={"uncle","aunt",NULL};
    char** arrPP[]={arrP1,arrP2,arrP3,arrP4,NULL};

    printf("Before sort :\n");
    printAllStrings(arrPP);
    sort(arrPP);

    printf("\nAfter sort :\n");
    printAllStrings(arrPP);
    printf("\nMaximum length string : %s \n",maxLengthString(arrPP));

    return 0;
}    

上記のコードはすべての文字列を出力します。

私の質問は:

  1. printAllStrings機能渡されたパラメータ(char** arr[]文字列の)配列、我々はポインタにポインタを渡すことができます- char** arr

  2. この行の意味は何ですかchar** ptr=(char**)*arr私は、char型へのポインタのこのキャストを理解しています。しかし、なぜポインターをキャストする必要があるのは、すでにchar型を指しているのでしょうか。

デビッドC.ランキン
  1. printAllStrings関数で、渡された(char** arr[])文字列のパラメータ配列で、ポインタをポインタに渡すことができます- char** arr[]

上記の例ではchar** arr[]、とchar** arr[](2つは同じ)があるので、「合格できますか?」質問は不明です。パラメータを(char ***arr)変更できるかどうかを尋ねている場合は、そうです。間接参照の最初のレベル(たとえば[ ])がポインタに変換されるためです。

  1. この行の意味は何ですかchar** ptr=(char**)*arr私は、char型へのポインタのこのキャストを理解しています。しかし、なぜポインターをキャストする必要があるのは、すでにchar型を指しているのでしょうか。

その理由は、あなたのパラメータがありconst char** arr[]、その後、あなたが宣言しchar** ptr破棄const修飾子のをarrconst char **char **同じではありません。したがってptr、逆参照されたarr((char** ptr=arr;)など)初期化しようとする、コンパイラはconst修飾子の破棄について文句を言います。

問題を正しく修正するのではなく、たとえば

const char **ptr = *arr;

初期化を「ファッジ」して、const修飾子を強制的に破棄します。その結果ptrconst型が保持さなくなり、ptr定数以外の方法で使用しようとしたときにコンパイラーが警告を発するのを防ぐことができますconst修飾子を捨てるだけで本当に悪いことが起こります)

私は間違っているかもしれませんが、割り当てのポイントは、ポインタの配列を初期化するために使用する文字列リテラルのconst性質を保持することであるように見えます。したがって、配列を次のように宣言するのではなく、次のようにします。

char* arrP1[]={"father","mother",NULL};

それらconstをcharへポインタの配列として宣言する必要があります。

const char *arrP1[]={"father","mother",NULL};

その場合のパラメータprintAllStringsは理にかなっており、文字列リテラルの変更など、許可されていないことを実行しようとすると、コンパイラは警告を表示します。

arrP1[0][0] = 'l';

(コンパイラはスローしますerror: assignment of read-only location ‘*arrP1[0]

コード全体で型を一貫して運ぶ場合は、キャストをどこにでも「ファッジ」する必要はなく、コンパイラーは自分自身からユーザーを保護するのに役立ちます。たとえば、文字列リテラルがconst修飾されていることを確認するための型の単純な作り直し(配列の並べ替えは可能ですが)は、次のような方法で実行できます。

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

void printAllStrings (const char **arr[])
{
    while (*arr != NULL) {
        const char **ptr = *arr;
        while (*ptr != NULL) {
            printf ("%s\n", *ptr);
            ptr++;
        }
        arr++;
    }
}

const char *maxLengthString (const char **arr[])
{
    size_t max = 0;
    const char *longest = NULL;

    while (*arr != NULL) {
        const char **ptr = *arr;
        while (*ptr != NULL) {
            size_t len = strlen (*ptr);
            if (len > max) {
                max = len;
                longest = *ptr;
            }
            ptr++;
        }
        arr++;
    }
    return longest;
}

int main (void) {

    const char *arrP1[] = {"father", "mother", NULL};
    const char *arrP2[] = {"sister", "brother", "grandfather", NULL};
    const char *arrP3[] = {"grandmother", NULL};
    const char *arrP4[] = {"uncle", "aunt", NULL};
    const char **arrPP[] = {arrP1, arrP2, arrP3, arrP4, NULL};

    printf ("Before sort :\n");
    printAllStrings (arrPP);

    // sort (arrPP);  /* you didn't post sort, so the following swaps */
    const char **tmp = arrPP[0];    /* simple swap example */
    arrPP[0] = arrPP[1];
    arrPP[1] = tmp;

    printf ("\nAfter sort :\n");
    printAllStrings (arrPP);

    printf ("\nMaximum length string : %s \n", maxLengthString (arrPP));

    return 0;
}

(投稿しなかったsort()ので、要素の上に単にスワップしてarrPPソートする機能を保持していることを示しmaxLengthString ()、最後のステートメントを機能させるためにのクイック実装が追加されました-ただし、最初のステートメントが見つかるだけです。複数の文字列が同じ長さの場合は最長の文字列)

使用例/出力

$ ./bin/array_ptp_const_char
Before sort :
father
mother
sister
brother
grandfather
grandmother
uncle
aunt

After sort :
sister
brother
grandfather
father
mother
grandmother
uncle
aunt

Maximum length string : grandfather

物事を見て、さらに質問があれば私に知らせてください。これがあなたが探していたものであるかどうかはわかりませんが、あなたのコードと質問に基づいて、それは最も論理的な選択のように思われました。

この記事はインターネットから収集されたものであり、転載の際にはソースを示してください。

侵害の場合は、連絡してください[email protected]

編集
0

コメントを追加

0

関連記事

分類Dev

Bash関数へのパラメーターの受け渡し

分類Dev

Verilog関数へのパラメーターの受け渡し

分類Dev

svelte関数へのパラメーターの受け渡し

分類Dev

Matlab関数へのパラメーターの受け渡し

分類Dev

BASH関数へのパラメーターの受け渡し

分類Dev

PostgreSQLとSSRS:PostgreSQL関数へのパラメーターの受け渡し

分類Dev

pthread関数への複数のパラメーターの受け渡しとアクセス

分類Dev

関数へのパラメーターとしてのオブジェクトの受け渡し:MATLAB

分類Dev

CMakeの再スキャンとパラメーターの受け渡し

分類Dev

PythonからR関数へのベクトルとパラメーターの受け渡し

分類Dev

Cの関数へのパラメーターとしての構造体メンバーの受け渡し

分類Dev

匿名関数へのパラメーターの受け渡しJavascript

分類Dev

解決関数へのパラメーターの受け渡し

分類Dev

ストアドプロシージャへのパラメータの受け渡し-特殊なケース

分類Dev

Jqueryフェードアウト関数へのパラメーターの受け渡し

分類Dev

C-参照と値による関数への構造パラメーターの受け渡し

分類Dev

ループ内の値をパラメータ関数と比較するためのキーの受け渡し

分類Dev

ストアドプロシージャへのパラメータの受け渡しの問題

分類Dev

SQLServerストアドプロシージャへのパラメータの受け渡し

分類Dev

PowerShellスクリプトへのパラメーターの受け渡し

分類Dev

SQL関数パラメーターの受け渡し

分類Dev

子コンポーネントポリマー3へのパラメーターとしての関数の受け渡し

分類Dev

ルーターミドルウェア関数へのパラメーターの受け渡し

分類Dev

C ++:テンプレートを介した引数の受け渡しと関数パラメーターを介した受け渡し

分類Dev

参照パラメーターを持つ関数へのポインターの受け渡し

分類Dev

ジャージーリソースへのパラメータの受け渡し

分類Dev

Liferayポートレットへのパラメーターの受け渡し

分類Dev

決定論的変数pymcへのパラメーターの受け渡し

分類Dev

Goのクロージャー-関数をパラメーターとして受け取る関数の宣言

Related 関連記事

  1. 1

    Bash関数へのパラメーターの受け渡し

  2. 2

    Verilog関数へのパラメーターの受け渡し

  3. 3

    svelte関数へのパラメーターの受け渡し

  4. 4

    Matlab関数へのパラメーターの受け渡し

  5. 5

    BASH関数へのパラメーターの受け渡し

  6. 6

    PostgreSQLとSSRS:PostgreSQL関数へのパラメーターの受け渡し

  7. 7

    pthread関数への複数のパラメーターの受け渡しとアクセス

  8. 8

    関数へのパラメーターとしてのオブジェクトの受け渡し:MATLAB

  9. 9

    CMakeの再スキャンとパラメーターの受け渡し

  10. 10

    PythonからR関数へのベクトルとパラメーターの受け渡し

  11. 11

    Cの関数へのパラメーターとしての構造体メンバーの受け渡し

  12. 12

    匿名関数へのパラメーターの受け渡しJavascript

  13. 13

    解決関数へのパラメーターの受け渡し

  14. 14

    ストアドプロシージャへのパラメータの受け渡し-特殊なケース

  15. 15

    Jqueryフェードアウト関数へのパラメーターの受け渡し

  16. 16

    C-参照と値による関数への構造パラメーターの受け渡し

  17. 17

    ループ内の値をパラメータ関数と比較するためのキーの受け渡し

  18. 18

    ストアドプロシージャへのパラメータの受け渡しの問題

  19. 19

    SQLServerストアドプロシージャへのパラメータの受け渡し

  20. 20

    PowerShellスクリプトへのパラメーターの受け渡し

  21. 21

    SQL関数パラメーターの受け渡し

  22. 22

    子コンポーネントポリマー3へのパラメーターとしての関数の受け渡し

  23. 23

    ルーターミドルウェア関数へのパラメーターの受け渡し

  24. 24

    C ++:テンプレートを介した引数の受け渡しと関数パラメーターを介した受け渡し

  25. 25

    参照パラメーターを持つ関数へのポインターの受け渡し

  26. 26

    ジャージーリソースへのパラメータの受け渡し

  27. 27

    Liferayポートレットへのパラメーターの受け渡し

  28. 28

    決定論的変数pymcへのパラメーターの受け渡し

  29. 29

    Goのクロージャー-関数をパラメーターとして受け取る関数の宣言

ホットタグ

アーカイブ