XSS

Questions about OS

I've tried to introduce the interesting questions I met through operating systems. I want to make the list as long as I can. If you guys have other interesting problems pls contact me. EMAIL: evol128@gmail.com

Please don't reference this post because it's incomplete.

 

1. In windows we have defragmenter to collect the fragments on the disk. What is the program we use in Linux?

 

2. What is the best scheduling algorithm on a flash disk? (e.g. RANDOM, Fist in first served, shortest first, Scan, F-Scan, etc)

 

 

 

 

Answers: The answer to every question is the same.

各种IDE之间的区别

假设IDE是Car shops的老板,用户是buyer

 

Visual Studio车行:

只有一种型号,不过用户可以自己定制它的外表,包括颜色,样式,甚至车内的挂饰等等。利用定制功能用户可以很轻松DIY出华丽的外表。同时车内配备了最先进的导航仪,防止用户出错。只是,你需要依次按下车内的15个开关才能打开车前盖;即使打开了车前盖,发动机也是锁死的,没法更改,没法替换

 

Eclipse车行:

这里的车是免费的。但它不提供整车的组装服务,用户必须自己装。好处是用户可以定制每一个零件的型号,坏处是麻烦。Eclipse甚至不能帮你给车涂漆,他只是扔给你一桶你喜欢的油漆,然后让你自己涂。作为替代,它提供给用户一组电话号码,其中包括了涂漆服务的电话,组装服务的电话,等等。觉得麻烦可以随时call那些服务,只不过很多服务都是要收费的。当然,你也可以自己开一家服务公司来赚外快。和Visual Studio一样,Eclipse内部配备了先进的导航仪。

 

TextEditor车行:

用户很惊讶的发现,这里根本不卖车。这里只是提供给你一堆螺丝钉,铁片,油漆等等造车的原料,以及一份很简短的造车指南。所有的一切都必须用户自己动手。导航仪?如果你真的想要的话可以自己造一个。

坦白说跟上面2者相比没有任何优势,但据说有一个叫程序员的物种很喜欢它,因为他们很喜欢上帝创造万物的感觉。

Computer Security课堂笔记

lbr :此程序已弃置不用。lbr的作用是打印文件,它的工作方式是在文件夹下生成随机文件名的image文件,向其中写入数据,然后打印它。该程序具有SUID权限。由于计算机的随机算法都是伪随机,当进行了大量打印之后,文件名有很大概率会重复。所以,我们可以预测将要出现的文件名,建立一个同名的,指向重要系统文件的符号链接,这样该系统文件中的内容将会被覆盖。

 

LD_LIBRARY_PATH LD_PRELOAD :都是用来影响动态链接库的环境变量,由于修改此变量后将可以覆盖库函数,never use it。在SUID程序中这2个变量自动禁用

 

system调用 :Use execXX instead. system调用的机制是启动一个shell,然后将参数传递给shell。参数并非只能是一条指令。说白了,用户可以在参数里面随便乱写。  而exec调用限定了后面的参数只能作为某个程序的参数,而不能是另外的程序。

 

sendmail :心惊胆寒啊,我在公司里实习的时候亲手写过sendmail程序。sendmail的漏洞是,对于本地邮件文件,程序会检查其owner,发现其owner不是邮件所有人之后就会强制改变其owner,所以攻击者只要偷偷放一个与邮件文件同名的suid程序到目录下,然后发一封邮件,程序就变成对方的了

 

chsh :chsh会往passwd文件中写入信息,如果你在输入中加入换行,就可以覆盖passwd文件中的重要信息。现在chsh会检查输入,所以此漏洞已经修复

随机数算法

本文参考more programming pearls的相关章节,表说我抄袭……

假设你有一个随机函数RandInt(L,U),如何产生1..N中的M个不重复的随机数?

正常人想到的算法是类似这样的:

//initialize set s to empty
int size = 0;
while (size < M) {
    int t = RandInt(1,N);
    if (t not in s){
        s.insert(t);
        size=size+1;
    }
}

但是这个算法有一个致命缺陷,当M值与N值很接近时,在获得最后几个随机数时它需要猜测太多次以至于这将严重降低程序的运行速度,对于特定的随机数列,它甚至不会停止。那么,有没有一种只需要运行M次RandInt函数即可获得M个不重复随机数的算法呢?有的。Floyd大神给出了他的答案:

