質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

90.32%

  • C

    3997questions

    C言語は、1972年にAT&Tベル研究所の、デニス・リッチーが主体となって作成したプログラミング言語です。 B言語の後継言語として開発されたことからC言語と命名。そのため、表記法などはB言語やALGOLに近いとされています。 Cの拡張版であるC++言語とともに、現在世界中でもっとも普及されているプログラミング言語です。

  • C++

    3781questions

    C++はC言語をもとにしてつくられた最もよく使われるマルチパラダイムプログラミング言語の1つです。オブジェクト指向、ジェネリック、命令型など広く対応しており、多目的に使用されています。

多次元配列についてです。

解決済

回答 2

投稿 編集

  • 評価
  • クリップ 0
  • VIEW 613

strike1217

score 563

1、ポインタのポインタを2次元配列で初期化したいです。

    char buf[3][100] = {
        "you will make me happy",
        "I love you!",
        "Thanks"
    };

    char **p;
    char *q[3] = {buf[0], buf[1], buf[2]};
    p = q;
}


これは、うまくいきました。
char **pを上記のように初期化すると面倒です。

qを用意しないで、

char **p = buf;
とやりたいのですが・・・・うまくいきません。(warningが出てきます)
どうすれば、よろしいでしょうか?

2、多次元配列の動的確保で落ちます・・・・

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#define line 100

int main() {
    int i = 0;
    char **p;
    p = (char **)calloc(10, sizeof(char *));

    char (*q)[line];  // char q[][line]
    int n = 4;
    q = (char(*)[line])malloc(n * (sizeof(char) * line));  // char q[n][line]

    char *r[line];  // char r[line][]
    for (i = 0; i < line; i++)
        r[i] = calloc(100, sizeof(char));

    if (p) {
        p[0] = "DESTINY"; 
        p[1] = "I love you!!";

        printf("p : %s %s\n", p[0], p[1]);
        for(i = 0; i < 10; i++)
            free(p[n]);
    } else
        printf("failed!!\n");

    if (q) {
        strcpy(q[0], "you will make me sad");
        strcpy(q[1], "basketball");

        printf("q : %s %s\n", q[0], q[1]);
        free(q);
    } else
        printf("failed!!\n");

    if (r) {
        r[0] = "you will make me happy";
        r[1] = "but I don't like you";

        printf("r : %s %s\n", r[0], r[1]);
        for(i = 0; i < line; i++)
            free(r[i]);
    }
    else
        printf("failed!!\n");

    return 0;
}


これ、コンパイルはおkでしたが、実行すると落ちます。
一体どこがおかしいのでしょう・・・

3番目のrを追加したら、おかしくなりました。
ダメな箇所の指摘をお願いします。

Windows
visual stdio
でやってみました。

  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 2

checkベストアンサー

+1

こんにちは。

pはchar型へのポインタへのポインタです。
従ってp[0]は「char型へのポインタ」を指してます。
ということは、pが指せるメモリ領域の構造は下記です。

struct p_array_image
{
    char* p0;
    char* p1;
    char* p2;
        :
};


要素数が3の時、sizeof(p_array_image)は32ビット・ビルドなら12でしょう。

逆にchar buf[3][100]は下記のような構造です。

struct buff_image
{
    char buff0[100];
    char buff1[100];
    char buff2[100];
};


sizeof(buff_image)は300ですね。

このようにpが指す構造とbuffの構造が全く異なるため、p経由でbuffの要素にアクセス出来るはずありません。従って、p=buff;はやるべきでない操作です。

動的配列の方は単なるバグと思います。

for(i = 0; i < 10; i++)
   free(p[n]);

当然、p[4]を10回も解放してはだめです。
(p[4]はNULLなので落ちているのはここが原因ではないと思いますが。)

3番目のrを追加したら、おかしくなりました。 
ダメな箇所の指摘をお願いします。

r[0], r[1]はcallocで確保したメモリではなく、文字列定数へのポインタですね。メモリ・マネージャが管理していない領域を解放すると異常が発生します。

そもそも、free関数に渡すポインタは、mallocやcallocで受け取ったポインタです。
それ以外のものを渡してはいけません。たとえそれがmallocやcallocで割り当てられた領域であったとしても途中のアドレスを渡してはダメです。必ず先頭アドレスを渡して下さい。
qは適切に解放されていると思います。pとrはNGです。

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2017/01/22 19:59

    ありがとうございます
    char buffer[100];
    char* re = buffer; これができるので2次元の時もできるものだと思ってしまいました。

    p[0] = "DESTINY";
    こういうことはしてはダメなんですね!!
    修正してみます。

    キャンセル

  • 2017/01/22 20:09

    char **p;
    p = (char **)calloc(10, sizeof(char *));
    この子の解放の仕方は・・・・
    for(i = 0; i < 10; i++)
    free(p[i]);
    こうですか??
    free(p);
    こうですか??

    キャンセル

  • 2017/01/22 20:46

    後者です。callocから返ってきたメモリの先頭アドレスをfreeに渡して解放します。

    また、free(p[i])で実際にfree()に渡っている値はなんでしょうか?
    printf("%p\n", p[i]);してみると良いと思います。

    キャンセル

  • 2017/01/22 20:52

    どうも2次元配列が苦手なので、もう少し勉強いたします。
    ありがとうございました。

    キャンセル

  • 2017/01/22 21:04

    ちょっと、質問の仕方が悪すぎたので、再度質問します!

    キャンセル

+1

アドレスとして配列に入れる方法ではどうでしょうか。

#include<stdio.h>
void main(void){

    char buf[3][100] = {
        "you will make me happy",
        "I love you!",
        "Thanks"
    };

    void *q[] = {&buf[0], &buf[1], &buf[2]};

    printf("%s %s %s\n",*q, *(q+1), *(q+2));
}

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2017/01/22 19:57

    ふむふむ・・・
    ありがとうございます!

    キャンセル

同じタグがついた質問を見る

  • C

    3997questions

    C言語は、1972年にAT&Tベル研究所の、デニス・リッチーが主体となって作成したプログラミング言語です。 B言語の後継言語として開発されたことからC言語と命名。そのため、表記法などはB言語やALGOLに近いとされています。 Cの拡張版であるC++言語とともに、現在世界中でもっとも普及されているプログラミング言語です。

  • C++

    3781questions

    C++はC言語をもとにしてつくられた最もよく使われるマルチパラダイムプログラミング言語の1つです。オブジェクト指向、ジェネリック、命令型など広く対応しており、多目的に使用されています。