4. 静态数组索引(C99)
  在
  void f(int a[static 10]) {
  /* ... */
  }
  中,你向编译器保证,你传递给f 的指针指向一个具有至少10个int 类型元素的数组的元素。我猜这也是为了优化;例如,编译器将会假定a 非空。编译器还会在你尝试要将一个可以被静态确定为null的指针传入或是一个数组太小的时候发出警告。
  在
  void f(int a[const]) {
  /* ... */
  }
  你不能修改指针a.,这和说明符int * const a.作用是一样的。然而,当你结合上一段中提到的static 使用,比如在int a[static const 10] 中,你可以获得一些使用指针风格无法得到的东西。
  5. 泛型表达式(C11)
  这个表达式会在编译期间根据控制表达式的类型,在一个含有一个或多个备选方案的集合中做出选择。下面这个例子可以很好的说明这一切:
  #define cbrt(X) _Generic((X),
  long double: cbrtl,
  default: cbrt,
  float: cbrtf
  )(X)
  因此,如果expr 是long double类型的, cbrt(expr) 被转换为cbrtl(expr),如果是float类型 则转换为cbrtf(expr) ,或是转换为cbrt(expr),如果是其他不同的类型(比如说double )。注意,_Generic 可以用在宏以外的地方,但是用在宏里面好因为C不允许你进行函数重载。
  6. wint_t (C99)
  我相信大家都知道wint_t 但是 wint_t 到底是个什么鬼东西呢?
  好吧,记住fgetc 实际上并不会返回 char 。它会返回int。显然这是因为fgetc 必须返回返回一个与其他char 都不同的值,也是EOF,表示到达文件末尾。基于相同的原因,fgetwc 并不返回wchar_t。它会返回一个类型,叫做wint_t 可以表示所有无效wchar_t 类型,包括WEOF,来表示到达文件末尾。
  Michal Fori?ek
  下面这段C程序可以准确的打印2的747次方而不产生误差。这是为什么呢?
  程序:
  #include <stdio.h>
  #include <math.h>
  int main() {
  printf("%.0f ",pow(2,747));
  return 0;
  }
  输出结果:  7402983151916069675202271883308899666103773198684199386306057157640700114662060195593254131453735723259390500531821

59998975553533608824916574615132828322000124194610605645134711392062011527273571616649243219599128195212771328
  答案:
  这个问题包含两个部分。
  其一,2的次方可以在double 中被准确的保存而不产生任何精度上的损失(这一结论直到2^1023都是对的,再往后会产生上溢,得到一个正无穷的值)
  另外一部分,很多人猜测是语言实现中的某些特殊情况导致的,但是实际上并非如此。的确,当输入的数据可以被2的某高次方整除时,有一部分代码被执行了,但是本质上这只是通常实现工作时的一个副作用。基本上,printf 在打印数字(任何类型)的时候只是做了从二进制到十进制的转换。并且由于结果对于浮点数可能会过大,printf 的内部实现包含和使用一个大整型实现,尽管在C中并没有大整型这种变量(在gcc源代码中,vfprintf.c 和dtoa.c 中包含了很多转换,如果你想要了解可以一看。)
  如果你尝试打印3^474,
  程序:
  #include <stdio.h>
  #include <math.h>
  int main() {
  printf("%.0f ",pow(3,474));
  return 0;
  }
  输出结果:  1430456768828466115327897475231203158390125920371120164772500692433310663451919482330309133027768477654716709315

5518867557708479462413116497799842448027156309852771422896137582164841870381535840058702788340257784498862132559872
  结果仍然是一个很大的数且位数也正确,但是这一次却不够精确。这里会产生一个相对误差,因为3^474不能以双精度浮点数准确的表示。准确的数应该是这样的143045676882846603471…
  译注:在linux系统上是可以的,在windows 64位上后面会有很多0
  Utkal Sinha
  我发现一些C语言特性或者是小技巧,我觉得只有很少的人知道。
  1. 不使用加号来使数字相加
  因为printf() 函数返回它所打印的字符的个数,我们可以利用这一点来使数字相加,代码如下:
#include<stdio.h>;
int add(int a,int b){
if(if(a!=0&&b!=0))
return printf("%*c%*c",a,' ',b,' ');
else return a!=0?a:b;
}
int main(){
int A = 0, B = 0;
printf("Enter the two numbers to add ");
scanf("%d %d",&A,&B);
printf("Required sum is %d",add(A,B));
return 0;
}
  利用位操作同样也可以做到:
  int Add(int x, int y)
  {
  if (y == 0)
  return x;
  else
  return Add( x ^ y, (x & y) << 1);
  }
  2. 条件运算符的用法
  通常我们都这样使用它:
  x = (y < 0) ? 10 : 20;
  但是同样也可以这样用:
  (y < 0 ? x : y) = 20;
  3. 在一个返回值为void 的函数中写一个return 语句
  static void foo (void) { }
  static void bar (void) {
  return foo();
  // 注意这里的返回语句.
  }
  int main (void) {
  bar();
  return 0;
  }
  4. 逗号表达式的使用
  通常逗号表达式会这样使用:
  for (int i=0; i<10; i++, doSomethingElse())
  {
  /* whatever */
  }
  但是你可以在其他任何地方使用逗号表达式:
  1
  int j = (printf("Assigning variable j "), getValueFromSomewhere());
  每条语句都进行了求值,但是表达式的值是后一个语句的值。
  5. 将结构体初始化为0
  struct mystruct a = {0};
  这将把结构体中全部元素初始化为0
  6. 多字符常量
  int x = 'ABCD';
  这会把x的值设置为0×41424344(或者0×44434241,取决于架构)
  7. printf 允许你使用变量来格式化格式说明符本身
  #include <stdio.h>
  int main() {
  int a = 3;
  float b = 6.412355;
  printf("%.*f ",a,b);
  return 0;
  }
  * 符号可以达到这一目的
  希望这些可以帮助到大家
  此致敬礼
  Vivek Nagarajan
  你可以在奇怪的地方使用#include
  如果你写:
  #include <stdio.h>
  void main()
  {
  printf
  #include "fragment.c"
  }
  且fragment.c 包含:
  ("dayum! ");
  这完全没有问题。只要#include 包含完整可解析的C表达式,预处理器并不在意它放在什么位置。
  Vipul Mehta
  1. printf 格式限定符中指定(POSIX扩展语法)
  printf("%4$d %3$d %2$d %1$d", 1, 2, 3, 9); //将会打印9 3 2 1
  2. 在scanf 中忽略输入输入
  scanf("%*d%d", &a);// 如果输入1 2,则只会得到2
  3. 在switch 中使用范围(gcc扩展语法)
  switch(c) {
  case 'A' ... 'Z':
  //do something
  break;
  case 1 ... 5 :
  //do something
  }
  4. 使用前缀ob 来限定常数,使其被当做二进制数(gcc扩展语法)
  printf("%d",0b1101);
  // prints 13
  5.完全正确的短的C语言程序
  main;
  译注:虽然编译没有error但是却不能执行
  Karan Bansal
  scanf()的力量
  假定我们有一个数组char a[100]
  读取一个字符串:
  scanf("%[^ ] ", a);//表示一直读取直到遇到' ',并且忽略掉' '
  读取字符串直到遇到逗号:
  scanf("%[^,]", a);//但是这次不会忽略逗号
  如果你想忽略掉某个输入,使用在% 后使用*,如果你想要得到John Smith 的姓:
  scanf("%s %s", temp, last_name);
  //典型答案,使用一个临时变量
  scanf("%s", last_name);
  scanf("%s", last_name);
  // 另一种答案,使用一个变量但是调用两次 `scanf()`
  scanf("%*s %s", last);
  //佳答案,因为你不需要额外的变量或是调用两次`scanf()`
  顺便提一句,你应该非常小心的使用scanf 因为它可能会是你的输入缓冲溢出!通常你应该使用fgets 和sscanf 而不是仅仅使用scanf,使用fgets 来读取一行,然后用sscanf 来解析这一行,像上面演示的一样。
  Afif Ahmed
  ~-n 等于n-1
  -~n 等于n+1
  原因:
  当我们写-n时,实际上是以补码形式储存,所以-n 可以写成~n + 1,吧整个式子放在上面表达式的前面你能明白原因了。