int sample(int M, int N){
    if (M=0) return new Set();
    else{
        Set s=sample(M-1,N-1);
        int t=RandInt(1,N);
        if(t not in s) s.insert(t);
        else s.insert(N);
        return s;        
    }
}

这个算法为了从1..N中产生M个随机数,先从1..N-1中产生M-1个随机数,然后加上N去产生第M个随机数。很神奇吧?

一些有趣的C语言问题

原文转自http://www.gowrikumar.com/c/

由于原文没有附答案,所有答案都是我做的,如有错误欢迎指出

P.S. 不要用V$去试验程序运行结果,M$ always试图创造标准

email evol128@hotmail.com

 

The expected output of the following C program is to print the elements in the array. But when actually run, it doesn't do so.

  #include<stdio.h>

 

  #define TOTAL_ELEMENTS (sizeof(array) / sizeof(array[0]))

  int array[] = {23,34,12,17,204,99,16};

  int main()
  {
      int d;

      for(d=-1;d <= (TOTAL_ELEMENTS-2);d++)
          printf("%d\n",array[d+1]);

      return 0;
  }

Find out what's going wrong.

 

sizeof 返回值为unsigned intunsigned intint作比较时int将自动转换为unsigned int


I thought the following program was a perfect C program. But on compiling, I found a silly mistake. Can you find it out (without compiling the program :-) ?

#include<stdio.h>

 

void OS_Solaris_print()

{

        printf("Solaris - Sun Microsystems\n");

}

 

void OS_Windows_print()

{

        printf("Windows - Microsoft\n");

 

}

void OS_HP-UX_print()

{

        printf("HP-UX - Hewlett Packard\n");

}

 

int main()

{

        int num;

        printf("Enter the number (1-3):\n");

        scanf("%d",&num);

        switch(num)

        {

                case 1:

                        OS_Solaris_print();

                        break;

                case 2:

                        OS_Windows_print();

                        break;

                case 3:

                        OS_HP-UX_print();

                        break;

                default:

                        printf("Hmm! only 1-3 :-)\n");

                        break;

        }

 

        return 0;

}

 

void OS_HP-UX_print() “-“是不允许的


What's the expected output for the following program and why?

enum {false,true};

 

int main()

{

        int i=1;

        do

        {

                printf("%d\n",i);

                i++;

                if(i < 15)

                        continue;

        }while(false);

        return 0;

}

 

输出只有1continue并不能跳过循环条件判断


The following program doesn't "seem" to print "hello-out". (Try executing it)

  #include <stdio.h>

  #include <unistd.h>

  int main()
  {
          while(1)
          {
                  fprintf(stdout,"hello-out");
                  fprintf(stderr,"hello-err");
                  sleep(1);
          }
          return 0;
  }

What could be the reason?

 

stdout是行缓冲的,当没有遇到换行符,程序没有结束,缓冲区空间足够的情况下,该程序都不会打印出任何输出

stderr是字符缓冲的,会立即输出


 

  #include <stdio.h>

  #define f(a,b) a##b

  #define g(a)   #a

  #define h(a) g(a)

 

  int main()
  {
          printf("%s\n",h(f(1,2)));
          printf("%s\n",g(f(1,2)));
          return 0;
  }

Just by looking at the program one "might" expect the output to be, the same for both the printf statements. But on running the program you get it as:
bash$ ./a.out
12
f(1,2)
bash$

Why is it so?

 

##是连接字符串用的,f(1,2)==12

#是把后面的表达式强制输出,g(1+2)==1+2

这两个运算符都是#define中专用

上题中第三个defineg(a)封装在h(a)里面的话,作为参数的a会在h中就被替代,否则遇到#将不去计算a的值而直接输出a的表达式


  #include<stdio.h>

  int main()
  {
          int a=10;
          switch(a)
          {
                  case '1':
                      printf("ONE\n");
                      break;
                  case '2':
                      printf("TWO\n");
                      break;
                  defa1ut:
                      printf("NONE\n");
          }
          return 0;
  }

If you expect the output of the above program to be NONE, I would request you to check it out!!

 

default打错了……提醒一下,上面这段程序是可以通过编译的


The following C program segfaults of IA-64, but works fine on IA-32.

  int main()
  {
      int* p;
      p = (int*)malloc(sizeof(int));
      *p = 10;
      return 0;
  }

Why does it happen so?

 

