2017-02-08 5 views
2

私は中規模のプログラマであり、標準Cを学んでいます。現在、さまざまな種類のデータ型を格納するポインタを使用するクラス演習に苦労しています。 char型の配列標準配列で複数のデータ型を格納するためにchar配列を使用する

は、私は大きなchar型の配列があるとします。

static char arr[1000]; 

私の教授がそれを説明したように、私はこの配列の各要素は、1バイトの粒度を持つローカルメモリの塊、と考えることができます。それは役に立つと思われる。今、私は最初の4バイト/要素を取り、int型を格納したいとします、私はそれを理解したよう

int a = 100; 
int* ptr = (int*)arr; 
*ptr = a; 

、2行目は、int型*ポインタを作成し、配列arrの冒頭で、それを指しています。 3行目は、aの値をその場所に書き込みます。 ptrはint型のポインタであり、arrには十分なスペースがあるので、sizeof(int)== 4であるため、4バイト/ 4要素分のデータを書き込みます。

これまでのところ、とても良いです。さて、私はこの概念を拡張したいとしましょう。

int a = 100; 
int b = 200; 
char* str = “My dog has fleas” 
int c = 300; 

論理的に次のようになります:

00 01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 
-------------------------------------------------------------------------------------- 
[ 100 ] [ 200 ] M y  d o g  h a s  f l e a s \0 [ 300 ] 

が、私はこの内の配列にデータを格納できるようにする必要があるのは、私がこの順で、私の配列に次を保存したいとしましょうその後、アレイ構造を事前に知っていれば、アレイを読み取ることができます。私のコード&の出力は以下の通りです。あらかじめ長い間ご容赦ください。それはコンパイルされますが動作しません。私のデバッガでそれを精査することは非常に混乱しています。私はどこで(そしてどのくらいの頻度で)オフトラックに行くのかは分かりません。誰かが洞察力やアドバイスを持っているなら、私はとても感謝しています。

int main(){ 

    static char arr[1000]; 

    int a = 100; 
    int b = 200; 
    char* str = "My dog has fleas"; 
    int c = 300; 

    // Create pointers to load data: 
    int* ptrA = arr;      // points to start of array 
    int* ptrB = ptrA + sizeof(int);  // points 4 bytes into array 
    char* ptrStr = ptrB + sizeof(int); // points 8 bytes into array 
    int* ptrC = ptrStr + sizeof("My dog has fleas"); // points to after the string 
             // (I don't know how to use sizeof() to measure the actual length of the string 

    // Load data into my array 
    *ptrA = a;  // Assign int 100 into the array? 
    *ptrB = b;  // Assign int 200 into the array? 
    *ptrStr = memcpy(ptrStr, str, sizeof("My dog has fleas"));  // Write "My dog has fleas" into the array? 
    *ptrC = c;  // Assign int 300 into the array? 

    // Knowing the array's structure, walk it and print results: 
    char* walkIt = arr; 
    int counter = 0; 
    while (counter < 30) { 
     if (counter == 0) { 
      // we are pointing at what should be the first int 
      int* tmpPtr1 = (int*)walkIt; 
      printf("%d ", *tmpPtr1); 
     } 
     else if (counter == 4) { 
      // we are pointing at what should be the second int 
      int* tmpPtr2 = (int*)walkIt; 
      printf("%d ", *tmpPtr2); 
     } 
     else if (counter == 8) { 
      // we are pointing at what should be the string 
      printf("%s ", walkIt); 
     } 
     else if (counter == 25) { 
      // we are pointing at what should be the third int 
      int* tmpPtr3 = (int*)walkIt; 
      printf("%d ", *tmpPtr3); 
     } 
     walkIt++;  // Continue walking the array 
     counter++;  // Don't walk too far 
    } 
    return 0; 
} 

出力がこれです:それは別のへのポインタをキャストして得られたポインタを参照解除、ボンネットの下に物事は多分そのようになるというのは本当だが

100 0 0  
+0

'memcpy(ptrStr、str、sizeof("私の犬はノミがあります) "))'。文字列の 'sizeof'はあなたが望む結果を与えるわけではありません。それはちょうどあなたのポインタのサイズを返します。代わりに 'strlen'を使用してください。あるいは、 'strcpy'を使ってコピーを行います。 – kaylum

+1

私はこの練習のポイントが何であるか完全には分かっていませんが、あなたの教授はあなたに不満を与えているようです。 'char'の配列の全部または一部に' int'や他の非'char'型のようにアクセスすることは、C言語では有効ではありません。 –

+1

あなたの教授は、あなたがしていることが[厳密なエイリアシングルール](http://stackoverflow.com/questions/98650/what-is-the-strict-aliasing-rule)に違反しているので間違っています。最適化。この目的のために 'union'を使う方が良いでしょう。 – Jack

答えて

2

すべての教授の最初には、間違っています型はstrict aliasingの規則に違反します。これは、異なる型の2つのポインタが同じメモリを参照することができず、そのようなポインタの最適化を可能にするというコンパイラの前提です。戻ってあなたのコードに行く

、問題は、ベースアドレスからのオフセットを計算する方法である。例:

int* ptrB = ptrA + sizeof(int); 

さて、ptrAint*のものであり、整数を追加すると、暗黙的に乗算ポインタにオフセット指定された要素のサイズによるオフセット。つまり、sizeof(int)バイトではなく、sizeof(int)*sizeof(int)バイトを追加しています。

強制的に特定の量のバイトを追加するには、char*にポインタをキャストして、sizeof(int)バイトを追加するだけでバイトが追加されるようにする必要があります。このコードは安全ではない、よりよい解決策になるunionを使用して、必ず失敗するということ

int* ptrB = (char*)ptrA + sizeof(int);  // points 4 bytes into array 

マインド。

+2

キャスティングは厳密なエイリアシング規則に違反しません。スペースにアクセスするための結果のポインターを使用します。 –

+0

@ M.M:ありがとう、私はそれを明確にした。 – Jack

+0

@Jack - Ohhhhhhhhhhhhh、それは意味の世界を作る。ありがとう、私は実装します。私はこれが私の教授が私にすべて学ぶことを望んでいたと思う。 – Pete

関連する問題