90415


**質問**

標準ライブラリscanfの変換指定子%dと%uの違いがわかりません。  
違いはあるのでしょうか？  
違いがあるのであればどのようなときに違うのかが知りたいです。

* * *

**manマニュアルの説明**

manマニュアルSCANF(3)によると以下の説明がありました。

> d 符号つきの 10進の整数に対応する。 次のポインターは int へのポインターでなければならない。  
>  u 符号なしの 10進の整数に対応する。 次のポインターは unsigned int へのポインターでなければならない。

以下のケースの組み合わせで確認してみました。

  * 変換指定が`%d`、`%u`
  * 変数の型が`int`、`unsigned int`

変数に読み込まれた値に違いが確認できませんでした。  
`gcc -Wall`と`clang -Weverything`でコンパイルしたときに、エラーや警告はでていません。

【コメントを受けて追記】`gcc -Wall -pedantic`でコンパイルしたときは警告が出ています。

**コンパイラ**

  * clang version 10.0.0-4ubuntu1
  * gcc (Ubuntu 9.4.0-1ubuntu1~20.04.1) 9.4.0

**コンパイル時の警告**  
`gcc -Wall -pedantic`でコンパイルすると次の警告が出ます。

[code]

    q6.c: In function ‘main’:
    q6.c:15:19: warning: format ‘%d’ expects argument of type ‘int *’, but argument 2 has type ‘unsigned int *’ [-Wformat=]
       15 |     num = scanf("%d", &ui);
          |                  ~^   ~~~
          |                   |   |
          |                   |   unsigned int *
          |                   int *
          |                  %d
    q6.c:20:19: warning: format ‘%u’ expects argument of type ‘unsigned int *’, but argument 2 has type ‘int *’ [-Wformat=]
       20 |     num = scanf("%u", &i);
          |                  ~^   ~~
          |                   |   |
          |                   |   int *
          |                   unsigned int *
          |                  %u
    
[/code]

**確認したコード**

[code]

    int num;
    int i;
    unsigned int ui;
    
    printf("%s", "int:%d => ");
    num = scanf("%d", &i);
    printf("i=[%x]\n", i);
    printf("num=[%d]\n", num);
    
    printf("%s", "unsigned int:%d => ");
    num = scanf("%d", &ui);
    printf("ui=[%x]\n", ui);
    printf("num=[%d]\n", num);
    
    printf("%s", "int:%u => ");
    num = scanf("%u", &i);
    printf("i=[%x]\n", i);
    printf("num=[%d]\n", num);
    
    printf("%s", "unsigned:int %u => ");
    num = scanf("%u", &ui);
    printf("ui=[%x]\n", ui);
    printf("num=[%d]\n", num);
    
[/code]

出力結果(-100を入力)

[code]

    int:%d => -100
    i=[ffffff9c]
    num=[1]
    unsigned int:%d => -100
    ui=[ffffff9c]
    num=[1]
    int:%u => -100
    i=[ffffff9c]
    num=[1]
    unsigned:int %u => -100
    ui=[ffffff9c]
    num=[1]
    
[/code]


CC BY-SA 4.0
2022-08-07T01:19:23.373
90412
2022-08-07T07:30:54.503
2022-08-07T02:08:17.833
35558
35558
question
c
scanfの変換指定子%dと%uの違いがわからない


C言語の規格書を辿ると

> Matches an optionally signed decimal integer, whose format is the same as
> expected for the subject sequence of the **strtoul** function with the value
> 10 for the **base** argument. The corresponding argument shall be a pointer
> to unsigned integer.

のように書かれていて、`%u`は`strtoul` 相当だそうです。で `strtoul` はというと、`strtol`, `strtoll`,
`strtoul`, and `strtoull` で一緒くたに扱われてて、（`unsigned long` であっても）マイナス記号を受け入れるそうです。  
なので、[cppreferenceの`strtoul`](https://ja.cppreference.com/w/c/string/byte/strtoul)などでもそのように説明されています。

結局、`scanf`の`%d`と`%u`、および`strtol`と`strtoul`の違いとは引数に要求する変数が符号付きか符号無しかの差はありますが、
**入力文字列の解釈に違いはない** となります。


CC BY-SA 4.0
2022-08-07T02:41:19.363
90415
2022-08-07T07:30:54.503
2022-08-07T07:30:54.503
4236
4236
90412
answer