本程序缺少了#include <stdlib.h>malloc由于缺少函数原型,默认返回值为int而不是void*,在IA32(x86)intvoid*长度相等(32),没有任何问题,而在IA64机器上void*(64)会被截为int(32)

 

引申问题:为啥IA64机器上int32位而不是64位?

诚然,根据c99标准,int可以是32位也可以是64位。但是如果int64位,而short16位或32位,中间会缺一个位数没有任何数据类型来表示。另一方面,出于兼容性考虑,也应该采用32位的int


Here is a small piece of program(again just 14 lines of program) which counts the number of bits set in a number.

Input

Output

0

0(0000000)

5

2(0000101)

7

3(0000111)

  int CountBits (unsigned int x )
  {
      static unsigned int mask[] = { 0x55555555,
          0x33333333,
          0x0F0F0F0F,
          0x00FF00FF,
          0x0000FFFF

          } ;

          int i ;
          int shift ; /* Number of positions to shift to right*/

          for ( i =0, shift =1; i < 5; i ++, shift *= 2)
                  x = (x & mask[i ])+ ( ( x >> shift) & mask[i]);
          return x;
  }

Find out the logic used in the above program.

 

这是一个分治法的典型应用。首先两两分组计算和,再44个一起算,再88个算……最后32位的和就加出来了,那些mask数字就是用来清0的。


What do you think would be the output of the following program and why? (If you are about to say "f is 1.0", I would say check it out again)

#include <stdio.h>

 

int main()

{

        float f=0.0f;

        int i;

 

        for(i=0;i<10;i++)

                f = f + 0.1f;

 

        if(f == 1.0f)

                printf("f is 1.0 \n");

        else

                printf("f is NOT 1.0\n");

 

        return 0;

}

 

浮点数运算有误差我想大家都知道。但是我想申明一下的是,0和无穷大是没有误差的。浮点数运算的误差产生于10进制小数转化为2进制小数时,经常不能用有限的位数来表示,于是在第23位必然产生误差


I thought the following C program is perfectly valid (after reading about the comma operator in C). But there is a mistake in the following program, can you identify it?

#include <stdio.h>

 

int main()

{

        int a = 1,2;

        printf("a : %d\n",a);

        return 0;

}

 

赋值号优先级>逗号,“int 常数“ 这种语句是非法的


What would be the output of the following C program? (Is it a valid C program?)

#include <stdio.h>

int main()

{

        int i=43;

        printf("%d\n",printf("%d",printf("%d",i)));

        return 0;

}

 

4321  printf的返回值为输出字符的个数


  void duff(register char *to, register char *from, register int count)
  {
      register int n=(count+7)/8;
      switch(count%8){
      case 0: do{ *to++ = *from++;
      case 7:  *to++ = *from++;
      case 6: *to++ = *from++;
      case 5: *to++ = *from++;
      case 4: *to++ = *from++;
      case 3: *to++ = *from++;
      case 2: *to++ = *from++;
      case 1: *to++ = *from++;
              }while( --n >0);
      }
  }

Is the above valid C code? If so, what is it trying to acheive and why would anyone do something like the above?

 

虽然我也觉得不可思议但这样写就是合法的。这是一个拷贝内存的程序,switch的目的是减少循环次数以增加程序执行效率,它将循环次数由count次减少为(count+7)/8


Here is yet another implementation of CountBits. Verify whether it is correct (how do you that???). If so, find out the logic used.

  int CountBits(unsigned int x)
  {
      int count=0;
      while(x)
      {
          count++;
          x = x&(x-1);
      }
      return count;
  }

 

每循环一次就消掉末尾的一个1


Are the following two function prototypes same?

  int foobar(void);
  int foobar();

The following programs should be of some help in finding the answer: (Compile and run both the programs and see what happens)
Program 1:

  #include <stdio.h>

  void foobar1(void)
  {
   printf("In foobar1\n");
  }

  void foobar2()
  {
   printf("In foobar2\n");
  }

  int main()
  {
     char ch = 'a';
     foobar1();
     foobar2(33, ch);
     return 0;
  }

Program 2:

  #include <stdio.h>

  void foobar1(void)
  {
   printf("In foobar1\n");
  }

  void foobar2()
  {
   printf("In foobar2\n");
  }

  int main()
  {
     char ch = 'a';
     foobar1(33, ch);
     foobar2();
     return 0;
  }

 

f()可以传参数,而f(void)不能传任何参数


