Cで符号付かどうかを判定するマクロを書くというのは有名な問題なわけですが、例えば

issigned(char)         ==> charが符号付ならば1、そうでないなら0
issigned(short)        ==> 1
issigned(unsigned int) ==> 0

のような結果を返すマクロなら簡単に書けるわけです。

#define issigned(t) ((t)-1<0)

といった感じでよいでしょう。

ではパラメタが型名ではなくて、式だったらどうでしょう

issigned(1)   ==> 1
issigned(1U)  ==> 0

これならまだ書けそうな気がしますね。では

issigned((short)1)         ==> 1
issigned((unsigned char)1) ==> 0

もサポートせよとなったら、なんか無理っぽい気がしてきますね。

少し簡単にして、パラメタは必ず左辺値に限るとしてみましょう。

short x = 1;
unsigned char y = 1;
issigned(x) ==> 1
issigned(y) ==> 0

これならできそうだ。もちろんパラメタに与えられた変数を変更してはいけませんよ!

さて、ここからが本題で、下の未完なCのコードを完成させて求める結果を出力するようにせよ

#include <stdio.h>

/* ここにコードを追加する。*/

int main()
{
  char c = 1;
  unsigned char uc = 1;
  signed char sc = 1;

  signed short ss = 1;
  unsigned short us = 1;

  signed int si = 1;
  unsigned int ui = 1;

  signed long sl = 1;
  unsigned long ul = 1;

  printf("c:  %d\n", issigned(c));
  printf("uc: %d\n", issigned(uc));
  printf("sc: %d\n", issigned(sc));
  printf("ss: %d\n", issigned(ss));
  printf("us: %d\n", issigned(us));
  printf("si: %d\n", issigned(si));
  printf("ui: %d\n", issigned(ui));
  printf("sl: %d\n", issigned(sl));
  printf("ul: %d\n", issigned(ul));

  printf("c : %d\n", issigned(char));
  printf("sc: %d\n", issigned(signed   char));
  printf("uc: %d\n", issigned(unsigned char));
  printf("ss: %d\n", issigned(signed   short));
  printf("us: %d\n", issigned(unsigned short));
  printf("si: %d\n", issigned(signed   int));
  printf("ui: %d\n", issigned(unsigned int));
  printf("sl: %d\n", issigned(signed   long));
  printf("ul: %d\n", issigned(unsigned long));

  return 0;
}

結果は

c:  1
uc: 0
sc: 1
ss: 1
us: 0
si: 1
ui: 0
sl: 1
ul: 0
c : 1
sc: 1
uc: 0
ss: 1
us: 0
si: 1
ui: 0
sl: 1
ul: 0

まあ、答えはいろいろありますね。もっとも不真面目に解くと

int main() { ... }
#define main hoge

だね。もちろん真面目度が高いほど高得点。