web-dev-qa-db-ja.com

署名されていない文字を読み取るためのscanfの使用

このコードを使用して0〜255(unsigned char)の値を読み取ろうとしています。

#include<stdio.h>
int main(void)
{
    unsigned char value;

    /* To read the numbers between 0 to 255 */
    printf("Please enter a number between 0 and 255 \n");
    scanf("%u",&value);
    printf("The value is %u \n",value);

    return 0;
}

期待どおりに次のコンパイラ警告が表示されます。

警告:形式 ‘%u’はタイプ ‘unsigned int *’を想定していますが、引数2はタイプ ‘unsigned char *’を持っています

そして、これはこのプログラムの私の出力です。

 0〜255の数値を入力してください
 45 
値は45です
セグメンテーションエラー

このコードの実行中にセグメンテーション違反が発生します。

scanfを使用してunsigned char値を読み取る最良の方法は何ですか?

21
user1293997

%u指定子は、それをunsigned charに読み込むときに未定義の動作を引き起こす整数を予期します。 unsigned char指定子%hhuを使用する必要があります。

37
Joe

C99以前では、scanfの未定義の動作によるセグメンテーション違反を回避するために、これだけのために追加の関数を書くことを検討しました。

アプローチ:

#include<stdio.h>
int my_scanf_to_uchar(unsigned char *puchar)
{
  int retval;
  unsigned int uiTemp;
  retval = scanf("%u", &uiTemp);
  if (retval == 1)   
  {
    if (uiTemp < 256) {
      *puchar = uiTemp;
    }
    else {
      retval = 0; //maybe better something like EINVAL
    }
  }
  return retval; 
}

次に、scanf("%u",my_scanf_to_uchar(に置き換えます

私がまだscanfを使用していて、getcharのような別の関数ではないので、これが話題から外れていないことを願っています:)

別のアプローチ(追加機能なし)

if (scanf("%u", &uiTemp) == 1 && uiTemp < 256) { value = uitemp; }
else {/* Do something for conversion error */}
2
grenix