What's the output of the following program and why?

  #include <stdio.h>

  int main()
  {
   float a = 12.5;
   printf("%d\n", a);
   printf("%d\n", *(int *)&a);
   return 0;
  }

 

第二个printffloat当作int(不是转换成int)给输出了


The following is a small C program split across files. What do you expect the output to be, when both of them compiled together and run?
File1.c

  int arr[80];

File2.c

  extern int *arr;
  int main()
  {
      arr[1] = 100;
      return 0;
  }

 

运行时错误

指针和数组是不同的,不同的!一个是间接引用,而另一个是直接访问

只有作为函数参数的数组会自动转换为指针!即不管f(int[])还是f(int*)参数都是int*

 


Explain the output of the following C program (No, the output is not 20).

  #include<stdio.h>

  int main()
  {
      int a=1;
      switch(a)
      {   int b=20;
          case 1: printf("b is %d\n",b);
                  break;
          default:printf("b is %d\n",b);
                  break;
      }
      return 0;
  }

 

int b=20没有执行到,b的值不确定


What is the output of the following program? (Again, it is not 40, (if the size of integer is 4)).

  #define SIZE 10

  void size(int arr[SIZE])
  {
          printf("size of array is:%d\n",sizeof(arr));
  }

  int main()
  {
          int arr[SIZE];
          size(arr);
          return 0;
  }

 

上上题刚刚提过,函数参数中的int[]自动转换为int*


The following is a simple c program, in which there is a function called Error to display errors. Can you see a potential problem with the way Error is defined?

  #include <stdlib.h>

  #include <stdio.h>

  void Error(char* s)
  {
      printf(s);
      return;
  }

  int main()
  {
      int *p;
      p = malloc(sizeof(int));
      if(p == NULL)
      {
          Error("Could not allocate the memory\n");
          Error("Quitting....\n");
          exit(1);
      }
      else

      {
          /*some stuff to use p*/

      }
      return 0;
  }

 

 

我觉得没太大问题,就是不能传参数么……


What is the differnce between the following function calls to scanf?(Please notice the space carefully in the second call. Try removing it and observe the behaviour of the program)

  #include <stdio.h>

  int main()
  {
      char c;
      scanf("%c",&c);
      printf("%c\n",c);

      scanf(" %c",&c);
      printf("%c\n",c);

      return 0;
  }

 

scanf中,空白字符(空格,tab,回车)可以匹配任意数量的空白字符(包括0个)

第二个scanf中的空格是为了防止上一个scanf结束时的回车符被读入c


What is the potential problem with the following C program?

  #include <stdio.h>

  int main()
  {
      char str[80];
      printf("Enter the string:");
      scanf("%s",str);
      printf("You entered:%s\n",str);

      return 0;
  }

 

输入超过79个字符……


What is the output of the following program?

  #include <stdio.h>

  int main()
  {
      int i;
      i = 10;
      printf("i : %d\n",i);
      printf("sizeof(i++) is: %d\n",sizeof(i++));
      printf("i : %d\n",i);
      return 0;
  }

 

i:10sizeof在编译阶段就会计算出结果,所以它不会对后面的表达式求值

例外:参数是变长数组时,求值会延迟至运行阶段


Why does the following program give a warning? (Please remember that sending a normal pointer to a function requiring const pointer does not give any warning)

  #include <stdio.h>

  void foo(const char **p) { }
  int main(int argc, char **argv)
  {
          foo(argv);
          return 0;
  }

 

请考虑下面这个程序:

const int x=32;

int * a;

const int **b;

b=&a;//const赋值给const

*b=&x;//const赋值给const

*a=31;//x变成31

为了防止这种事情发生,b=&a必须warning

引申问题:

我将其改为foo(const char* const*p),理论上已经杜绝上面这种情况了,但是仍然warning,请问是怎么回事?

 


What is the output of the following program?

  #include <stdio.h>

  int main()
  {
          int i;
          i = 1,2,3;
          printf("i:%d\n",i);
          return 0;
  }

 

i:1

等号优先级比逗号大


The following is a piece of code which implements the reverse Polish Calculator. There is a(are) serious(s) bug in the code. Find it(them) out!!! Assume that the function getop returns the appropriate return values for operands, opcodes, EOF etc..

  #include <stdio.h>

  #include <stdlib.h>

 

  #define MAX 80

  #define NUMBER '0'

 

  int getop(char[]);
  void push(double);
  double pop(void);
  int main()
  {
      int type;
      char s[MAX];

      while((type = getop(s)) != EOF)
      {
          switch(type)
          {
              case NUMBER:
                  push(atof(s));
                  break;
              case '+':
                  push(pop() + pop());
                  break;
              case '*':
                  push(pop() * pop());
                  break;
              case '-':
                  push(pop() - pop());
                  break;
              case '/':
                  push(pop() / pop());
                  break;
              /*   ...

               *   ...   

               *   ...

               */

          }
      }
  }

 

