質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
C++

C++はC言語をもとにしてつくられた最もよく使われるマルチパラダイムプログラミング言語の1つです。オブジェクト指向、ジェネリック、命令型など広く対応しており、多目的に使用されています。

Q&A

解決済

3回答

3084閲覧

size_t型を含んだ演算

Sukabo

総合スコア31

C++

C++はC言語をもとにしてつくられた最もよく使われるマルチパラダイムプログラミング言語の1つです。オブジェクト指向、ジェネリック、命令型など広く対応しており、多目的に使用されています。

0グッド

0クリップ

投稿2020/06/01 07:14

編集2020/06/01 07:15

実行環境 Visual Studio 2019

以下のコードの実行結果は0です。

C++

1#include <cstdlib> 2#include <vector> 3 4int main() 5{ 6 std::vector<int> v; 7 int tmp = v.size() - 1; 8 printf("%d\n", tmp / 3); 9}

以下のコードの実行結果は1431655765です。

C++

1#include <cstdlib> 2#include <vector> 3 4int main() 5{ 6 std::vector<int> v; 7 printf("%d\n", (v.size() - 1) / 3); 8}

v.size()の型がsize_tであることが原因と推測しますが、このような違いが出る理由がはっきり分からないので教えていただきたいです。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答3

0

このような違いが出る理由がはっきり分からないので

size_t符号なしの型です(cpp reference)。

投稿2020/06/01 07:28

maisumakun

総合スコア145183

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

maisumakun

2020/06/01 07:31

符号なし整数がアンダーフローした場合は、2^桁数を法とする演算として処理されることが保証されています。 https://www.jpcert.or.jp/sc-rules/c-int30-c.html 一方、符号付き整数がアンダーフローした場合の動作は未定義です。
Sukabo

2020/06/01 12:08

ご回答ありがとうございます。
guest

0

ベストアンサー

v.size()の型がsize_tであることが原因と推測しますが、このような違いが出る理由がはっきり分からない

短い答え:質問文で言及がある通り、v.size()の型がsize_t(≒intではない)ことが直接原因です。前者は中間結果をint型に代入していますが、後者はそのような型変換が生じないという違いがあります。


長い答え:C++言語における算術変換ルール、動作環境のint型およびsize_t型のサイズ(ビット幅)に依存した結果です。おそらく、32bit Windowsアプリケーションとしてビルド&実行されたのではないでしょうか?

あなたが試した動作環境(OS、コンパイラ)では、下記のように定義されているはずです。

  • int=32bit 符号付き整数型
  • size_t=32bit 符号なし整数型

ここからは説明のため、T型の値xx@Tと表記します。

c++

1int tmp = v.size() - 1; 2printf("%d\n", tmp / 3);
  • 1行目:式v.size()0@size_tを返します。減算-両辺の型をそろえるためリテラル1@int1@size_tに変換され、式0@size_t - 1@size_tの演算結果(-1@size_t相当)は符号無し型のため(2^32)-1=4294967295@size_tとなります。これをint型にキャストすると-1@intに戻り、変数tmpには-1@intが代入されます。
  • 2行目:式-1@int / 3@intの演算結果は0@intです。

c++

1printf("%zu\n", (v.size() - 1) / 3); 2// size_t型には書式"%zu"が対応する(修正済み)
  • 部分式(v.size() - 1)の演算結果が4294967295@size_tとなるまでは前述の通り。
  • 4294967295@size_t / 3@intの除算/両辺の型をそろえるためリテラル3@int3@size_tに変換され、演算結果は1431655765@size_tとなります。

投稿2020/06/01 08:27

yohhoy

総合スコア6191

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

Sukabo

2020/06/01 12:10

ご回答ありがとうございます。 size_tがintにキャストされると勘違いしていました。
guest

0

  • 前者はint tmp = v.size() - 1;として強引にintに変換している.(tmp / 3はint型)
  • 後者はしてない.((v.size() - 1) / 3はsize_t型)

投稿2020/06/01 07:30

fana

総合スコア11654

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

fana

2020/06/01 07:40

関係あるような無いような事柄だけど,size_tの値をprintfで表示する際は"%d"じゃダメかと. →ググってみたら "%zd" と書くらしい.
yohhoy

2020/06/01 07:44

size_t型は常に符号無し(unsigned)整数と定義されるため、厳密には "%zu" 指定が必須ですね。
SHOMI

2020/06/01 07:48

32/64bitでサイズ変わりますしね
fana

2020/06/01 07:53

御指摘感謝. (ググったら "&zu" → コメントに "%zd" と誤記した模様…)
Sukabo

2020/06/01 12:09

そもそも最終的にint型になると勘違いしていました。 ご回答ありがとうございます。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問