evol128[Blog]

I am the bone of my code

Some interesting C problems 2nd edition

evol128 posted @ 2011年6月30日 19:55 in language with tags c interesting interview , 3403 阅读

本文第一版写于2010-5-19 

本文尚不是最终版本,感谢Gee Law, Dr. Du,stackoverflow上众网友,以及在美帝过着荒淫无度的生活的Inifok对我的帮助

原题转自http://www.gowrikumar.com/c/   答案请反白,部分题目的答案尚不完善,希望大家能帮助我解决

 

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 int,unsigned int与int作比较时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;

}

 

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


--------------------------------------------------------------------------------

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?

 

通常来讲,你会看到hello-err却看不到hello-out

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

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?

 

本题答案有待完善

#和##都是宏运算符

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

#的结果就是参数的字符串,#abcd = abcd

宏定义中处理类似函数的f(x)时,如果发现是##或者#运算符,是不会对参数x进行进一步展开的,所以才会产生上面的结果

参考资料:http://en.wikipedia.org/wiki/C_preprocessor


--------------------------------------------------------------------------------

  #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)下int与void*长度相等(32位),没有任何问题,而在IA64机器上void*(64位)会被截为int(32位)

 

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

诚然,根据c99标准,int可以是32位也可以是64位。但是如果int为64位,而short为16位或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.

 

这是一个分治法的典型应用。首先两两分组计算和,再4个4个一起算,再8个8个算……最后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进制小数时,经常不能用有限的位数来表示,于是在最后一位会产生误差。大家在编程的时候请尽量避免浮点数比较,如果真的要比较,请用a-b<=0.0000001这种方式来显示指定精度


--------------------------------------------------------------------------------

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 2"这是非法的。如果真的要用逗号表达式应该写成int a = (1,2);


--------------------------------------------------------------------------------

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?

 

虽然我也觉得不可思议但这样写就是合法的。这是一个拷贝内存的程序,它将循环次数由count次减少为(count+7)/8次,这样写的目的是通过unrolling减少跳转时的开销,并且为编译器优化提供足够的资源。

P.S. 我很好奇在现在的编译器上这种做法能提高多少速度,有空我会去验证一下的

 

--------------------------------------------------------------------------------

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;
  }

 

第二个printf把float当作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;
  }问的地址

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

平常大家之所以会混淆数组和指针的使用,是因为根据C standard,在除了sizeof,&取址操作符,字符串initailizer以外的表达式中,数组a会被转化为指向a[0]的指针

 

运行时错误,误把数组当成指针用去访问了不能访问的资源


--------------------------------------------------------------------------------

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*,所以size得写成宏


--------------------------------------------------------------------------------

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;
  }

 

让用户定义printf的format会有很大的安全隐患。C语言中对于变长参数列表并没有记录参数个数的机制,printf的工作原理是根据format中的% 按顺序从内存中获取参数,而不管该参数是否存在。恶意用户可以通过在这程序里写一堆%s来查看内存数据,更进一步还可以用%n来修改内存数据


--------------------------------------------------------------------------------

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;
  }

 

这题也是有一个严重的buffer overflow安全隐患,用户只要输入超过80个字符就能够覆盖内存数据。通过修改返回地址,恶意用户可以轻易让一个攻击程序获得root权限,具体操作方式请参考wiki:http://en.wikipedia.org/wiki/Stack_buffer_overflow


--------------------------------------------------------------------------------

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:10,sizeof在编译阶段就会计算出结果,所以它不会运行后面的表达式

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


--------------------------------------------------------------------------------

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了就不能修改,请考虑下面这个程序:

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返回匹配的变量个数

4个的,我没有想到好方法,只有算3次gcd了


--------------------------------------------------------------------------------

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;
  }

 

没啥好说的,就是scanf的匹配,必须严格按照格式输入,scanf中的common character遇到不匹配时会立即返回

 


--------------------------------------------------------------------------------

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));
  }

 

?后面必须跟值,return x并不是一个右值

 


--------------------------------------------------------------------------------

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??

 

这题的答案待证实

我的理解是,第一个程序中只有声明而没有定义,所以没有分配内存空间

而extern搜寻的是定义,它只找到第二个a=10,所以没有发生冲突

更多讨论:http://www.velocityreviews.com/forums/t444439-why-no-compilation-error.html


--------------------------------------------------------------------------------

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)))

 

天杀的,都不说一下这程序干嘛的。看了好久才看出来a是struct,b是struct的内部变量,用来算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;

检查第一位,当a与b符号相同但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;

 

第一个,指向的char是const;第二个,p本身是const


--------------------------------------------------------------------------------

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

参考:http://www.cplusplus.com/reference/clibrary/cstdio/printf/


--------------------------------------------------------------------------------

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”)){} }

 

Avatar_small
编程代写 说:
2024年1月12日 14:31

我们逐步成为了留学生计算机作业代写行业中的顶尖公司,同时成长成国际的专业的教育平台。尽管如此,我们还是严格把握质量,保证每一篇论文都是高质量,从而给予留学生最大的方便,让留学也快乐起来。如果您需要代码作业代写、计算机代修、计算机作业代写以及与任何其他与网课相关的帮助, 请一定要联系我们, 我们将为同学们提供最优质的服务, 包您满意!


登录 *


loading captcha image...
(输入验证码)
or Ctrl+Enter