无视错误处理的话,两个操作数的顺序反了,在减法和除法中会有问题


The following is a simple program which implements a minimal version of banner command available on most *nix systems. Find out the logic used in the program.

  #include<stdio.h>

  #include<ctype.h>

 

  char t[]={
      0,0,0,0,0,0,12,18,33,63,
      33,33,62,32,62,33,33,62,30,33,
      32,32,33,30,62,33,33,33,33,62,
      63,32,62,32,32,63,63,32,62,32,
      32,32,30,33,32,39,33,30,33,33,
      63,33,33,33,4,4,4,4,4,4,
      1,1,1,1,33,30,33,34,60,36,
      34,33,32,32,32,32,32,63,33,51,
      45,33,33,33,33,49,41,37,35,33,
      30,33,33,33,33,30,62,33,33,62,
      32,32,30,33,33,37,34,29,62,33,
      33,62,34,33,30,32,30,1,33,30,
      31,4,4,4,4,4,33,33,33,33,
      33,30,33,33,33,33,18,12,33,33,
      33,45,51,33,33,18,12,12,18,33,
      17,10,4,4,4,4,63,2,4,8,
      16,63

      };

  int main(int argc,char** argv)
  {

      int r,pr;
      for(r=0;r<6;++r)
          {
          char *p=argv[1];

          while(pr&&*p)
              {
              int o=(toupper(*p++)-'A')*6+6+r;
              o=(o<0||o>=sizeof(t))?0:o;
              for(pr=5;pr>=-1;--pr)
                  {
                  printf("%c",( ( (pr>=0) && (t[o]&(1<<pr)))?'#':' '));

                  }
              }
          printf("\n");
          }
      return 0;
  }

banner的作用是用#号组成对应的字符

char t[]中每6个数字代表一个字母,一个数字表示一行中#号的位置,1就是#0就是空格,其它的自己看了

另外:有几个数字写错了,你能把它(们)找出来吗?


What is the output of the following program?

  #include <stdio.h>

  #include <stdlib.h>

 

  #define SIZEOF(arr) (sizeof(arr)/sizeof(arr[0]))

 

  #define PrintInt(expr) printf("%s:%d\n",#expr,(expr))

  int main()
  {
      /* The powers of 10 */

      int pot[] = {
          0001,
          0010,
          0100,
          1000

      };
      int i;

      for(i=0;i<SIZEOF(pot);i++)
          PrintInt(pot[i]);
      return 0;
  }

 

注意两点:0开头的数字是8进制;#号的作用


The following is the implementation of the Euclid's algorithm for finding the G.C.D(Greatest Common divisor) of two integers. Explain the logic for the below implementation and think of any possible improvements on the current implementation.
BTW, what does scanf function return?

  #include <stdio.h>

  int gcd(int u,int v)
  {
      int t;
      while(v > 0)
      {
          if(u > v)
          {
              t = u;
              u = v;
              v = t;
          }
          v = v-u;
      }
      return u;
  }

  int main()
  {
      int x,y;
      printf("Enter x y to find their gcd:");
      while(scanf("%d%d",&x, &y) != EOF)
      {
          if(x >0 && y>0)
              printf("%d %d %d\n",x,y,gcd(x,y));
                  printf("Enter x y to find their gcd:");
      }
      printf("\n");
      return 0;
  }

Also implement a C function similar to the above to find the GCD of 4 integers.

 

gcd算法大家都知道,%-效率会高

scanf返回匹配的变量个数


What's the output of the following program. (No, it's not 10!!!)

  #include <stdio.h>

  #define PrintInt(expr) printf("%s : %d\n",#expr,(expr))

  int main()
  {
      int y = 100;
      int *p;
      p = malloc(sizeof(int));
      *p = 10;
      y = y/*p; /*dividing y by *p */;
      PrintInt(y);
      return 0;
  }

 

y/ *p 这样就没问题了


