2

教科書で次の C コードの断片を見ましたが、正しく動作しています... しかし、出力が正しく動作していない理由がわかりません。

#include <stdio.h>

int main()
{

    struct {
        int x,y;
    } s[4] = {{10,20},{15,25},{8,75},{6,2}};
    int *i;
    i=s;

    clrscr();
    printf("\n%d",s[i[7]].x);
    printf("\n%d",i[i[1]-i[2]]);
    printf("\n%d",i[s[3].y]);
    printf("\n%d",(s+1)->x+5);
    printf("\n%d",s[i[0]-i[4]].y + 10);
    printf("\n%d",++i[i[6]]);
    getch();

    return 0;

}

sまた、ステートメントで整数ポインターを割り当てる方法がわかりません

i=s;
4

4 に答える 4

2

また、ステートメントで s に整数ポインターを割り当てる方法もわかりません。i=s;

それは簡単です。C ではキャストなしではできません。あなたのコンパイラは親切にもそのようなプログラムを受け入れますが、他のコンパイラにはそのプログラムのコンパイルを拒否する権利があります。

于 2012-06-16T16:27:32.927 に答える
1

少し追加する:CIで、次のような状況が発生した場合のトリックに従います:この#type#s [p]のように見えるときはいつでも、sは#type#タイプのポインターであり、s[p]は別の記述方法です* (s + p)。したがって、(「i」には配列のベースアドレスが割り当てられます)たとえば、-i [i [1] -i[2]]はi[(*(i + 1))-(*(i + 2))]です。 => i [20-15] => i [5] => *(i + 5)=>75。

また、注意してください

1)構造体のストレージの割り当てには、内部パディングを使用できます。例:2つのintと1つのcharを持つ構造体は、必ずしも4 + 4 + 2 = 10バイト連続する必要はなく、内部パディングがある場合があります。ただし、この2つのintを持つ構造体は、内部パディングのみを使用します。

2)互換性のないポインタがほとんどのコンパイラによって割り当てられるため、警告が表示されます。

3)「i」には、内部パディングのない構造体の配列のベースアドレスが割り当てられているため、この慎重に設計されたコードは魔法のように機能します。

于 2012-06-19T05:09:46.653 に答える
1

ポインタの割り当てに関する限り:

以下からコメントを取得するには:

「int の配列と int だけで構成された struct の配列のメモリ レイアウトは同じです」

ポインター型を定義する必要があるのは、ポインターが指しているデータのサイズをコンパイラーが認識しなければならないためです。整数のサイズは 4 バイトですが、この構造体のサイズは 8 バイトになります。プログラムが location のメモリーにアクセスしようとすると、コンパイラーは、プログラムが 8 バイト後にデータを必要としていることを認識します。s[1]s[0]i[1]i[0]

s構造体の配列 (int 型の 2 つのメンバーを持つ) でiあり、int へのポインターです。の最初の要素はs2 つの int の構造体であるため、 の最初の要素i = sの最初のメンバーのアドレスを に代入しsますi

i = &s[0]は同じ課題です。

0x00s[0]で開始した場合、最初のメンバーはアドレス0x00を持ち、2 番目のメンバーはアドレス0x04を持ちます。0x08で始まる場合、その場所の構造体には、アドレス0x0Cを持つ 2 番目のメンバーがあります。s[1]

ではi = s、の最初の要素の 2 番目のメンバーであるi[0]アドレス0x00i[1]があり、 はアドレス0x04を持っていますs。配列内の 2 番目の構造体の最初のメンバーであるi[2]アドレス0x08i[3]を持ち、配列内の 2 番目の構造体の 2 番目のメンバーであるアドレス0x0Cを持ちます。等々...

  { 10, 20 } { 15, 25 } { 8, 75 } { 6, 2 }
s:|    0    |     1    |    2    |   3   |
i:| 0 |  1  |  2 |  3  |  4 | 5  | 6 | 7 |

i最初の整数 (8 つすべてのうち) を指すようになりました。

i[0] = 10

i[7] = 2

最初のprintfステートメントは次のように解釈さi[7] = 2れます。s[2]{8,75}8

ポインターは実際には互換性がなく、gcc バージョン 4.4.3 (Ubuntu 4.4.3-4ubuntu5.1) でコンパイルすると、次の警告が生成されます。

test.c: 関数 'main' 内: test.c:10: 警告: 互換性のないポインター型からの代入

ただし、プログラムは出力をコンパイルして生成します。

8 75 15 20 85

于 2012-06-16T16:26:25.080 に答える
0

コンパイラは、s[4] のデータを 10、20、15、25、8、75、6、2 などの線形メモリに格納します。i[7] は 2 です。次の例のような単なるトリックです。

次のような構造があります。

struct block{
int a;
int b;
};

struct block item;

の住所を知っている場合item->b、どうすれば の住所を知ることができますかitem

答えは、item->bマイナスのアドレスを使用しています((struct block *)0)->b

于 2012-06-16T16:47:29.703 に答える