一些C语言题目

*************************************************************

以下转自酷壳 - CoolShell.cn

*************************************************************


1、下面的程序并不见得会输出 hello-std-out,你知道为什么吗?

1
2
3
4
5
6
7
8
9
10
11
12
#include <stdio.h>
#include <unistd.h>
int main() 
{
     while (1)
     {
         fprintf (stdout, "hello-std-out" );
         fprintf (stderr, "hello-std-err" );
         sleep(1);
     }
     return 0;
}

参考答案:stdout和stderr是不是同设备描述符。stdout是块设备,stderr则不是。对于块设备,只有当下面几种情况下才会被输入,1)遇到回车,2)缓冲区满,3)flush被调用。而stderr则不会。

这是因为:stderr在默认是非缓冲的,stdout和stdin默认情况下是行缓冲的,当然它们的缓冲类型都是可以设置的

所以,如果使用stdout,并想立即输出信息,要么是输出信息的结尾添加换行符\n,或者是添加flush(stdout)语句。

         还有就是即时输出的话使用stderr


2、下面的程序看起来是正常的,使用了一个逗号表达式来做初始化。可惜这段程序是有问题的。你知道为什么呢?

1
2
3
4
5
6
7
8
#include <stdio.h>
 
int main()
{
     int a = 1,2;
     printf ( "a : %d\n" ,a);
     return 0;
}

参考答案:这个程序会得到编译出错(语法出错),逗号表达式是没错,可是在初始化和变量声明时,逗号并不是逗号表达式的意义。这点要区分,要修改上面这个程序,你需要加上括号: int a = (1,2);

3、下面的程序会有什么样的输出呢?

1
2
3
4
5
6
7
#include <stdio.h>
int main()
{
     int i=43;
     printf ( "%d\n" , printf ( "%d" , printf ( "%d" ,i)));
     return 0;
}

参考答案:程序会输出4321,你知道为什么吗?要知道为什么,你需要知道printf的返回值是什么。printf返回值是输出的字符个数。

4、下面的程序会输出什么?

1
2
3
4
5
6
7
8
9
#include <stdio.h>
int main() 
{
     float a = 12.5;
     printf ( "%d\n" , a);
     printf ( "%d\n" , ( int )a);
     printf ( "%d\n" , *( int *)&a);
     return 0; 
}

参考答案
该项程序输出如下所示,
0
12
1095237632
原因是:浮点数是4个字节,12.5f 转成二进制是:01000001010010000000000000000000,十六进制是:0×41480000,十进制是:1095237632。所以,第二和第三个输出相信大家也知道是为什么了。而对于第一个,为什么会输出0,我们需要了解一下float和double的内存布局,如下:

  • float: 1位符号位(s)、8位指数(e),23位尾数(m,共32位)
  • double: 1位符号位(s)、11位指数(e),52位尾数(m,共64位)

然后,我们还需要了解一下printf由于类型不匹配,所以,会把float直接转成double,注意,12.5的float和double的内存二进制完全不一样。别忘了在x86芯片下使用是的反字节序,高位字节和低位字位要反过来。所以:

  • float版:0×41480000 (在内存中是:00 00 48 41)
  • double版:0×4029000000000000 (在内存中是:00 00 00 00 00 00 29 40)

而我们的%d要求是一个4字节的int,对于double的内存布局,我们可以看到前四个字节是00,所以输出自然是0了。

这个示例向我们说明printf并不是类型安全的,这就是为什么C++要引如cout的原因了。

5、下面,我们再来看一个交叉编译的事情,下面的两个文件可以编译通过吗?如果可以通过,结果是什么?

file1.c

1
int arr[80];

file2.c

1
2
3
4
5
6
7
extern int *arr;
int main() 
{     
     arr[1] = 100;
     printf ( "%d\n" , arr[1]);
     return 0; 
}

