6.使用_exit退出
  问:在下面的代码中,atexit()并没有被调用,为什么?
  #include<stdio.h>
  void func(void)
  {
  printf(" Cleanup function called ");
  return;
  }
  int main(void)
  {
  int i=0;
  atexit(func);
  for(;i<0xffffff;i++);
  _exit(0);
  }
  这是因为_exit()函数的使用,该函数并没有调用atexit()等函数清理。如果使用atexit()应当使用exit()或者“return”与之相配合。
  7.void*和C结构体
  问:你能设计一个能接受任何类型的参数并返回interger(整数)结果的函数吗?
  答:如下:
  int func(void*ptr)
  如果这个函数的参数超过一个,那么这个函数应该由一个结构体来调用,这个结构体可以由需要传递参数来填充。
  8.*和++操作
  问:下面的操作会输出什么?为什么?
  #include<stdio.h>
  int main(void)
  {
  char*ptr="Linux";
  printf(" [%c] ",*ptr++);
  printf(" [%c] ",*ptr);
  return 0;
  }
  答:输出结果应该是这样:
  [L]
  [i]
  因为“++”和“*”的优先权一样,所以“*ptr++”相当于“*(ptr++)”。即应该先执行ptr++,然后才是*ptr,所以操作结果是“L”。第二个结果是“i”。
  9.问:修改代码片段(或者只读代码)
  问:下面的代码段有错,你能指出来吗?
  #include<stdio.h>
  int main(void)
  {
  char*ptr="Linux";
  *ptr='T';
  printf(" [%s] ",ptr);
  return 0;
  }
  答:这是因为,通过*ptr=‘T’,会改变内存中代码段(只读代码)“Linux”的第一个字母。这个操作是无效的,因此会造成seg-fault或者崩溃。
  10.会改变自己名字的进程
  问:你能写出一个在运行时改变自己进程名的程序吗?
  答:参见下面这段代码:
  #include<stdio.h>
  int main(int argc,char*argv[])
  {
  int i=0;
  char buff[100];
  memset(buff,0,sizeof(buff));
  strncpy(buff,argv[0],sizeof(buff));
  memset(argv[0],0,strlen(buff));
  strncpy(argv[0],"NewName",7);
  //Simulate a wait.Check the process
  //name at this point.
  for(;i<0xffffffff;i++);
  return 0;
  }
  11.返回本地变量的地址
  问:下面代码有问题吗?如果有,该怎么修改?
  #include<stdio.h>
  int*inc(int val)
  {
  int a=val;
  a++;
  return&a;
  }
  int main(void)
  {
  int a=10;
  int*val=inc(a);
  printf(" Incremented value is equal to[%d] ",*val);
  return 0;
  }
  答:尽管上面的程序有时候能够正常运行,但是在“inc()”中存在严重的漏洞。这个函数返回本地变量的地址。因为本地变量的生命周期是“inc()”的生命周期,所以在inc结束后,使用本地变量会发生不好的结果。这可以通过将main()中变量“a”的地址来避免,这样以后还可以修改这个地址存储的值。
  12.处理printf()的参数
  问:下面代码会输出什么?
  #include<stdio.h>
  int main(void)
  {
  int a=10,b=20,c=30;
  printf(" %d..%d..%d ",a+b+c,(b=b*2),(c=c*2));
  return 0;
  }
  答:输出结果是:
  110..40..60
  这是因为C语言里函数的参数默认是从右往左处理的,输出时是从左往右。