89891


c言語における1の補数について、signed char型(8bitとします)の-2をunsigned char型にキャストした場合、`1111
1101`から`1111 1110`にビットパターンが変化すると理解しているのですが、この理解は正しいでしょうか？

また、iso c99ではmemset関数は次のようになっていました

> 7.21.6.1 memset関数  
>  形式  
>  #include <string.h>  
>  void *memset(void *s, int c, size̲t n);  
>  機能 memset関数は，c（unsigned char型に型変換する。）の値を，sが指すオブジェクトの最初のn文字のそれぞれにコピーする。

私の1の補数の理解が正しいなら、次のコードは2の補数の処理系では`1`，1の補数の処理系では`0`が出力されるのではないかと疑問に思いました。

[code]

    #include <stdio.h>
    #include <string.h>
    #include <stdlib.h>
    
    int main()
    {
        signed char *s = malloc(sizeof(signed char) * 1);
        if (s == NULL)
            return 1;
        memset(s, -2, sizeof(signed char) * 1);
        printf("%d\n", s[0] == -2);
    }
    
[/code]

もしそうだとすると、このコードはmemsetを使用する以上、unsigned charからsigned
charへの暗黙の型変換が発生し、処理系定義の動作とならざるを得ないと理解していいでしょうか？（私の規格の理解や、コードに問題点があればご指摘お願いします）


CC BY-SA 4.0
2022-07-09T19:18:31.860
89873
2022-07-10T23:30:37.923
2022-07-10T02:57:04.917
44647
44647
question
c
1の補数とmemsetについて


> 2の補数の処理系では`1`，1の補数の処理系では`0`が出力されるのではないか

どちらの処理系においても`-2`のビット表現は一意に定まり、unsigned
charへ型変換が挟まろうとビット化けするわけではない、という理解です。そのため、処理系によらず常に`1`が出力されると思います。

* * *

なお、C++言語ではC++20にて[符号付き整数型が2の補数表現であることを規定](https://cpprefjp.github.io/lang/cpp20/signed_integers_are_twos_complement.html)されました。つまり1の補数表現をの処理系は扱わないことになっています。言語は異なりますが、特段必要なければ1の補数は忘れてもいいのかもしれません。


CC BY-SA 4.0
2022-07-10T00:25:29.717
89876
2022-07-10T00:25:29.717
4236
89873
answer


１の補数系マシンってことだと２１世紀である現在は[完全に絶滅](https://ja.stackoverflow.com/questions/12855/)していますし、過去のマシンで有名どころとなると
[CDC6600](https://ja.wikipedia.org/wiki/CDC_6600) とか
[PDP-11](https://ja.wikipedia.org/wiki/PDP-11) ってことになりそうですが

  * CDC6600 は 1964 年
  * PDP-11 は 1970 年
  * [ANSI-C](https://ja.stackoverflow.com/questions/39922/) は 1989 年

であるため、これらのマシンに [c](/questions/tagged/c "'c' のタグが付いた質問を表示") コンパイラが実装されていたとしても
C89 なり C99 なりに合致しているわけがなくて、なので言語規格書の文言を追っかけても意味がないです。

`memset()` の第二引数は `int c` なので `-2` を渡すことは問題なくできます。そして「 `unsigned char`
型に変換する」の意味は言語規格書の文言によらず単にビットパターンを変更せずに解釈を変えるだけ、つまり単純に上位ビットを無視するということで、よって `-2`
のビットパターン下位ビット `1111 1101` がそのままメモリに書きこまれます。そのメモリから `signed char`
として値を取り出し汎整数拡張させれば単に `-2` なので、提示命題は `1` が出力されるのでしょう。

そもそも `CDC6600` はバイト＝１２ビットだし１文字は６ビットです。なのでオイラの上記説明も成り立ちませんしそもそも C89
の文言をそのまま解釈しても話が難しくなるだけです。

その辺の絶滅した過去をいくら考えても現代マシンには適用できないし、いさぎよく忘れ去ってしまいましょう。


CC BY-SA 4.0
2022-07-10T23:30:37.923
89891
2022-07-10T23:30:37.923
8589
89873
answer