ページ 11

int型のサイズが4でなかったらエラー

Posted: 2010年12月28日(火) 16:38
by みけCAT
開発環境はDev-C++4.9.9.2日本語版、gccのバージョンは3.4.2です。
int型のサイズが4バイトではなかったらエラーにしたいと思い、次のコードを書きました。

コード:

#include <stdio.h>

#if sizeof(int)!=4
#error sizeof(int) must be 4
#endif

int main(void) {
	printf("Hello,World!\n");
	return 0;
}
このコードだと、次のエラーが出ます。
3:11 D:\(中略)\intsizemust4.c missing binary operator before token "("
どうすればうまくいくか教えてくれるとありがたいです。
よろしくお願いします。

Re: int型のサイズが4でなかったらエラー

Posted: 2010年12月28日(火) 16:56
by maru
sizeofはプリプロセスでは処理されないからでしょうね。

コード:

#include "limits.h"
#if INT_MAX!=LONG_MAX
ではいかがでしょうか。

Re: int型のサイズが4でなかったらエラー

Posted: 2010年12月28日(火) 16:57
by やんち
これでどうでしょう。

コード:

#include <stdio.h>

/* #if sizeof(int)!=4*/
#if (__SIZEOF_INT__ != 4)
#error sizeof(int) must be 4
#endif/* (__SIZEOF_INT != 4) */

int main(void) {
    printf("Hello,World!\n");
    return 0;
}

Re: int型のサイズが4でなかったらエラー

Posted: 2010年12月28日(火) 17:12
by みけCAT
maru さんが書きました:sizeofはプリプロセスでは処理されないからでしょうね。

コード:

#include "limits.h"
#if INT_MAX!=LONG_MAX
ではいかがでしょうか。
Longも4バイトでなかった場合、これではチェックできないと思います。
やんち さんが書きました:これでどうでしょう。

コード:

#include <stdio.h>
 
/* #if sizeof(int)!=4*/
#if (__SIZEOF_INT__ != 4)
#error sizeof(int) must be 4
#endif/* (__SIZEOF_INT != 4) */
 
int main(void) {
    printf("Hello,World!\n");
    return 0;
} 
#error sizeof(int) must be 4と言われてしまいました。
次のコードでは、ちゃんと
Hello,World!
4
と表示されます。

コード:

#include <stdio.h>

#if 0
/* #if sizeof(int)!=4*/
#if (__SIZEOF_INT__ != 4)
#error sizeof(int) must be 4
#endif/* (__SIZEOF_INT != 4) */
#endif/*0*/ 
 
int main(void) {
    printf("Hello,World!\n");
    printf("%d\n",sizeof(int));
    return 0;
}

Re: int型のサイズが4でなかったらエラー

Posted: 2010年12月28日(火) 17:34
by ISLe
__SIZEOF_INT__ はgcc4で定義されますがgcc3では定義されないのですね。

コード:

#include <limits.h>
#if UINT_MAX != (1<<(CHAR_BIT*4))-1
#error sizeof(int) must be 4
#endif
これはどうでしょう。
Cygwin版gcc 3.4.4/gcc 4.3.4とvc++2010では使えました。

Re: int型のサイズが4でなかったらエラー

Posted: 2010年12月28日(火) 17:40
by みけCAT
きちんとコンパイルできました。

コード:

#include <stdio.h>

#include <limits.h>
#if UINT_MAX != (1<<(CHAR_BIT*4))-1
#error sizeof(int) must be 4
#endif
 
int main(void) {
    printf("Hello,World!\n");
    return 0;
}
こうするとちゃんとエラーが出ました。

コード:

#include <stdio.h>

#include <limits.h>
#if UINT_MAX != (1<<(CHAR_BIT*2))-1
#error sizeof(int) must be 4
#endif
 
int main(void) {
    printf("Hello,World!\n");
    return 0;
}
ISLeさん、ありがとうございました。

Re: int型のサイズが4でなかったらエラー

Posted: 2010年12月28日(火) 18:30
by Justy
 sizeof(int)==4の評価をコンパイル時にしたいのであれば、これでいけるかもしれません。

コード:

#include <stdio.h>
 
#define static_assert_(eval) typedef char static_error_##__LINE__[(eval)?1: -1]
static_assert_(sizeof(int) == 4);
 
int main(void) {
    printf("Hello,World!\n");
    return 0;
}
[hr]# 12/28 19:53 __LINE__の評価のタイミング問題の為、下記のように訂正。

コード:

#include <stdio.h>

#define define_join2(A, B) define_join2_(A, B)
#define define_join2_(A, B) A ## B

#define static_assert_(eval) typedef char define_join2(static_error_,__LINE__)[(eval)?1: -1]
static_assert_(sizeof(int) == 4);