参考答案:该程序可以编译通过,但运行时会出错。为什么呢?原因是,在另一个文件中用 extern int *arr来外部声明一个数组并不能得到实际的期望值,因为他们的类型并不匹配。所以导致指针实际并没有指向那个数组。注意:一个指向数组的指针,并不等于一个数组。修改:extern int arr[]。(参考:ISO C语言 6.5.4.2 节)

6、请说出下面的程序输出是多少?并解释为什么?(注意,该程序并不会输出 “b is 20″)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#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;
}

参考答案:该程序在编译时,可能会出现一条warning: unreachable code at beginning of switch statement。我们以为进入switch后,变量b会被初始化,其实并不然,因为switch-case语句会把变量b的初始化直接就跳过了。所以,程序会输出一个随机的内存值。

7、请问下面的程序会有什么潜在的危险?

1
2
3
4
5
6
7
8
9
#include <stdio.h>
int main() 
{     
     char str[80];
     printf ( "Enter the string:" );
     scanf ( "%s" ,str);
     printf ( "You entered:%s\n" ,str);
     return 0;
}

参考答案:本题很简单了。这个程序的潜在问题是,如果用户输入了超过80个长度的字符,那么就会有数组越界的问题了,你的程序很有可以及会crash了。

8、请问下面的程序输出什么?

1
2
3
4
5
6
7
8
9
10
#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;
}

参考答案:如果你觉得输出分别是,10,4,11,那么你就错了,错在了第三个,第一个是10没有什么问题,第二个是4,也没有什么问题,因为是32位机上一个int有4个字节。但是第三个为什么输出的不是11呢?居然还是10?原因是,sizeof不是一个函数,是一个操作符,其求i++的类型的size,这是一件可以在程序运行前(编译时)完全的事情,所以,sizeof(i++)直接就被4给取代了,在运行时也就不会有了i++这个表达式。

9、请问下面的程序的输出值是什么?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
#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;
}

参考答案:好吧,如果你对于PrintInt这个宏有问题的话,你可以去看一看《语言的歧义》中的第四个示例。不过,本例的问题不在这里,本例的输出会是:1,8,64,1000,其实很简单了,以C/C++中,以0开头的数字都是八进制的。

10、请问下面的程序输出是什么?(绝对不是10)

#include 
#define PrintInt(expr) printf("%s : %dn",#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;
}