The following is a simple C program to read a date and print the date. Run it and explain the behaviour

  #include <stdio.h>

  int main()
  {
      int day,month,year;
      printf("Enter the date (dd-mm-yyyy) format including -'s:");
      scanf("%d-%d-%d",&day,&month,&year);
      printf("The date you have entered is %d-%d-%d\n",day,month,year);
      return 0;
  }

 

没啥好说的,-就是匹配-

 


The following is a simple C program to read and print an integer. But it is not working properly. What is(are) the mistake(s)?

  #include <stdio.h>

  int main()
  {
      int n;
      printf("Enter a number:\n");
      scanf("%d\n",n);

      printf("You entered %d \n",n);
      return 0;
  }

 

上面说过,scanf中的’\n’匹配任意多个空白字符,所以该程序会一直等待,直到你输入了非空白字符为止


The following is a simple C program which tries to multiply an integer by 5 using the bitwise operations. But it doesn't do so. Explain the reason for the wrong behaviour of the program.

  #include <stdio.h>

  #define PrintInt(expr) printf("%s : %d\n",#expr,(expr))

  int FiveTimes(int a)
  {
      int t;
      t = a<<2 + a;
      return t;
  }

  int main()
  {
      int a = 1, b = 2,c = 3;
      PrintInt(FiveTimes(a));
      PrintInt(FiveTimes(b));
      PrintInt(FiveTimes(c));
      return 0;
  }

 

+优先级比<<大,建议大家背一下优先级顺序表


Is the following a valid C program?

  #include <stdio.h>

  #define PrintInt(expr) printf("%s : %d\n",#expr,(expr))

  int max(int x, int y)
  {
      (x > y) ? return x : return y;
  }

  int main()
  {
      int a = 10, b = 20;
      PrintInt(a);
      PrintInt(b);
      PrintInt(max(a,b));
  }

 

?后面必须跟值

 


The following is a piece of C code, whose intention was to print a minus sign 20 times. But you can notice that, it doesn't work.

  #include <stdio.h>

  int main()
  {
      int i;
      int n = 20;
      for( i = 0; i < n; i-- )
          printf("-");
      return 0;
  }

Well fixing the above code is straight-forward. To make the problem interesting, you have to fix the above code, by changing exactly one character. There are three known solutions. See if you can get all those three.

 

1.n-- 2.i+n 3.-i<n

友情提醒:~i<n是错的


What's the mistake in the following code?

  #include <stdio.h>

  int main()
  {
      int* ptr1,ptr2;
      ptr1 = malloc(sizeof(int));
      ptr2 = ptr1;
      *ptr2 = 10;
      return 0;
  }

 

ptr2类型是int不是int*


What is the output of the following program?

  #include <stdio.h>

  int main()
  {
      int cnt = 5, a;

      do {
          a /= cnt;
      } while (cnt --);

      printf ("%d\n", a);
      return 0;
  }

 

运行时错误,最后除以0

 


What is the output of the following program?

  #include <stdio.h>

  int main()
  {
      int i = 6;
      if( ((++i < 7) && ( i++/6)) || (++i <= 9))
          ;
      printf("%d\n",i);
      return 0;
  }

 

i=8

&& || 运算符当可以通过第一个操作数确定结果时就不会计算第二个操作数的值。上面的++i<7已经是false了,所以i++/6没有算


What is the bug in the following program?

  #include <stdlib.h>

  #include <stdio.h>

  #define SIZE 15

  int main()
  {
      int *a, i;

      a = malloc(SIZE*sizeof(int));

      for (i=0; i<SIZE; i++)
          *(a + i) = i * i;
      for (i=0; i<SIZE; i++)
          printf("%d\n", *a++);
      free(a);
      return 0;
  }

 

a的值变了,free时没有释放正确的空间

 


Is the following a valid C program? If so, what is the output of it?

  #include <stdio.h>

  int main()
  {
    int a=3, b = 5;

printf(&a["Ya!Hello! how is this? %s\n"], &b["junk/super"]);
    printf(&a["WHAT%c%c%c  %c%c  %c !\n"], 1["this"],
       2["beauty"],0["tool"],0["is"],3["sensitive"],4["CCCCCC"]);
    return 0;
  }

 

a[i]i[a]是等价的


What is the output of the following, if the input provided is:
Life is beautiful

  #include <stdio.h>

  int main()
  {
      char dummy[80];
      printf("Enter a string:\n");
      scanf("%[^a]",dummy);
      printf("%s\n",dummy);
      return 0;
  }

 

