C Language
暗黙的および明示的な変換
サーチ…
構文
- 明示的変換(別名「キャスティング」):(タイプ)式
備考
「 明示的変換 」は、一般に「キャスティング」とも呼ばれます。
関数呼び出しにおける整数変換
関数が適切なプロトタイプを持っているとすれば、整数変換の規則に従って関数への呼び出しのために整数が拡張される。C11 6.3.1.3。
6.3.1.3符号付き整数と符号なし整数
整数型の値が_Bool以外の整数型に変換された場合、その値を新しい型で表すことができる場合は変更されません。それ以外の場合、新しい型が符号なしの場合、その値が新しい型の範囲内に入るまで、新しい型で表現できる最大値よりも1を繰り返して加算または減算することによって値が変換されます。
それ以外の場合は、新しい型が署名され、その値をその中で表現することはできません。結果がインプリメンテーションによって定義されるか、インプリメンテーション定義のシグナルが発生します。
明らかに値が収まりきれず、これには明白な意味がないので、通常は、幅のある符号付きの型をより狭い符号付きの型に切り捨てるべきではありません。上記で引用したC標準は、これらのケースを「実装定義」と定義しています。つまり、移植性がありません。
次の例では、 int
が32ビット幅であると仮定しています。
#include <stdio.h>
#include <stdint.h>
void param_u8(uint8_t val) {
printf("%s val is %d\n", __func__, val); /* val is promoted to int */
}
void param_u16(uint16_t val) {
printf("%s val is %d\n", __func__, val); /* val is promoted to int */
}
void param_u32(uint32_t val) {
printf("%s val is %u\n", __func__, val); /* here val fits into unsigned */
}
void param_u64(uint64_t val) {
printf("%s val is " PRI64u "\n", __func__, val); /* Fixed with format string */
}
void param_s8(int8_t val) {
printf("%s val is %d\n", __func__, val); /* val is promoted to int */
}
void param_s16(int16_t val) {
printf("%s val is %d\n", __func__, val); /* val is promoted to int */
}
void param_s32(int32_t val) {
printf("%s val is %d\n", __func__, val); /* val has same width as int */
}
void param_s64(int64_t val) {
printf("%s val is " PRI64d "\n", __func__, val); /* Fixed with format string */
}
int main(void) {
/* Declare integers of various widths */
uint8_t u8 = 127;
uint8_t s64 = INT64_MAX;
/* Integer argument is widened when function parameter is wider */
param_u8(u8); /* param_u8 val is 127 */
param_u16(u8); /* param_u16 val is 127 */
param_u32(u8); /* param_u32 val is 127 */
param_u64(u8); /* param_u64 val is 127 */
param_s8(u8); /* param_s8 val is 127 */
param_s16(u8); /* param_s16 val is 127 */
param_s32(u8); /* param_s32 val is 127 */
param_s64(u8); /* param_s64 val is 127 */
/* Integer argument is truncated when function parameter is narrower */
param_u8(s64); /* param_u8 val is 255 */
param_u16(s64); /* param_u16 val is 65535 */
param_u32(s64); /* param_u32 val is 4294967295 */
param_u64(s64); /* param_u64 val is 9223372036854775807 */
param_s8(s64); /* param_s8 val is implementation defined */
param_s16(s64); /* param_s16 val is implementation defined */
param_s32(s64); /* param_s32 val is implementation defined */
param_s64(s64); /* param_s64 val is 9223372036854775807 */
return 0;
}
関数呼び出しにおけるポインタ変換
void*
へのポインタ変換は暗黙的ですが、他のポインタ変換は明示的でなければなりません。コンパイラは任意のポインタからデータ型への明示的な変換を許可しますが、間違った型付きポインタによるオブジェクトへのアクセスは誤りであり、未定義の動作につながります。これらが許可される唯一のケースは、型が互換性があるか、またはオブジェクトを見ているポインタが文字型であるかどうかです。
#include <stdio.h>
void func_voidp(void* voidp) {
printf("%s Address of ptr is %p\n", __func__, voidp);
}
/* Structures have same shape, but not same type */
struct struct_a {
int a;
int b;
} data_a;
struct struct_b {
int a;
int b;
} data_b;
void func_struct_b(struct struct_b* bp) {
printf("%s Address of ptr is %p\n", __func__, (void*) bp);
}
int main(void) {
/* Implicit ptr conversion allowed for void* */
func_voidp(&data_a);
/*
* Explicit ptr conversion for other types
*
* Note that here although the have identical definitions,
* the types are not compatible, and that the this call is
* erroneous and leads to undefined behavior on execution.
*/
func_struct_b((struct struct_b*)&data_a);
/* My output shows: */
/* func_charp Address of ptr is 0x601030 */
/* func_voidp Address of ptr is 0x601030 */
/* func_struct_b Address of ptr is 0x601030 */
return 0;
}
Modified text is an extract of the original Stack Overflow Documentation
ライセンスを受けた CC BY-SA 3.0
所属していない Stack Overflow