参考答案:本题输出的是100。为什么呢?问题就出在 y = y/*p;上了,我们本来想的是 y / (*p) ,然而,我们没有加入空格和括号,结果y/*p中的 /*被解释成了注释的开始。于是,这也是整个恶梦的开始。

11、下面的输出是什么?

1
2
3
4
5
6
7
8
9
10
#include <stdio.h>
int main() 
{
     int i = 6;
     if ( ((++i < 7) && ( i++/6)) || (++i <= 9))
         ;
 
     printf ( "%d\n" ,i);
     return 0;
}

参考答案:本题并不简单的是考前缀++或反缀++,本题主要考的是&&和||的短路求值的问题。所为短路求值:对于(条件1 && 条件2),如果“条件1”是false,那“条件2”的表达式会被忽略了。对于(条件1 || 条件2),如果“条件1”为true,而“条件2”的表达式则被忽略了。所以,我相信你会知道本题的答案是什么了。

12、下面的C程序是合法的吗?如果是,那么输出是什么?

1
2
3
4
5
6
7
8
9
10
11
12
#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; 
}

参考答案
本例是合法的,输出如下:

Hello! how is this? super
That is C !

本例主要展示了一种另类的用法。下面的两种用法是相同的:

“hello”[2]
2["hello"]

如果你知道:a[i] 其实就是 *(a+i)也就是 *(i+a),所以如果写成 i[a] 应该也不难理解了。

13、请问下面的程序输出什么?(假设:输入 Hello, World)

1
2
3
4
5
6
7
8
9
#include <stdio.h>
int main() 
{
     char dummy[80];
     printf ( "Enter a string:\n" );
     scanf ( "%[^r]" ,dummy);
     printf ( "%s\n" ,dummy);
     return 0;
}

参考答案:本例的输出是“Hello, Wo”,scanf中的”%[^r]“是从中作梗的东西。意思是遇到字符r就结束了。

14、下面的程序试图使用“位操作”来完成“乘5”的操作,不过这个程序中有个BUG,你知道是什么吗?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#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;
}

参考答案:本题的问题在于函数FiveTimes中的表达式“t = a<<2 + a;”,对于a<<2这个位操作,优先级要比加法要低,所以这个表达式就成了“t = a << (2+a)”,于是我们就得不到我们想要的值。该程序修正如下:

1
2
3
4
5
6
int FiveTimes( int a) 
{
     int t;
     t = (a<<2) + a;
     return t;

puzzle 1

此段程序的作者希望输出数组中的所有元素,但是他却没有得到他想要的结果,是什么让程序员和计算机产生歧义?

1
2
3
4
5
6
7
8
9
10
11
12
#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;
}

解答:
运行上面的程序,结果是什么都没有输出,导致这个结果的原因是sizeof的返回值是一个unsinged int,为此在比较int d 和TOTAL_ELEMENTS两个值都被转换成了unsigned int来进行比较,这样就导致-1被转换成一个非常大的值,以至于for循环不满足条件。因此,如果程序员不能理解sizeof操作符返回的是一个unsigned int的话,就会产生类似如上的人机歧义。

puzzle 2

看上去非常完美的程序,是什么导致了编程程序不通过?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
#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;
}

解答:
程序员要以计算机的语言进行思考,不上上面那段程序导致的结果不止是歧义这么简单,而直接的结果是,导致计算机”听不懂”你在说什么。导致计算机听不懂的原因是HP-UX中的’-'是减号?还是其他什么?

puzzle 3

下面这段程序会输出什么,为什么?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
enum { false , true };
 
int main()
{
     int i=1;
     do
     {
         printf ( "%d\n" ,i);
         i++;
 
         if (i < 15)
             continue ;
     } while ( false );
 
     return 0;
}

解答:
1到14?不对,结果是1,因为continue的含义是不执行循环体之后语义,而直接到循环点。明显while(false)不属于循环体。导致这段程序的歧义就是:程序员没有完全理解计算机语言中continue的含义。

puzzle 4

下面这段程序的输出结果是:

1
2
3
4
5
6
7
8
9
10
11
#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;
}

当然,你首先要了解##和#的用法,如果不懂的话,本题你可以直接跳过。
解答:
看到这段程序你可能会认为,这两个printf输出的同一个结果,可是答案却非如此,本题的输出是12和f(1,2),为什么会这样呢?因为这是宏,宏的解开不象函数执行,由里带外。

puzzle 5

下面这段程序的输出是什么

#include <stdio.h>
int main()
{
int a=10;
switch(a)
{
case ’1′:
printf(“ONE\n”);
break;
case ’2′:
printf(“TWO\n”);
break;
defau1t:
printf(“NONE\n”);

return 0;
}

解答:
本题我故意将语法敏感插件去掉,为了就是能得到更好的效果,这道题又是什么让歧义再次发生,如果不仔细你可能永远都找不到答案,如果真到的到了那个时候,你是否会因为对default语义的怀疑,而不敢再使用default?本题的歧义点就是default,看好了是defau1t而不是default,不是关键字!为什么计算能”听懂”这样的defau1t,算然它听懂了,但它的理解却是标号”defau1t”

puzzle 6

下面这段程序的输出什么?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#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;
}

解答:
你是否似曾相识?不错这个问题在酷壳之前的博文《你能做对下面这些JavaScript的题吗?》中曾今提到过,不要让两个浮点数相比较。
所以本题的答案是”f is NOT 1.0″,如果你真想比较两个浮点数时,你应该按一定精度来比较,比如你一定要在本题中做比较那么你应该这么做if( (f – 1.0f)<0.1 )

puzzle 7

下面两个函数是否具有相同的原型?

1
2
int foobar( void );
int foobar();

下面这两段程序将会帮你找到上题的答案
程序1

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
#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;
}

程序2

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
#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;
}

解答
程序片段一,没有问题,程序片段二编译报错,这两个程序告诉我们,foobar1(void)和foobar2()是有不同原型的的。我们可以在《ISO/IEC 9899》的C语言规范找到下面两段关于函数声明的描述

10.The special case of an unnamed parameter of type void as the only item in the list specifies that the function has no parameters

14.An identifier list declares only the identifiers of the parameters of the function. An empty list in a function declarator that is part of a definition of that function specifies that the function has no parameters. The empty list in a function declarator that is not part of a definition of that function specifies that no information about the number or types of the parameters is supplied.124)

上面两段话的意思就是:foobar1(void)是没有参数,而foobar1()等于forbar1(…)等于参数类型未知。

总结
看到这些C语言的题目,不禁让我想起了巴别塔,计算机语言作为如此严谨的语言都有可能带来如此多的歧义,更何况自然语言,更何况相互不通的自然语言。要杜绝歧义,我们就必须清晰的了解计算机语言每一个指令的语义。就如同人类,人类要和平就要相互了解各自的文化。愿世界上人们清晰了解别人的语言的语义,愿世界不再因为文化的不同而战争,原世界和平。

(转载本站文章请注明作者和出处 酷壳 – CoolShell.cn ,请勿用于任何商业用途)

——===  访问 酷壳404页面 以支持公益事业 ===——
*************************************************************************************************
以下内容出自  http://www.gowrikumar.com/c/index.html
*************************************************************************************************

一些C语言题目_第1张图片

Dear visitor,

Thanks for your interest in C programming. In this page, you will find a list of interesting C programming questions/puzzles, These programs listed are the ones which I have received as e-mail forwards from my friends, a few I read in some books, a few from the internet, and a few from my coding experiences in C.

Most of the programs are meant to be compiled, run and to be explained for their behaviour. The puzzles/questions can be broadly put into the following categories:

  • General typo errors, which C programmers do often and are very difficult to trace.
  • Small programs which are extremely hard to understand at the first examination. These questions make a good excercise of reading and understanding effecient code written by others.

I have used Gnu/Linux/gcc for all of them. The order in which the programs appear doesn't have any relation with the level of difficulty. Please feel free to contact me if you need any help in solving the problems. My contact info. is available here And you might be interested in a few references for C programming, which I personally found very interesting. 

If you are preparing for campus interviews, you might find the following link interesting:
http://placementsindia.blogspot.com
http://www.interviewmantra.net/category/interview-questions/c


Regards,
Gowri Kumar 

C puzzles

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.
hint

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;
}
hint
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;
}
hint
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?
  #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?
hint
  #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!!
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?
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. 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;
}
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;
}
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;
}
  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? 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;
  }
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;
  }
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;
  }
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;
  }
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;
  }
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;
  }
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;
  }
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;
  }
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;
  }
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;
  }
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;
  }
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;
  }

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;
  }
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. 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;
  }
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;
  }
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. 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;
  }
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;
  }
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;
  }
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;
  }
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;
  }
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;
  }
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?? 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)))
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? What is the use of the following macro?
  #define DPRINTF(x) printf("%s:%d\n",#x,x)
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?) What does the following macro do?
  #define ROUNDUP(x,n) ((x+n-1)&(~(n-1)))
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. 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 . What does the format specifier  %n  of  printf  function do? 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....) 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;
What is the difference between  memcpy  and  memmove ? What is the format specifiers for  printf  to print double and float values? Write a small C program to determine whether a machine's type is little-endian or big-endian. Write a C program which prints  Hello World!  without using a semicolon!!!


This work by CH Gowri Kumar is licensed under a Creative Commons Attribution-ShareAlike 3.0 Unported License.


你可能感兴趣的:(c)