有点像正则表达式,%[^a]匹配到第一个a出现为止


Note : This question has more to do with Linker than C language
We have three files a.c, b.c and main.c respectively as follows:
a.c
---

int a;

b.c
---

int a = 10;

main.c
------

extern int a;

int main()

{

        printf("a = %d\n",a);

        return 0;

}

Let's see what happens, when the files are compiled together:

bash$ gcc a.c b.c main.c

bash$ ./a.out

a = 10

Hmm!! no compilation/linker error!!! Why is it so??

 

I don’t know. But it works. Who can tell me why?


The following is the offset macros which is used many a times. Figure out what is it trying to do and what is the advantage of using it.

  #define offsetof(a,b) ((int)(&(((a*)(0))->b)))

 

天杀的,都不说一下这程序干嘛的。看了好久才看出来astructbstruct的内部变量,用来算b的偏移量的

方法是——让运行环境帮你算。。。

好吧,我稍微说下原理,将0强制转换成指向a的指针,(当然它不是,不过因为我们不去访问数据所以不会有问题),然后获得0->b的指针,把地址换成整数,就是偏移量


The following is the macro implementation of the famous, Triple xor swap.

  #define SWAP(a,b) ((a) ^= (b) ^= (a) ^= (b))

What are the potential problems with the above macro?

 

也就swap(a++,b++)这样的会有问题吧?++会被计算多次


What is the use of the following macro?

  #define DPRINTF(x) printf("%s:%d\n",#x,x)

DPRINTF(x)     输出   x:x的值\n


Let's say you were asked to code a function IAddOverFlow which takes three parameters, pointer to an integer where the result is to be stored, and the two integers which needs to be added. It returns 0 if there is an overflow and 1 otherwise:

  int IAddOverFlow(int* result,int a,int b)
  {
      /* ... */

  }

So, how do you code the above function? (To put in a nutshell, what is the logic you use for overflow detection?)

 

if((a^b)>=0 && (*result^a)<0) return 0;

else return 1;

检查第一位,当ab符号相同但result符号却不同时溢出

P.S. 我写的括号是不可以省略的


What does the following macro do?

  #define ROUNDUP(x,n) ((x+n-1)&(~(n-1)))

 

天杀的程序no.2。我花费无数心血才发现原来n必须是2的次方。。。返回值是(x+n-1) /n *n

这个程序多半是用来内存对齐的,所以用位运算以获得高效率


Most of the C programming books, give the following example for the definition of macros.

  #define isupper(c) (((c) >= 'A') && ((c) <= 'Z'))

But there would be a serious problem with the above definition of macro, if it is used as follows (what is the problem??)

  char c;
  /* ... */

  if(isupper(c++))
  {
      /* ... */

  }

But most of the libraries implement the isupper (declared in ctypes.h) as a macro (without any side effects). Find out how isupper() is implemented on your system.

 

我看到的是查表(orz)


I hope you know that ellipsis (...) is used to specify variable number of arguments to a function. (What is the function prototype declaration for printf?) What is wrong with the following delcaration?

  int VarArguments(...)
  {
      /*....*/

      return 0;
  }

 

第一个参数不能省略


Write a C program to find the smallest of three integers, without using any of the comparision operators.

 

答案不唯一

int min(int a, int b){

int x=a-b;

return b+(x & x>>31);

}

括号仍然不要省略


What does the format specifier %n of printf function do?

 

不打印任何东西,存贮当前已经打印出的字符数到对应参数指针中、

例如:printf(“1234%n56%n\n”,&a,&b)  a=4 b=6


Write a C function which does the addition of two integers without using the '+' operator. You can use only the bitwise operators.(Remember the good old method of implementing the full-adder circuit using the or, and, xor gates....)

 

答案不唯一

int add(int a,int b){

while(b){

       a=a^b;

       b=~a&b;

b=b<<1;

}

return a;

}

 

老外写了一个很YD的:

char* p=(char *)a;

result=(int)&p[b];

 


How do you print I can print % using the printf function? (Remember % is used as a format specifier!!!)

 

%%


What's the difference between the following two C statements?

  const char *p;
  char* const p;

 

第一个,指向的charconst;第二个,pconst


What is the difference between memcpy and memmove?

 

memmove可以自己拷给自己,memcpy拷给自己的行为未定义


What is the format specifiers for printf to print double and float values?

 

%f %G %g %e %E