int main(void) {
    printf("Hello,World!\n");
    return 0;
}

Re: int型のサイズが4でなかったらエラー

Posted: 2010年12月28日(火) 18:34
by みけCAT
Justy さんが書きました: sizeof(int)==4の評価をコンパイル時にしたいのであれば、これでいけるかもしれません。

コード:

#include <stdio.h>
 
#define static_assert_(eval) typedef char static_error_##__LINE__[(eval)?1: -1]
static_assert_(sizeof(int) == 4);
 
int main(void) {
    printf("Hello,World!\n");
    return 0;
}
これでもできました。
しかし、任意のエラーメッセージを出せないので、わかりにくいですね。

Re: int型のサイズが4でなかったらエラー

Posted: 2010年12月28日(火) 18:42
by YuO
みけCAT さんが書きました:

コード:

#if UINT_MAX != (1<<(CHAR_BIT*4))-1
これはundefined behaviorの可能性があります。ISO/IEC 9899:1999 6.5.7 Bitwise shift operators
If the value of the right operand is negative or is greater than or equal to the width of the promoted left operand, the behavior is undefined.
つまり,ビットシフト演算子の右辺の値が左辺のサイズ以上だった場合はundfined behaviorなので,intがCHAR_BIT * 4以下のサイズしか持たない場合,undefined behaviorです。

なので,Justyさんの方法が安全で汎用性を持ちます。
エラーメッセージは変数名で頑張るしかないですが……。

Re: int型のサイズが4でなかったらエラー

Posted: 2010年12月28日(火) 19:50
by Justy
 あ、gccだと __LINE__よりも先に ## を処理してしまいますね。
みけCAT さんが書きました:
Justy さんが書きました:任意のエラーメッセージを出せないので、わかりにくいですね。
 エラーメッセージに変数名を出す環境ならこれで多少はマシになるかも。

コード:

#include <stdio.h>

#define define_join4(A, B, C, D)	define_join4_(A, B, C, D)
#define define_join4_(A, B, C, D)	A ## B ## C ## D

#define static_assert_(eval, tag) typedef char define_join4(static_error_L, __LINE__, _, tag)[(eval)?1: -1]
static_assert_(sizeof(int) == 4, sizeof_int_must_be_4);

int main(void)
{
    printf("Hello,World!\n");
    return 0;
}

Re: int型のサイズが4でなかったらエラー

Posted: 2010年12月28日(火) 19:57
by みけCAT
Justy さんが書きました: あ、gccだと __LINE__よりも先に ## を処理してしまいますね。
みけCAT さんが書きました:
Justy さんが書きました:任意のエラーメッセージを出せないので、わかりにくいですね。
 エラーメッセージに変数名を出す環境ならこれで多少はマシになるかも。

コード:

#include <stdio.h>

#define define_join4(A, B, C, D)	define_join4_(A, B, C, D)
#define define_join4_(A, B, C, D)	A ## B ## C ## D

#define static_assert_(eval, tag) typedef char define_join4(static_error_L, __LINE__, _, tag)[(eval)?1: -1]
static_assert_(sizeof(int) == 4, sizeof_int_must_be_4);

int main(void)
{
    printf("Hello,World!\n");
    return 0;
}
ありがとうございます。
試しにsizeof(int)==2としてみると、
size of array `static_error_L7_sizeof_int_must_be_4' is negative
と表示されました。

Re: int型のサイズが4でなかったらエラー

Posted: 2010年12月29日(水) 01:48
by ISLe
いまさらですが

コード:

#include <limits.h>
#if UINT_MAX != 0xffffffff
#error sizeof(int) must be 4
#endif
で必要十分な気がしました。
もしcharが16ビットだとsizeof(int)が4でも64ビットですけどそれは望まれてない気がするのですが。

gcc 3.4.2で使えるか分かりませんがinttypes.hをインクルードしてint32_t型などを使うようにすると環境を選ばなくなる気がします。

Re: int型のサイズが4でなかったらエラー

Posted: 2010年12月29日(水) 07:11
by みけCAT
ISLe さんが書きました:いまさらですが

コード:

#include <limits.h>
#if UINT_MAX != 0xffffffff
#error sizeof(int) must be 4
#endif
で必要十分な気がしました。
もしcharが16ビットだとsizeof(int)が4でも64ビットですけどそれは望まれてない気がするのですが。
おお。これはわかりやすくていいですね。

コード:

#include <stdio.h>

#include <limits.h>
#if UINT_MAX != 0xffffffff
#error sizeof(int) must be 4
#endif

int main(void) {
	printf("Hello,World!\n");
	return 0;
}
ありがとうございます。