4

入力raw pcmストリームをmp3を使用するように変換していますlame。そのライブラリ内のencoding関数はmp3、型の配列でエンコードされたサンプルを返しますunsigned charflvこのmp3でエンコードされたストリームは、エンコードされたサンプルをchar配列に書き込む関数を使用するコンテナー内に配置する必要があります。私の問題は、lame(タイプのunsigned char)からflvライブラリに配列を渡そうとしていることです。次のコード(シンボリックのみ)は、私の問題を示しています。

/* cast from unsigned char to char. */

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

void display(char *buff, int len) {

  int i = 0;
  for(i = 0; i < len; i++) {
    printf("buff[%d] = %c\n", i, buff[i]);
  }
}

int main() {

  int len = 10;
  unsigned char* buff = (unsigned char*) malloc(len * sizeof(unsigned char));
  int i = 0;

  for(i = 65; i < (len + 65); i++) {
    buff[i] = (unsigned char) i;
    printf("char = %c", (char) i);
  }

  printf("Displaying array in main.\n");
  for(i = 0; i < len; i++) {
    printf("buff[%d] = %u\n", i, 'buff[i]');
  }

  printf("Displaying array in func.\n");
  display(buff, len);

  return 0;
}

私の質問: 1。以下のコードの暗黙の型変換は安全ですか?関数
に渡すことによって示されるように安全ですか?奇妙な動作が発生する可能性がありますか? 2。関数に固執する以外に選択肢がほとんどないことを考えるとそれらは存在しますが、sの配列をsに変換する「安全な」方法はありますか?buffdisplay
unsigned charchar

4

3 に答える 3

6

unsigned char *への変換char *(またはその逆)に関する唯一の問題は、それがエラーになることです。キャストで固定します。

display((char *) buff, len);

注:このキャストは不要です。

printf("char = %c", (char) i);

これで問題ありません:

printf("char = %c", i);

いずれにせよ aをto に渡すことは不可能であるため、フォーマッタは最初に arg を取り%cます(常に に変換されるか、非常にまれなケースでは.)。intcharprintf()intunsigned int

于 2013-02-07T08:46:53.830 に答える
3

必要のない型の安全性について多くのことを心配しているようです。これは C であり C++ ではないため、強力な型付けシステムはありません。「符号ビット」が決して設定されない限り、からunsigned charへの変換char通常無害です。問題を回避するための鍵は、問題を実際に理解することです。次の問題/機能が C に存在します。

  • デフォルトのchar型には、実装定義の署名があります。特にビット単位の操作ではなく、その符号の仮定を行ったり、あらゆる種類の算術演算で使用したりしないでください。charASCII 文字の保存/印刷にのみ使用してください。16 進リテラルと混合しないでください。そうしないと、微妙なバグが発生する可能性があります。
  • C の整数昇格では、 と の間のすべての小さい整数型charunsigned char、結果を保持できる整数型に暗黙的に昇格されます。これは実際には常に になりますint
  • 正式には、異なる型間のポインター変換は未定義の動作になる可能性があります。しかし、unsigned char と char の間のポインター変換は、実際には安全です。
  • 文字リテラル '\0' などはintC の型です。
  • printf および同様の関数は、デフォルトですべての文字パラメーターを int に昇格します。

また、malloc の void* 結果をキャストしています。これは C ではまったく無意味であり、関数プロトタイプが表示されない場合に関数を「デフォルトの int」に変換する C 標準の古いバージョンでは潜在的に有害です。

そして、さまざまな奇妙なロジック関連のバグと悪い習慣があり、私は修正しましたが、詳細にはコメントしません. この変更されたコードを使用します。

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

void display(const char *buff, int len) {

  for(int i = 0; i < len; i++) {
    printf("buff[%d] = %c\n", i, buff[i]);
  }
}

int main() {

  int len = 10;
  unsigned char* buff = malloc(len * sizeof(unsigned char));

  if(buff == NULL)
  {
    // error handling
  }

  char ch = 'A';
  for(int i=0; i<len; i++)
  {
    buff[i] = (unsigned char)ch + i;
    printf("char = %c\n", buff[i]); 
  }


  printf("\nDisplaying array in main.\n");
  for(int i = 0; i < len; i++) {
    printf("buff[%d] = %u\n", i, buff[i]);
  }

  printf("\nDisplaying array in func.\n");
  display((char*)buff, len);

  free(buff);

  return 0;
}
于 2013-02-07T09:46:37.723 に答える
1

任意の整数型から他の同じかそれより大きい整数型への C/C++ キャストは、データ損失を生じないことが保証されています。符号付きフィールドと符号なしフィールド間のキャストは、通常、オーバーフローとアンダーフローの危険を引き起こしますが、実際に変換しているバッファーは、型が実際には void* である生データを指しています。

于 2013-02-07T08:44:38.120 に答える