Write a small C program to determine whether a machine's type is little-endian or big-endian.

 

答案不唯一

int a=1;

char* p=&a; //p指向的是a的前8个字节

if(*p) printf(“little-endian\n”);// little-endian的话前8位是0x01

else printf(“big-endian\n”);


Write a C program which prints Hello World! without using a semicolon!!!

 

答案不唯一

main(){ if(printf(“Hello World!\n”)){} }

估算测试

原题摘自programming pearls, 部分题目对中国人有些困难,所以本地化了一下

对于下面各题,请给出一个区间,使得你认为90%的概率将真实值包含在其中,请勿把区间设置得太大,这样就没有意义了

1.2000年1月1日美国人口数量,以百万为单位(中国人口大家都知道,就不换了)

2.拿破仑出生年份(国人就改成孙中山吧,毛泽东太好猜了)

3.密西西比-密苏里河长度,英里为单位(国人就去算长江,千米单位)

4.波音747最大起飞重量,以磅为单位(你算公斤也行)

5.无线信号从地球传播到月球所需秒数

6.伦敦的纬度

7.航天飞机绕地球一圈所需分钟数

8.金门大桥两座钢塔之间的距离,英尺单位(国人去算南京长江大桥,两座桥头堡的距离,米作单位,经过那么多次了没理由算不出来吧)

9.独立宣言署名人数(去算共产党第一次代表大会人数)

10.成年人的骨头块数

答案请反白











答案:1. 27250万

2 .1769(1866)

3.3710(6397)

4. 875000(397000)

5.1.29(近地点3.6远地点4.0)

6.51.5度

7.91(没有详细的解答方案,但是据我考察现在最新型的航天飞机大概是30000千米/小时,换算过去大概是70分钟,所以这个数据是靠谱的)

8.4200(1577)

9.56(12)

10.206

 

这题做得我内牛满面

出自《编程珠玑》第四章书后习题

证明下面程序输入x为正整数时能够终止

 

while x !=1 do
        if even(x)
                x=x/2
        else
                x=3*x+1

 

 

 

 

 

 

做了2个小时终告放弃。。。书后和谐用语的答案如下,建议大家尝试下证明,然后再看答案

关于这个未解决的书著名数学问题请参考“the 3x+1 problem and its generalization"一文

 

关于java中System.in与System.out的思考

最近在工作上涉及到system的一些源代码,突然想到一个问题:System.out是流,却拥有各种各样的print方法来打印字符,这样大大方便了程序的编写;那么,为什么system.in没有这样的方法呢?

就这个问题我跟同事们探讨了一下,也到usenet上去问了,感谢大家的帮助,最终总结出比较靠谱的解释如下:

System.in与System.out都是字节流而非字符流,PrintStream所做的工作,就是当输出一个非字节流类型的数据的时候,通过平台相关的转换算法将其转化为字节流,但其本质仍然是一个个的字符

而在读取的时候,如果采用相同的处理方法,则会产生这样的一个问题:如何判断一个数据的终止?

就拿int为例,如果读入的int是字符形式的,那如何得知数据长度?没有数据长度就无法停止读取。也许有人提出可以采用分隔符的方式来终止读取,这样做的弊端是作为分隔符的那个字符就被舍弃了,所以sun提供了java.util.scanner来实现此功能而不是将其作为默认配置。如果int是纯字节流呢?那很遗憾,这样就与输出不匹配了,输入输出的一致性始终是最先要考虑的因素。

总的来说,在输出时,java能够清楚地知道用户想输出的是什么,并进行统一的处理;但是在输入时,java难道能够知道用户读的是什么吗?不知道。所以就没有提供一个统一的处理方法,而是交给用户根据自己的需要对输入流进行封装

Java的ClassLoader机制

本文部分内容翻译自ri的java document

ClassLoader,顾名思义,就是用来加载class的。java程序中的所有class都要经由某个classloader的子类来加载

大体上而言,bootstrap classloader负责加载vm启动时所引用的class,extention classloader加载虚拟机需要的扩展class,而system classloader则负责从classpath中寻找各种各样的类

除了bootstrap classloader外,每一个classloader都有一个parent classloader(这是一个field,不是继承关系中的parent),当需要加载一个类时,首先查找这个类是否已经加载过;如果没有,则交由parent classloader去加载;如果parent classloader不能加载,那就由自己加载。当然其中一系列复杂的路径处理权限管理过程被我略掉了。