今年になってから100回くらい「C言語むずい」って言ってる気がするな

以下のコードは、tcc, faucc, sdcc, bcc(Boarland ではないほう), clang で通らないが、Cとして正しいプログラム。

int *b = (int*)(struct xxyyzz {
    struct aabb {
        int a;
    } n;
    struct nenum {
        int x;
    } f;
}*)0;

int func(struct xxyyzz {int funarg; struct aabb {int funarg;}; } x)
{
    struct xxyyzz xxyyzz;
    struct aabb z;
    int a;

    xxyyzz.funarg;

    {
        struct xxyyzz {
            int aa;
            struct aabb y;
            union aabb {
                int x;
            } n;
            union aabb z;
        };

        union aabb a;
        a.x = 0;

        {
            int *a = (int*)(struct xxyyzz{union aabb{int n3;}f; struct nenum{int a;}ne;}*)0;
            union aabb z;
            z.n3 = 8;
        }
    }

    return z.funarg;
}


struct aabb x;
int main()
{
    struct aabb z;
    z.a = 0;

    return x.a;
}

C の難しいところのひとつとして、式と宣言と型定義が結びついているというのがある。


C99 の sizeof なんかは、コンパイル時定数のように見えて、型定義も副作用も書けるという立派な複雑すぎる要素のひとつである。

#include <stdio.h>
int main()
{
	sizeof(struct a { int a;}); /* 型定義ができる */
	struct a aa; 

	sizeof(int [puts("a")]); /* 副作用が書ける */
	sizeof(int [((struct b {int b;}*)0, puts("b"))]); /* もちろん両方書ける */
	struct b bb;

	sizeof(sizeof(int [puts("c")])); /* これは副作用無い */
}