SOのための小さな教育ツールを準備したいと思います。これは、初心者(および中級)プログラマーがC、C++、およびそれらのプラットフォームでの不当な前提を認識して挑戦するのに役立つはずです。
例:
私は、SOでの経験から、通常は経験の浅い/半経験のある主流の開発者によって作成され、さまざまなマシンでそれらが壊れる方法を記録する「もっともらしい」仮定を実行する、小さなテストプログラムをさまざまなプラットフォームで実行できると考えました。
これの目標は、何かをすることが「安全」であることを証明することではありません(実行することは不可能であり、テストが壊れた場合にのみ何も証明しません)代わりに、最も理解の難しい個人動作が未定義または実装定義である場合に、最も目立たない式が別のマシンでどのように中断するか。
これを達成するために私はあなたに尋ねたいと思います:
テストおもちゃの現在のバージョンは次のとおりです。
#include <stdio.h>
#include <limits.h>
#include <stdlib.h>
#include <stddef.h>
int count=0;
int total=0;
void expect(const char *info, const char *expr)
{
printf("..%s\n but '%s' is false.\n",info,expr);
fflush(stdout);
count++;
}
#define EXPECT(INFO,EXPR) if (total++,!(EXPR)) expect(INFO,#EXPR)
/* stack check..How can I do this better? */
ptrdiff_t check_grow(int k, int *p)
{
if (p==0) p=&k;
if (k==0) return &k-p;
else return check_grow(k-1,p);
}
#define BITS_PER_INT (sizeof(int)*CHAR_BIT)
int bits_per_int=BITS_PER_INT;
int int_max=INT_MAX;
int int_min=INT_MIN;
/* for 21 - left to right */
int ltr_result=0;
unsigned ltr_fun(int k)
{
ltr_result=ltr_result*10+k;
return 1;
}
int main()
{
printf("We like to think that:\n");
/* characters */
EXPECT("00 we have ASCII",('A'==65));
EXPECT("01 A-Z is in a block",('Z'-'A')+1==26);
EXPECT("02 big letters come before small letters",('A'<'a'));
EXPECT("03 a char is 8 bits",CHAR_BIT==8);
EXPECT("04 a char is signed",CHAR_MIN==SCHAR_MIN);
/* integers */
EXPECT("05 int has the size of pointers",sizeof(int)==sizeof(void*));
/* not true for Windows-64 */
EXPECT("05a long has at least the size of pointers",sizeof(long)>=sizeof(void*));
EXPECT("06 integers are 2-complement and wrap around",(int_max+1)==(int_min));
EXPECT("07 integers are 2-complement and *always* wrap around",(INT_MAX+1)==(INT_MIN));
EXPECT("08 overshifting is okay",(1<<bits_per_int)==0);
EXPECT("09 overshifting is *always* okay",(1<<BITS_PER_INT)==0);
{
int t;
EXPECT("09a minus shifts backwards",(t=-1,(15<<t)==7));
}
/* pointers */
/* Suggested by jalf */
EXPECT("10 void* can store function pointers",sizeof(void*)>=sizeof(void(*)()));
/* execution */
EXPECT("11 Detecting how the stack grows is easy",check_grow(5,0)!=0);
EXPECT("12 the stack grows downwards",check_grow(5,0)<0);
{
int t;
/* suggested by jk */
EXPECT("13 The smallest bits always come first",(t=0x1234,0x34==*(char*)&t));
}
{
/* Suggested by S.Lott */
int a[2]={0,0};
int i=0;
EXPECT("14 i++ is strictly left to right",(i=0,a[i++]=i,a[0]==1));
}
{
struct {
char c;
int i;
} char_int;
EXPECT("15 structs are packed",sizeof(char_int)==(sizeof(char)+sizeof(int)));
}
{
EXPECT("16 malloc()=NULL means out of memory",(malloc(0)!=NULL));
}
/* suggested by David Thornley */
EXPECT("17 size_t is unsigned int",sizeof(size_t)==sizeof(unsigned int));
/* this is true for C99, but not for C90. */
EXPECT("18 a%b has the same sign as a",((-10%3)==-1) && ((10%-3)==1));
/* suggested by nos */
EXPECT("19-1 char<short",sizeof(char)<sizeof(short));
EXPECT("19-2 short<int",sizeof(short)<sizeof(int));
EXPECT("19-3 int<long",sizeof(int)<sizeof(long));
EXPECT("20 ptrdiff_t and size_t have the same size",(sizeof(ptrdiff_t)==sizeof(size_t)));
#if 0
{
/* suggested by R. */
/* this crashed on TC 3.0++, compact. */
char buf[10];
EXPECT("21 You can use snprintf to append a string",
(snprintf(buf,10,"OK"),snprintf(buf,10,"%s!!",buf),strcmp(buf,"OK!!")==0));
}
#endif
EXPECT("21 Evaluation is left to right",
(ltr_fun(1)*ltr_fun(2)*ltr_fun(3)*ltr_fun(4),ltr_result==1234));
{
#ifdef __STDC_IEC_559__
int STDC_IEC_559_is_defined=1;
#else
/* This either means, there is no FP support
*or* the compiler is not C99 enough to define __STDC_IEC_559__
*or* the FP support is not IEEE compliant. */
int STDC_IEC_559_is_defined=0;
#endif
EXPECT("22 floating point is always IEEE",STDC_IEC_559_is_defined);
}
printf("From what I can say with my puny test cases, you are %d%% mainstream\n",100-(100*count)/total);
return 0;
}
ああ、そして私がこのコミュニティーwikiを最初から作成したのは、人々がこれを読んだときに私のばらばらを編集したいと思っているからです。
[〜#〜] update [〜#〜]入力いただきありがとうございます。私はあなたの答えからいくつかのケースを追加しました、そしてGregが提案したようにこれのためにgithubをセットアップできるかどうかを確認します。
[〜#〜] update [〜#〜]:このためのgithubリポジトリを作成しました。ファイルは "gotcha.c"です:
パッチまたは新しいアイデアをここに回答してください。ここでそれらを議論または明確化できます。その後、それらをgotcha.cにマージします。
以下を含む部分式の評価の順序
+
、-
、=
、*
、/
)、ただし例外:&&
および||
)、?:
)、および,
)is nspecified
例えば
int Hello()
{
return printf("Hello"); /* printf() returns the number of
characters successfully printed by it
*/
}
int World()
{
return printf("World !");
}
int main()
{
int a = Hello() + World(); //might print Hello World! or World! Hello
/** ^
|
Functions can be called in either order
**/
return 0;
}
sdcc 29.7/ucSim/Z80
We like to think that:
..09a minus shifts backwards
but '(t=-1,(15<<t)==7)' is false.
..19-2 short<int
but 'sizeof(short)<sizeof(int)' is false.
..22 floating point is always IEEE
but 'STDC_IEC_559_is_defined' is false.
..25 pointer arithmetic works outside arrays
but '(diff=&var.int2-&var.int1, &var.int1+diff==&var.int2)' is false.
From what I can say with my puny test cases, you are Stop at 0x0013f3: (106) Invalid instruction 0x00dd
printfがクラッシュします。 「O_O」
gcc 4.4@x86_64-suse-linux
We like to think that:
..05 int has the size of pointers
but 'sizeof(int)==sizeof(void*)' is false.
..08 overshifting is okay
but '(1<<bits_per_int)==0' is false.
..09a minus shifts backwards
but '(t=-1,(15<<t)==7)' is false.
..14 i++ is strictly left to right
but '(i=0,a[i++]=i,a[0]==1)' is false.
..15 structs are packed
but 'sizeof(char_int)==(sizeof(char)+sizeof(int))' is false.
..17 size_t is unsigned int
but 'sizeof(size_t)==sizeof(unsigned int)' is false.
..26 sizeof() does not evaluate its arguments
but '(i=10,sizeof(char[((i=20),10)]),i==10)' is false.
From what I can say with my puny test cases, you are 79% mainstream
gcc 4.4@x86_64-suse-linux(-O2)
We like to think that:
..05 int has the size of pointers
but 'sizeof(int)==sizeof(void*)' is false.
..08 overshifting is okay
but '(1<<bits_per_int)==0' is false.
..14 i++ is strictly left to right
but '(i=0,a[i++]=i,a[0]==1)' is false.
..15 structs are packed
but 'sizeof(char_int)==(sizeof(char)+sizeof(int))' is false.
..17 size_t is unsigned int
but 'sizeof(size_t)==sizeof(unsigned int)' is false.
..26 sizeof() does not evaluate its arguments
but '(i=10,sizeof(char[((i=20),10)]),i==10)' is false.
From what I can say with my puny test cases, you are 82% mainstream
clang 2.7@x86_64-suse-linux
We like to think that:
..05 int has the size of pointers
but 'sizeof(int)==sizeof(void*)' is false.
..08 overshifting is okay
but '(1<<bits_per_int)==0' is false.
..09a minus shifts backwards
but '(t=-1,(15<<t)==7)' is false.
..14 i++ is strictly left to right
but '(i=0,a[i++]=i,a[0]==1)' is false.
..15 structs are packed
but 'sizeof(char_int)==(sizeof(char)+sizeof(int))' is false.
..17 size_t is unsigned int
but 'sizeof(size_t)==sizeof(unsigned int)' is false.
..21a Function Arguments are evaluated right to left
but '(gobble_args(0,ltr_fun(1),ltr_fun(2),ltr_fun(3),ltr_fun(4)),ltr_result==4321)' is false.
ltr_result is 1234 in this case
..25a pointer arithmetic works outside arrays
but '(diff=&p1-&p2, &p2+diff==&p1)' is false.
..26 sizeof() does not evaluate its arguments
but '(i=10,sizeof(char[((i=20),10)]),i==10)' is false.
From what I can say with my puny test cases, you are 72% mainstream
open64 4.2.3@x86_64-suse-linux
We like to think that:
..05 int has the size of pointers
but 'sizeof(int)==sizeof(void*)' is false.
..08 overshifting is okay
but '(1<<bits_per_int)==0' is false.
..09a minus shifts backwards
but '(t=-1,(15<<t)==7)' is false.
..15 structs are packed
but 'sizeof(char_int)==(sizeof(char)+sizeof(int))' is false.
..17 size_t is unsigned int
but 'sizeof(size_t)==sizeof(unsigned int)' is false.
..21a Function Arguments are evaluated right to left
but '(gobble_args(0,ltr_fun(1),ltr_fun(2),ltr_fun(3),ltr_fun(4)),ltr_result==4321)' is false.
ltr_result is 1234 in this case
..25a pointer arithmetic works outside arrays
but '(diff=&p1-&p2, &p2+diff==&p1)' is false.
..26 sizeof() does not evaluate its arguments
but '(i=10,sizeof(char[((i=20),10)]),i==10)' is false.
From what I can say with my puny test cases, you are 75% mainstream
インテル11.1@x86_64-suse-linux
We like to think that:
..05 int has the size of pointers
but 'sizeof(int)==sizeof(void*)' is false.
..08 overshifting is okay
but '(1<<bits_per_int)==0' is false.
..09a minus shifts backwards
but '(t=-1,(15<<t)==7)' is false.
..14 i++ is strictly left to right
but '(i=0,a[i++]=i,a[0]==1)' is false.
..15 structs are packed
but 'sizeof(char_int)==(sizeof(char)+sizeof(int))' is false.
..17 size_t is unsigned int
but 'sizeof(size_t)==sizeof(unsigned int)' is false.
..21a Function Arguments are evaluated right to left
but '(gobble_args(0,ltr_fun(1),ltr_fun(2),ltr_fun(3),ltr_fun(4)),ltr_result==4321)' is false.
ltr_result is 1234 in this case
..26 sizeof() does not evaluate its arguments
but '(i=10,sizeof(char[((i=20),10)]),i==10)' is false.
From what I can say with my puny test cases, you are 75% mainstream
Turbo C++/DOS/Small Memory
We like to think that:
..09a minus shifts backwards
but '(t=-1,(15<<t)==7)' is false.
..16 malloc()=NULL means out of memory
but '(malloc(0)!=NULL)' is false.
..19-2 short<int
but 'sizeof(short)<sizeof(int)' is false.
..22 floating point is always IEEE
but 'STDC_IEC_559_is_defined' is false.
..25 pointer arithmetic works outside arrays
but '(diff=&var.int2-&var.int1, &var.int1+diff==&var.int2)' is false.
..25a pointer arithmetic works outside arrays
but '(diff=&p1-&p2, &p2+diff==&p1)' is false.
From what I can say with my puny test cases, you are 81% mainstream
Turbo C++/DOS/Medium Memory
We like to think that:
..09a minus shifts backwards
but '(t=-1,(15<<t)==7)' is false.
..10 void* can store function pointers
but 'sizeof(void*)>=sizeof(void(*)())' is false.
..16 malloc()=NULL means out of memory
but '(malloc(0)!=NULL)' is false.
..19-2 short<int
but 'sizeof(short)<sizeof(int)' is false.
..22 floating point is always IEEE
but 'STDC_IEC_559_is_defined' is false.
..25 pointer arithmetic works outside arrays
but '(diff=&var.int2-&var.int1, &var.int1+diff==&var.int2)' is false.
..25a pointer arithmetic works outside arrays
but '(diff=&p1-&p2, &p2+diff==&p1)' is false.
From what I can say with my puny test cases, you are 78% mainstream
ターボC++/DOS /コンパクトメモリ
We like to think that:
..05 int has the size of pointers
but 'sizeof(int)==sizeof(void*)' is false.
..09a minus shifts backwards
but '(t=-1,(15<<t)==7)' is false.
..16 malloc()=NULL means out of memory
but '(malloc(0)!=NULL)' is false.
..19-2 short<int
but 'sizeof(short)<sizeof(int)' is false.
..20 ptrdiff_t and size_t have the same size
but '(sizeof(ptrdiff_t)==sizeof(size_t))' is false.
..22 floating point is always IEEE
but 'STDC_IEC_559_is_defined' is false.
..25 pointer arithmetic works outside arrays
but '(diff=&var.int2-&var.int1, &var.int1+diff==&var.int2)' is false.
..25a pointer arithmetic works outside arrays
but '(diff=&p1-&p2, &p2+diff==&p1)' is false.
From what I can say with my puny test cases, you are 75% mainstream
cl65 @ Commodore PET(副エミュレータ)
後で更新します:
Borland C++ Builder 6.0 on Windows XP
..04 a char is signed
but 'CHAR_MIN==SCHAR_MIN' is false.
..08 overshifting is okay
but '(1<<bits_per_int)==0' is false.
..09 overshifting is *always* okay
but '(1<<BITS_PER_INT)==0' is false.
..09a minus shifts backwards
but '(t=-1,(15<<t)==7)' is false.
..15 structs are packed
but 'sizeof(char_int)==(sizeof(char)+sizeof(int))' is false.
..16 malloc()=NULL means out of memory
but '(malloc(0)!=NULL)' is false.
..19-3 int<long
but 'sizeof(int)<sizeof(long)' is false.
..22 floating point is always IEEE
but 'STDC_IEC_559_is_defined' is false.
From what I can say with my puny test cases, you are 71% mainstream
Visual Studio Express 2010 C++ CLR、Windows 7 64ビット
(CLRコンパイラは純粋なCをサポートしていないため、C++としてコンパイルする必要があります)
We like to think that:
..08 overshifting is okay
but '(1<<bits_per_int)==0' is false.
..09a minus shifts backwards
but '(t=-1,(15<<t)==7)' is false.
..14 i++ is structly left to right
but '(i=0,a[i++]=i,a[0]==1)' is false.
..15 structs are packed
but 'sizeof(char_int)==(sizeof(char)+sizeof(int))' is false.
..19-3 int<long
but 'sizeof(int)<sizeof(long)' is false.
..22 floating point is always IEEE
but 'STDC_IEC_559_is_defined' is false.
From what I can say with my puny test cases, you are 78% mainstream
MINGW64(gcc-4.5.2プレリリース)
- http://mingw-w64.sourceforge.net/
We like to think that:
..05 int has the size of pointers
but 'sizeof(int)==sizeof(void*)' is false.
..05a long has at least the size of pointers
but 'sizeof(long)>=sizeof(void*)' is false.
..08 overshifting is okay
but '(1<<bits_per_int)==0' is false.
..09a minus shifts backwards
but '(t=-1,(15<<t)==7)' is false.
..14 i++ is structly left to right
but '(i=0,a[i++]=i,a[0]==1)' is false.
..15 structs are packed
but 'sizeof(char_int)==(sizeof(char)+sizeof(int))' is false.
..17 size_t is unsigned int
but 'sizeof(size_t)==sizeof(unsigned int)' is false.
..19-3 int<long
but 'sizeof(int)<sizeof(long)' is false.
..22 floating point is always IEEE
but 'STDC_IEC_559_is_defined' is false.
From what I can say with my puny test cases, you are 67% mainstream
64ビットWindowsはLLP64モデルを使用します。int
とlong
はどちらも32ビットとして定義されています。つまり、どちらもポインターに対して十分な長さではありません。
avr-gcc 4.3.2/ATmega168(Arduino Diecimila)
失敗した仮定は次のとおりです。
..14 i++ is structly left to right
..16 malloc()=NULL means out of memory
..19-2 short<int
..21 Evaluation is left to right
..22 floating point is always IEEE
Atmega168には16ビットPCがありますが、コードとデータは別々のアドレス空間にあります。大きなAtmegaには22ビットPCがあります。
-Arch ppcでコンパイルされたMacOSX 10.6上のgcc 4.2.1
We like to think that:
..09a minus shifts backwards
but '(t=-1,(15<<t)==7)' is false.
..13 The smallest bits come always first
but '(t=0x1234,0x34==*(char*)&t)' is false.
..14 i++ is structly left to right
but '(i=0,a[i++]=i,a[0]==1)' is false.
..15 structs are packed
but 'sizeof(char_int)==(sizeof(char)+sizeof(int))' is false.
..19-3 int<long
but 'sizeof(int)<sizeof(long)' is false.
..22 floating point is always IEEE
but 'STDC_IEC_559_is_defined' is false.
From what I can say with my puny test cases, you are 78% mainstream
ずっと前に、私は持っている教科書からCを教えていました
printf("sizeof(int)=%d\n", sizeof(int));
サンプルの質問として。 sizeof
はint
ではなくsize_t
型の値を生成するため、この実装ではint
は16ビットであり、size_t
は32、それはビッグエンディアンでした。 (プラットフォームは680x0ベースのMacintosh上のLightspeed Cでした。私はそれがずっと前だったと言った。)
人々が行う++
および--
の仮定を含める必要があります。
a[i++]= i;
たとえば、は構文的には合法ですが、推論するには多すぎることに応じてさまざまな結果が生成されます。
++
(または--
)と2回以上発生する変数を含むステートメントは問題です。
とても興味深い!
私がそれについて考えることができる他の事柄はチェックするのに役立つかもしれません:
関数ポインターとデータポインターは同じアドレス空間に存在しますか? (DOSスモールモードのようなハーバードアーキテクチャマシンの不具合。ただし、それをどのようにテストするかはわかりません。)
nULLデータポインターを受け取り、それを適切な整数型にキャストすると、数値は0になりますか? (一部の非常に古いマシンでの破損---参照 http://c-faq.com/null/machexamp.html 。)関数ポインタによる同上。また、値が異なる場合があります。
対応するストレージオブジェクトの最後を超えてポインタをインクリメントし、その後再びインクリメントすると、適切な結果が得られますか? (私はこれが実際に壊れるマシンを知りませんが、C仕様では、ポインタについて考える t(a)配列の内容、または(b)配列の直後の要素、または(c)NULLのいずれかを指します。参照 http://c-faq.com/aryptr/non0based.html =。)
異なるストレージオブジェクトへの2つのポインタを<と>で比較すると、一貫した結果が得られますか? (私はエキゾチックなセグメントベースのマシンでこれが壊れることを想像することができます;仕様はそのような比較を禁止しているので、コンパイラーはポインターのオフセット部分のみを比較する権利があり、セグメント部分は比較できません。)
うーん。もう少し考えてみます。
編集: 優れたC FAQへの明確なリンクをいくつか追加しました。
「正しくない」仮定の2つの非常に異なるクラスを区別する努力をする必要があると思います。良い半分(右シフトと符号拡張、ASCII互換エンコーディング、メモリは線形、データと関数ポインタは互換性があるなど)はmost Cコーダーが作成するかなり合理的な仮定であり、 Cが今日設計されていて、レガシーのIBMジャンクの祖先がなかった場合、標準の一部として含まれます。残りの半分(メモリエイリアシングに関連するもの、入力メモリと出力メモリがオーバーラップするときのライブラリ関数の動作、ポインタがint
に収まる、またはプロトタイプなしでmalloc
を使用できるという32ビットの仮定、その呼び出し規則は、可変関数と非可変関数で同じです...)最近のコンパイラが実行する最適化と競合するか、64ビットマシンまたは他の新しいテクノロジへの移行と競合します。
_EXPECT("## pow() gives exact results for integer arguments", pow(2, 4) == 16);
_
もう1つは、fopen
のテキストモードに関するものです。ほとんどのプログラマーは、テキストとバイナリーが同じ(Unix)か、テキストモードが_\r
_文字(Windows)を追加すると想定しています。しかし、Cは固定幅のレコードを使用するシステムに移植されています。テキストファイルのfputc('\n', file)
は、ファイルサイズがレコード長の倍数になるまでスペースなどを追加することを意味します。
そしてここに私の結果があります:
gcc(Ubuntu 4.4.3-4ubuntu5)4.4.3 on x86-64
_We like to think that:
..05 int has the size of pointers
but 'sizeof(int)==sizeof(void*)' is false.
..08 overshifting is okay
but '(1<<bits_per_int)==0' is false.
..09a minus shifts backwards
but '(t=-1,(15<<t)==7)' is false.
..14 i++ is strictly left to right
but '(i=0,a[i++]=i,a[0]==1)' is false.
..15 structs are packed
but 'sizeof(char_int)==(sizeof(char)+sizeof(int))' is false.
..17 size_t is unsigned int
but 'sizeof(size_t)==sizeof(unsigned int)' is false.
From what I can say with my puny test cases, you are 78% mainstream
_
ここに楽しいものがあります:この関数の何が問題になっていますか?
float sum(unsigned int n, ...)
{
float v = 0;
va_list ap;
va_start(ap, n);
while (n--)
v += va_arg(ap, float);
va_end(ap);
return v;
}
[回答(rot13):Inevnqvp nethzragf borl gur byq X&E cebzbgvba ehyrf、juvpu zrnaf lbh pnaabg hfr 'sybng'(be 'pune' be 'fubeg')va in_net! Naq gur pbzcvyre vf erdhverq abg gb gerng guvf nf n pbzcvyr-gvzr reebe。 (TPP qbrf rzvg n jneavat、gubhtu。)]
浮動小数点表現による離散化エラー。たとえば、標準の式を使用して二次方程式を解いたり、有限差分を使用して導関数を近似したり、標準の式を使用して分散を計算したりすると、類似した数値間の差の計算により精度が失われます。線形システムを解くためのガウスアルゴリズムは、丸め誤差が累積するので良くありません。したがって、QRまたはLU分解、コレスキー分解、SVDなど)を使用します。浮動小数点数の加算は連想的ではありません。 、無限、およびNaN値a + b-a≠b。
文字列:文字、コードポイント、コード単位の違い。さまざまなオペレーティングシステムでのUnicodeの実装方法。 Unicodeエンコーディング。 C++では、任意のUnicodeファイル名のファイルを移植可能な方法で開くことはできません。
スレッドなしでも競合状態:ファイルが存在するかどうかをテストすると、結果はいつでも無効になる可能性があります。
ERROR_SUCCESS
= 0
整数サイズのチェックを含めます。ほとんどの人は、intはshortよりもcharよりも大きいと想定しています。ただし、これらはすべてfalseである可能性があります:sizeof(char) < sizeof(int); sizeof(short) < sizeof(int); sizeof(char) < sizeof(short)
このコードは失敗する可能性があります(非境界整列アクセスにクラッシュ)
unsigned char buf[64];
int i = 234;
int *p = &buf[1];
*p = i;
i = *p;
前提条件が満たされない実装ではプログラムがクラッシュする可能性が高いため、C内から簡単にテストできないものもあります。
「ポインタ値の変数を使用して何を実行しても問題ありません。逆参照する場合にのみ、有効なポインタ値を含める必要があります。」
void noop(void *p); /* A no-op function that the compiler doesn't know to optimize away */
int main () {
char *p = malloc(1);
free(p);
noop(p); /* may crash in implementations that verify pointer accesses */
noop(p - 42000); /* and if not the previous instruction, maybe this one */
}
トラップ表現を許可されている整数型および浮動小数点型(unsigned char
以外)と同じです。
「整数計算は折り返します。このため、このプログラムは大きな負の整数を出力します。」
#include <stdio.h>
int main () {
printf("%d\n", INT_MAX+1); /* may crash due to signed integer overflow */
return 0;
}
(C89のみ。)「main
の終わりから落ちても大丈夫です。」
#include <stdio.h>
int main () {
puts("Hello.");
} /* The status code is 7 on many implementations. */
まあまだ言及されていない古典的な移植性の仮定は
組み込みデータ型に関するいくつかのこと:
char
とsigned char
は、実際には2つの異なる型です(同じ符号付き整数型を参照するint
とsigned int
とは異なります)。-3/5
は0
または-1
を返す可能性があります。 1つのオペランドが負の場合のゼロへの丸めは、C99以上およびC++ 0x以上でのみ保証されます。int
が少なくとも 16ビット、long
が少なくとも 32ビット、long long
には少なくとも 64ビットがあります。 float
は、少なくとも6つの上位10進数を正しく表すことができます。 double
は、少なくとも10桁の上位10進数を正しく表すことができます。確かに、mostマシンでは、2の補数とIEEE 754フロートがあります。
編集:プログラムの最新バージョンに更新されました
Solaris-SPARC
32ビットのgcc 3.4.6
We like to think that:
..08 overshifting is okay
but '(1<<bits_per_int)==0' is false.
..09 overshifting is *always* okay
but '(1<<BITS_PER_INT)==0' is false.
..09a minus shifts backwards
but '(t=-1,(15<<t)==7)' is false.
..13 The smallest bits always come first
but '(t=0x1234,0x34==*(char*)&t)' is false.
..14 i++ is strictly left to right
but '(i=0,a[i++]=i,a[0]==1)' is false.
..15 structs are packed
but 'sizeof(char_int)==(sizeof(char)+sizeof(int))' is false.
..19-3 int<long
but 'sizeof(int)<sizeof(long)' is false.
..22 floating point is always IEEE
but 'STDC_IEC_559_is_defined' is false.
From what I can say with my puny test cases, you are 72% mainstream
64ビットのgcc 3.4.6
We like to think that:
..05 int has the size of pointers
but 'sizeof(int)==sizeof(void*)' is false.
..08 overshifting is okay
but '(1<<bits_per_int)==0' is false.
..09 overshifting is *always* okay
but '(1<<BITS_PER_INT)==0' is false.
..09a minus shifts backwards
but '(t=-1,(15<<t)==7)' is false.
..13 The smallest bits always come first
but '(t=0x1234,0x34==*(char*)&t)' is false.
..14 i++ is strictly left to right
but '(i=0,a[i++]=i,a[0]==1)' is false.
..15 structs are packed
but 'sizeof(char_int)==(sizeof(char)+sizeof(int))' is false.
..17 size_t is unsigned int
but 'sizeof(size_t)==sizeof(unsigned int)' is false.
..22 floating point is always IEEE
but 'STDC_IEC_559_is_defined' is false.
From what I can say with my puny test cases, you are 68% mainstream
sUNStudio 11 32ビット
We like to think that:
..08 overshifting is okay
but '(1<<bits_per_int)==0' is false.
..09a minus shifts backwards
but '(t=-1,(15<<t)==7)' is false.
..13 The smallest bits always come first
but '(t=0x1234,0x34==*(char*)&t)' is false.
..14 i++ is strictly left to right
but '(i=0,a[i++]=i,a[0]==1)' is false.
..15 structs are packed
but 'sizeof(char_int)==(sizeof(char)+sizeof(int))' is false.
..19-3 int<long
but 'sizeof(int)<sizeof(long)' is false.
From what I can say with my puny test cases, you are 79% mainstream
sUNStudio 11 64ビット
We like to think that:
..05 int has the size of pointers
but 'sizeof(int)==sizeof(void*)' is false.
..08 overshifting is okay
but '(1<<bits_per_int)==0' is false.
..09a minus shifts backwards
but '(t=-1,(15<<t)==7)' is false.
..13 The smallest bits always come first
but '(t=0x1234,0x34==*(char*)&t)' is false.
..14 i++ is strictly left to right
but '(i=0,a[i++]=i,a[0]==1)' is false.
..15 structs are packed
but 'sizeof(char_int)==(sizeof(char)+sizeof(int))' is false.
..17 size_t is unsigned int
but 'sizeof(size_t)==sizeof(unsigned int)' is false.
From what I can say with my puny test cases, you are 75% mainstream
これはどう:
データポインターを有効な関数ポインターと同じにすることはできません。
これは、すべてのフラットモデル、MS-DOS TINY、LARGE、およびHUGEモデルではTRUE、MS-DOS SMALLモデルではfalse、MEDIUMモデルおよびCOMPACTモデルではほぼ常にfalse(ロードアドレスによって異なりますが、実際には古いDOSが必要です)それを真実にする)。
このためのテストを書くことはできません
さらに悪いことに、ptrdiff_tにキャストされたポインタが比較される場合があります。これはMS-DOS LARGEモデルには当てはまりません(LARGEとHUGEの唯一の違いは、HUGEがポインターを正規化するコンパイラーコードを追加することです)。
この爆弾がハードに配置されている環境では64Kを超えるバッファーが割り当てられないため、テストを記述できません。それを示すコードは他のプラットフォームでクラッシュします。
この特定のテストは、現在機能していない1つのシステムに合格します(mallocの内部に依存することに注意してください)。
char *ptr1 = malloc(16);
char *ptr2 = malloc(16);
if ((ptrdiff_t)ptr2 - 0x20000 == (ptrdiff_t)ptr1)
printf("We like to think that unrelated pointers are equality comparable when cast to the appropriate integer, but they're not.");
テキストモード(fopen("filename", "r")
)を使用して、あらゆる種類のテキストファイルを読み取ることができます。
これは理論的にはうまく機能するはずですがうまく機能しますが、コードでftell()
を使用し、テキストファイルにUNIXスタイルの行末がある場合、 Windows標準ライブラリのバージョンであるftell()
は、無効な値を返すことがよくあります。解決策は、代わりにバイナリモードを使用することです(fopen("filename", "rb")
)。
過剰な量の右シフトはどうですか?それは標準で許可されていますか、それともテストする価値がありますか?
標準Cは次のプログラムの動作を指定していますか?
void print_string(char * st) { char ch; while((ch = * st ++)!= 0) putch( ch);/*これが定義されていると仮定します*/ } int main(void) { print_string( "Hello"); return 0; }
私が使用している少なくとも1つのコンパイラでは、print_stringへの引数が "char const * "。このような制限は規格で許可されていますか?
一部のシステムでは、アライメントされていない「int」へのポインタを生成できますが、他のシステムでは生成できません。テストする価値があるかもしれません。
aIX 5.3上のgcc 3.3.2(そうです、gccを更新する必要があります)
We like to think that:
..04 a char is signed
but 'CHAR_MIN==SCHAR_MIN' is false.
..09a minus shifts backwards
but '(t=-1,(15<<t)==7)' is false.
..13 The smallest bits come always first
but '(t=0x1234,0x34==*(char*)&t)' is false.
..14 i++ is structly left to right
but '(i=0,a[i++]=i,a[0]==1)' is false.
..15 structs are packed
but 'sizeof(char_int)==(sizeof(char)+sizeof(int))' is false.
..16 malloc()=NULL means out of memory
but '(malloc(0)!=NULL)' is false.
..19-3 int<long
but 'sizeof(int)<sizeof(long)' is false.
..22 floating point is always IEEE
but 'STDC_IEC_559_is_defined' is false.
From what I can say with my puny test cases, you are 71% mainstream
C++でできることは、struct
がCでできることに限定されていることです。実際、C++では、struct
は、デフォルトですべてがパブリックである点を除いて、class
に似ています。
C++構造体:
_struct Foo
{
int number1_; //this is public by default
//this is valid in C++:
private:
void Testing1();
int number2_;
protected:
void Testing2();
};
_
異なるシステムの標準的な数学関数は、同じ結果を与えません。
32ビットx86上のVisual Studio Express 2010。
Z:\sandbox>cl testtoy.c
Microsoft (R) 32-bit C/C++ Optimizing Compiler Version 16.00.30319.01 for 80x86
Copyright (C) Microsoft Corporation. All rights reserved.
testtoy.c
testtoy.c(54) : warning C4293: '<<' : shift count negative or too big, undefined
behavior
Microsoft (R) Incremental Linker Version 10.00.30319.01
Copyright (C) Microsoft Corporation. All rights reserved.
/out:testtoy.exe
testtoy.obj
Z:\sandbox>testtoy.exe
We like to think that:
..08 overshifting is okay
but '(1<<bits_per_int)==0' is false.
..09a minus shifts backwards
but '(t=-1,(15<<t)==7)' is false.
..14 i++ is structly left to right
but '(i=0,a[i++]=i,a[0]==1)' is false.
..15 structs are packed
but 'sizeof(char_int)==(sizeof(char)+sizeof(int))' is false.
..19-3 int<long
but 'sizeof(int)<sizeof(long)' is false.
..22 floating point is always IEEE
but 'STDC_IEC_559_is_defined' is false.
From what I can say with my puny test cases, you are 78% mainstream
Codepad.org (C++: g++ 4.1.2 flags: -O -std=c++98 -pedantic-errors -Wfatal-errors -Werror -Wall -Wextra -Wno-missing-field-initializers -Wwrite-strings -Wno-deprecated -Wno-unused -Wno-non-virtual-dtor -Wno-variadic-macros -fmessage-length=0 -ftemplate-depth-128 -fno-merge-constants -fno-nonansi-builtins -fno-gnu-keywords -fno-elide-constructors -fstrict-aliasing -fstack-protector-all -Winvalid-pch
)。
コードパッドにはstddef.h
。コードパッドが警告をエラーとして使用しているため、テスト9を削除しました。 count
変数は、何らかの理由で既に定義されているため、名前も変更しました。
We like to think that:
..08 overshifting is okay
but '(1<<bits_per_int)==0' is false.
..14 i++ is structly left to right
but '(i=0,a[i++]=i,a[0]==1)' is false.
..15 structs are packed
but 'sizeof(char_int)==(sizeof(char)+sizeof(int))' is false.
..19-3 int<long
but 'sizeof(int)<sizeof(long)' is false.
From what I can say with my puny test cases, you are 84% mainstream
参考までに、CのスキルをJavaに変換しなければならない人のために、ここにいくつかの落とし穴があります。
EXPECT("03 a char is 8 bits",CHAR_BIT==8);
EXPECT("04 a char is signed",CHAR_MIN==SCHAR_MIN);
Javaでは、charは16ビットであり、署名されています。バイトは8ビットで、符号付きです。
/* not true for Windows-64 */
EXPECT("05a long has at least the size of pointers",sizeof(long)>=sizeof(void*));
longは常に64ビットです。参照は32ビットまたは64ビットにすることができます(32 GBを超えるアプリがある場合)64ビットJVMは通常32ビット参照を使用します。
EXPECT("08 overshifting is okay",(1<<bits_per_int)==0);
EXPECT("09 overshifting is *always* okay",(1<<BITS_PER_INT)==0);
シフトはマスクされるため、i << 64 == i == i << -64、i << 63 == i << -1
EXPECT("13 The smallest bits always come first",(t=0x1234,0x34==*(char*)&t));
ByteOrder.nativeOrder()はBIG_ENDIANまたはLITTLE_ENDIANにできます
EXPECT("14 i++ is strictly left to right",(i=0,a[i++]=i,a[0]==1));
i = i++
変更しないi
/* suggested by David Thornley */
EXPECT("17 size_t is unsigned int",sizeof(size_t)==sizeof(unsigned int));
コレクションと配列のサイズは、JVMが32ビットか64ビットかに関係なく、常に32ビットです。
EXPECT("19-1 char<short",sizeof(char)<sizeof(short));
EXPECT("19-2 short<int",sizeof(short)<sizeof(int));
EXPECT("19-3 int<long",sizeof(int)<sizeof(long));
charは16ビット、shortは16ビット、intは32ビット、longは64ビットです。