
(style): int result is returned as long value.
If the return value is long to avoid loss of information,
then you have loss of information.
(スタイル):int型の乗算結果をlong型関数の返却値にすると情報欠損の可能性がある
[(style)truncLongCastReturn]
■LP64コンパイラで桁あふれする例
uint64_t 生涯賃金ブラック(
uint32_t 時給,
uint32_t 稼働時間,
uint32_t 稼働日,
uint32_t 稼働月,
uint32_t 稼働年数
){
return 時給 * 稼働時間 * 稼働日 * 稼働月 * 稼働年数 ;
}
gcc -m64等の
LP64モードコンパイラの場合でも
int型は
32bitの4byteです。
64bitの8byteではありません。
このため
LP64モードといえども
ILP32モードと同様に
int型で計算するで
桁あふれの可能性があります。
特に掛け算に注意してください。
例えば
生涯賃金を [時給*8h*20日*12か月*40年] で計算すると
上記の生涯賃金ブラック関数は
桁あふれします。
■修正例(uint64_t)でキャストする
uint64_t 生涯賃金ホワイト(
uint32_t 時給,
uint32_t 稼働時間,
uint32_t 稼働日,
uint32_t 稼働月,
uint32_t 稼働年数
){
return (uint64_t)時給 * 稼働時間 * 稼働日 * 稼働月 * 稼働年数 ;
}
(uint64_t)でキャストする
64bit型で計算するので
ちょっとやそっとでは桁あふれしません。
■実行結果(桁あふれで生涯賃金が0円になる)
sizeof(int) = 4
生涯賃金ブラック1 = c0000000円
生涯賃金ブラック2 = 80000000円
生涯賃金ブラック3 = 40000000円
生涯賃金ブラック4 = 0円
sizeof(uint64_t) = 8
生涯賃金ホワイト1 = 12c0000000円
生涯賃金ホワイト2 = 2580000000円
生涯賃金ホワイト3 = 3840000000円
生涯賃金ホワイト4 = 4b00000000円
生涯賃金が0円になるのは悲しいですね。
■まとめ(コンパイル可能)
#include <stdio.h>
#include <stdint.h>
#include <limits.h>
//64 bit linux os の intのサイズは8じゃない
uint64_t 生涯賃金ブラック(
uint32_t 時給,
uint32_t 稼働時間,
uint32_t 稼働日,
uint32_t 稼働月,
uint32_t 稼働年数
){
return 時給 * 稼働時間 * 稼働日 * 稼働月 * 稼働年数 ;
}
uint64_t 生涯賃金ホワイト(
uint32_t 時給,
uint32_t 稼働時間,
uint32_t 稼働日,
uint32_t 稼働月,
uint32_t 稼働年数
){
return (uint64_t)時給 * 稼働時間 * 稼働日 * 稼働月 * 稼働年数 ;
}
int main(void) {
printf("sizeof(int) = %zu\n",sizeof(int));
printf("生涯賃金ブラック1 = %lx円\n",生涯賃金ブラック(0x100000,8,20,12,40));
printf("生涯賃金ブラック2 = %lx円\n",生涯賃金ブラック(0x200000,8,20,12,40));
printf("生涯賃金ブラック3 = %lx円\n",生涯賃金ブラック(0x300000,8,20,12,40));
printf("生涯賃金ブラック4 = %lx円\n",生涯賃金ブラック(0x400000,8,20,12,40));
printf("sizeof(uint64_t) = %zu\n",sizeof(uint64_t));
printf("生涯賃金ホワイト1 = %lx円\n",生涯賃金ホワイト(0x100000,8,20,12,40));
printf("生涯賃金ホワイト2 = %lx円\n",生涯賃金ホワイト(0x200000,8,20,12,40));
printf("生涯賃金ホワイト3 = %lx円\n",生涯賃金ホワイト(0x300000,8,20,12,40));
printf("生涯賃金ホワイト4 = %lx円\n",生涯賃金ホワイト(0x400000,8,20,12,40));
}