2016-04-13 8 views
0

私は、少なくとも私が期待していなかった何か "C"の "奇妙な"動作に出くわしました。このコードの次の行を考える:(arrayB + 1)[1]しかしarrayBの第三の要素(従って、それは予想通り3印刷)配列内の矛盾するポインタ

ある*(arrayB+1 +1)に変換されるよう

int arrayB[10] = {1, 2, 3, 4, 5, 6, 7, 8, 9}; 
printf("%d\n", (arrayB+1)[1]); 

これは正常に動作し、Iは初期化以下のコードを検討2DアレイはarrayAこのコードは、警告が発生しない

int ** arrayA = malloc(sizeof(int *) * 5); 
for (int i = 0; i < 5; i++) { 
    arrayA[i] = malloc(sizeof(int) * 10); 
    for (int j = 0; j < 10; j++) { 
     arrayA[i][j] = j; 
    } 
} 

printf("%d\n", *(arrayA+1)[2]); 

(各{0, 1, 2, 3, 4, 5, 6, 7, 8, 9}、10個のintの5つのアレイを有する)と呼ばれ、そのを主張しますはint型です。

:しかし.. arrayAがさらに後にこれが許容されることであるint **あるので*(arrayA+1)[2]は、タイプint *である*(arrayA+3)に変換し、(配列の添字は、間接参照演算子よりも高い優先順位を有するので)それがなければならないと思われます*(arrayA+1)[2] = 1;

これはどのように可能ですか?あたかもをint *に割り当てているようですが、通常は警告が表示されます。

+0

(はい、それはexitに自動的に解放されますが、各バイトを占める今の習慣に取得し、後で自分で悲しみを大幅に節約されますされます)これは*ありません* 2次元配列のみが不良ですそれのエミュレーションCにはネイティブの多次元配列があります。あなたの人生を不必要に複雑にしないでください。 –

答えて

3

それはありません*(arrayA+1)[2]*(arrayA+3)

に変換...と思われる、あなたは*を落としました。 *(arrayA+1)[2]**(arrayA+3)になります。これは実際にはintです。

+0

!!華麗な説明 –

0

int ** arrayA(2D)について説明します。

arrayAはint **なので、arrayA + xもint **です。

* arrayAまたはarrayA [i]はint *であり、線形配列(1D)です。

したがって、任意の優先度を持つ*(arrayA + 1)[2]は、アドレスではない値です。ポインタの補正に加えて

-1

、あなたはへのポインタへのポインタint型(例えばint **arrayA;)宣言し、ポインタを割り当て、その後、メモリを割り当てて、個々のポインタにブロックを割り当てることは自由ですが、各行に固定数の要素を扱うときは、そのようにする必要はありません。 の配列へのポインタ-noを単に宣言することができます。(例えばint (*arrayA)[10];と一度に割り当てる例:

#include <stdio.h> 
#include <stdlib.h> 

#define ASZ 5 

void *xmalloc (size_t s) { 
    void *memptr = malloc (s); 
    if (memptr == 0) { 
     fprintf (stderr, "xmalloc() error: virtual memory exhausted.\n"); 
     exit (EXIT_FAILURE); 
    } 
    return memptr; 
} 

int main (void) { 

    int i, j; 
    int (*arrayA)[ASZ] = xmalloc (sizeof *arrayA * ASZ); 

    for (i = 0; i < ASZ; i++) { 
     for (j = 0; j < ASZ; j++) { 
      arrayA[i][j] = j+i; 
     } 
    } 

    for (i = 0; i < ASZ; i++) { 
     if (!i) putchar ('\n'); 
     for (j = 0; j < ASZ; j++) { 
      printf (" %2d", arrayA[i][j]); 
     } 
     putchar ('\n'); 
    } 

    printf("\n *(arrayA+1)[2] = %d\n\n", *(arrayA+1)[2]); 

    free (arrayA); 

    return 0; 
} 

(あなたのメモリ割り当てを検証することを忘れないでください)生活をより

使用例/出力

を作ることができます xmallocのようなヘルパーを使用。
$ ./bin/arr2dderef 

    0 1 2 3 4 
    1 2 3 4 5 
    2 3 4 5 6 
    3 4 5 6 7 
    4 5 6 7 8 

*(arrayA+1)[2] = 3 

Linuxでvalgrindなどのメモリエラーチェックプログラムを使用してメモリ使用を検証することを忘れないでください。それが不要になったときにメモリを解放します。

$ valgrind ./bin/arr2dderef 
==28392== Memcheck, a memory error detector 
==28392== Copyright (C) 2002-2013, and GNU GPL'd, by Julian Seward et al. 
==28392== Using Valgrind-3.10.1 and LibVEX; rerun with -h for copyright info 
==28392== Command: ./bin/arr2dderef 
==28392== 

    0 1 2 3 4 
    1 2 3 4 5 
    2 3 4 5 6 
    3 4 5 6 7 
    4 5 6 7 8 

*(arrayA+1)[2] = 3 

==28392== 
==28392== HEAP SUMMARY: 
==28392==  in use at exit: 0 bytes in 0 blocks 
==28392== total heap usage: 1 allocs, 1 frees, 100 bytes allocated 
==28392== 
==28392== All heap blocks were freed -- no leaks are possible 
==28392== 
==28392== For counts of detected and suppressed errors, rerun with: -v 
==28392== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 1 from 1)