2

最も重要な関数が type の引数を取るライブラリの関数を使用していますconst short int*。私が代わりに持っているのはint *、 を にキャストする方法があるかどうか疑問に思っていint *ましたconst short int*。次のコード スニペットは、私が直面している問題を強調しています。

/* simple program to convert int* to const short* */


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

    void disp(const short* arr, int len) {

      int i = 0;
      for(i = 0; i < len; i++) {
        printf("ith index = %hd\n", arr[i]);
      }
    }

    int main(int argc, char* argv[]) {

      int len = 10, i = 0;
      int *arr = (int *) malloc(sizeof(int) * len);

      for(i = 0; i < len; i++) {
        arr[i] = i;
      }

      disp(arr, len);

      return 0;
    }

上記のコード スニペットがコンパイルされます。これは私がこれまでに
試したことです: 1. c-style キャストを試しました。関数呼び出しは次のようになります
disp((const short*) arr, len)。結果の出力は非常に奇妙でした:

ith index = 0
ith index = 0
ith index = 1
ith index = 0
ith index = 2
ith index = 0
ith index = 3
ith index = 0
ith index = 4
ith index = 0 
  1. const-ness キャストを試しました。関数呼び出しは次のようになりました:
    disp(const_cast<const short*> arr, len);
    これにより、コンパイル中にエラーが発生しました。

私の質問:
1. アプローチ 1 の出力がおかしいのはなぜですか? あそこで何が起こっているのですか?
2.アプローチ2でconstキャストを使用してconst-nessを削除する例を見ました。同じものを追加する方法がわかりません。
3. を にキャストする方法はありint*ますconst short int*か?

PS: 以前に尋ねられたこの種の質問がある場合は、お知らせください。私はそれをグーグルで検索しましたが、具体的なものは見つかりませんでした。

4

4 に答える 4

5

int *一般に、からへのキャストはshort *有用な動作を提供しません (実際、結果のポインターを逆参照しようとすると、未定義の動作につながる可能性があります)。それらは根本的に異なる型へのポインタです。

関数が一連の s へのポインターを期待している場合はshort、それを指定する必要があります。の配列を作成しshort、元の配列から入力する必要があります。

于 2013-02-04T14:28:53.570 に答える
4

キャストはほとんどの場合、設計上の問題の兆候です。short*(またはそれ以外の) を取る関数がある場合は、constで呼び出す必要がありますshort*。したがって、 の配列を割り当てる代わりに、 の配列をint割り当てshortます。

int*anを aにキャストすると、コンパイラに、実際には へのポインターであるshort*ふりをするように指示されます。それはそうしますが、コンパイラに嘘をついたので、あなたはその結果に責任があります。int*short

于 2013-02-04T14:33:29.903 に答える
3

そうです、a の SIZE は多くの環境shortで an とは異なりintます (そうである必要はありません。たとえば 16-bitintと 16- bit を持つコンパイラは確かにありますshort)。

したがって、この方法でポインターをキャストすることから得られるのは、a) 未定義の動作、および b) 自分が何をしているのか正確にわかっていない限り、おそらくとにかく望んでいたものではないということです。

あなたのコードからの出力は、私が期待するものから完全にうまく見えるので、あなたがやろうとしていることについて何も言っていないことは明らかです!

編集: ポインターは「サイズ依存」であるため、あるサイズのポインターを別のサイズの型へのポインターにキャストすると、データの配置が正しくないことに注意してください。これが、他のすべての値がゼロになる理由です。出力 - anintは [通常] 4 バイトであり、ashortは 2 バイトであるため、ポインターはインデックスごとに 2 バイトを「ステップ」します (arr[i]元のarr+ i * 2 バイトになります。ここで、int * arr4 バイトの「ステップ」があります) 。 、だからarr + i * 4バイト整数値に応じて、これから「整数の半分」の値が得られます-数値が小さいため、これはゼロです。

そのため、コンパイラーは、ユーザーが要求したことを正確に実行します。つまり、shortを含むメモリーの塊を指すポインターを作成しますが、ユーザーが期待すること、つまりそれぞれを にint変換することはしません。そのためには、次のいずれかを行う必要があります。intshort

short **sarr = malloc(sizof(short *) * 10); 

for(i = 0; i < 10; i++)
{
    sarr[i] = (short *)(&arr[i]);       // This may well not work, since you get the "wrong half" of the int.
}

これが間違った半分を与える場合、これを行うことができます:

     sarr[i] = (short *)(&arr[i])+1;      // Get second half of int.

ただし、「バイトオーダー」(ビッグエンディアンまたはリトルエンディアン)に依存するため、移植性がありません。そして、一般的なコードでこれを行うのは非常に悪いコーディング スタイルです。

または: short *sarr = malloc(sizof(short *) * 10);

for(i = 0; i < 10; i++)
{
    sarr[i] = (short)(arr[i]);
}

2 番目の方法は、整数配列のコピーを短い配列に作成するという意味で機能します。これは、コンテンツが保存されている順序などにも依存しません。もちろん、 の値arr[i]が に収まる値よりも大きい場合、!shortと同じ値は得られません。arr[i]short

どちらの場合も、不要になった配列を解放することを忘れないでください。

于 2013-02-04T14:33:38.367 に答える
2

q.1 へ
の回答 出力はまったく変ではありません。どうやら、コンパイラは各int4 バイトと各short2 バイトを割り当てます。したがって、arrサイズは 10x4 = 40 バイトです。番号 0..9 を割り当てると、メモリ内にあります (1 バイトあたり 1 文字、 でグループ化int):

0 0 0 0
0 0 0 1
0 0 0 2
0 0 3
0 0 0 4
...

メモリにキャストarrするとshort、2バイトに「グループ化」されます:

0 0
0 0
0 0
0 1
0 0
0 2
0 0
...

0効果と、割り当てた番号の間に突然 -s が挿入された理由を理解していただければ幸いです。

q.2の答え関数内で
の の宣言は、 の実行中に の内容が変更されないことを意味するだけです。を呼び出すために、引数を明示的に配列にキャストする必要はありません。constdisplayarrdisplayconstdisplay

q.3 への
回答は、@Pete および @Mats による回答を参照してください。

于 2013-02-04T14:53:17.377 に答える