C语言知识点考题

其实已经看了很多很好的帖子,但是只看帖子不能达到系统的认识/最新的认识,一定要看官方标准/大牛著作!

值得深究的有4

1、下面的程序并不见得会输出 hello-std-out  在Qt 5.2 Plain C Project下测试,每次都会输出hello-std-out

#include <stdio.h>
#include <unistd.h>

int main(void)
{
    while(1)
    {
        fprintf(stderr,"hello-std-err ");
        fprintf(stdout,"hello-std-out ");
        sleep(1);
    }
    return 0;
}
参考答案stdout是块设备,stderr则不是。对于块设备,只有遇到下面几种情况下才会被输入,1)遇到回车,2)缓冲区满,3)flush被调用。

 

 2、下面的程序看起来是正常的,使用了一个逗号表达式来做初始化。

#include <stdio.h>

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

 

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

#include <stdio.h>
int main()
{
    int i=43;
    printf("%d\n",printf("%d",printf("%d",i)));
    return 0;
}
运行结果:


参考答案:printf返回值是输出的字符个数。

 

4、下面的程序会输出什么  这个值得重点分析,涉及到计算机内部存储数据的格式,需要补补计算机系统结构了

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

运行结果:


参考答案:浮点数是4个字节,12.5f 转成

二进制是:01000001010010000000000000000000,

十六进制是:0x41480000,

十进制 是: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版:0x41480000 (在内存中是:00 00 48 41)

double版:0x4029000000000000 (在内存中是:00 00 00 00 00 00 29 40)

而我们的%d要求是一个4字节的int,对于double的内存布局,我们可以看到前四个字节是00,所以输出自然是0了。 这个示例向我们说明printf并不是类型安全的,这就是为什么C++要引如cout的原因了。

 

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

file1.c

int arr[80];
file2.c 
extern int *arr;
int main()  
{      
    arr[1] = 100;
    printf("%d\n", arr[1]);
    return 0;  
}
Visual Studio 2010 编译错误提示:

参考答案:一个指向数组的指针,并不等于一个数组。修改:extern int arr[]。(参考:ISO C语言 6.5.4.2 节)

 

 6、是关于switch语句的,参见博文:switch的三个注意点

 

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

#include <stdio.h>

int main()  
{      
    char str[80];
    printf("Enter the string:");
    scanf("%s",str);
    printf("You entered:%s\n",str);
   
    return 0;
}
记得刚学C语言时,字符串以‘\0’结束这个知识点被我忽略了很久,也因此让我有点时间遇到类似问题,痛苦的要死。
参考答案:本题很简单了。这个程序的潜在问题是,如果用户输入了超过80个长度的字符,那么就会有数组越界的问题了,你的程序很有可以及会crash了。

 

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

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

}
运行结果:Tested by Qt Plain C Project

参考分析:sizeof不是一个函 数,是一个操作符。求(i++)的类型的size,这是一件可以在程序运行前(编译时)完全的事情,所以,sizeof(i++)直接就被4给取代了,在运行时也就不会有了i++这个表达式。

  9、请问下面的程序的输出值是什么
#include <stdio.h>
#include <stdlib.h>

#define SIZEOF(arr) (sizeof(arr)/sizeof(arr[0]))  // 我愚昧了,以前从来没想过用这种方式计算定义时未指定
                                                  // 数组长度的数字的长度
#define PrintInt(expr) printf("%s:%d\n",#expr,(expr))  // #expr以字符形式输出expr

int main()
{
	int pot[] = {
		0001,
		0010,
		0100,
		1000
	};
	int i;
	for(i=0;i<SIZEOF(pot);i++)
	{
		PrintInt(pot[i]);
	}

	return 0;
}

运行结果:

参考答案:其实很简单,在C/C++中,以0开头的数字都是八进制的。 


10、下面的输出是什么

#include <stdio.h>

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

	return 0;
}
运行结果:


参考答案:本题主要考的是&&和||的短路求值的问题。

 

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

#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"[2], 2["hello"]。如果你知道:a[i] 其实就是 *(a+i)也就是 *(i+a),所以如果写成 i[a] 应该也不难理解了。 

 

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

#include <stdio.h>

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

	return 0;
}
运行结果-1:


运行结果-2:


参考答案:"%[^r]",当且仅当遇到字符r才结束输入,而且r不被指针接收。 

 

13、下面的程序试图使用“位操作”来完成“乘5”的操作

int FiveTimes(int a)  
{
    int t;
    t = a<<2 + a;  // 因为<<的优先级低于+,所以正确的是:t = (a<<2) + a; 

    return t;
}


原文:http://wenku.baidu.com/link?url=MyfwrskYY2luO69lroATY4BAN-e040K_07TGAw44yYNomfMs-Ku7oCHNgy2J8lPfXHZlGv2t59RTafNroVAVshPHqczRCFPL31wBuvv6L1K


 

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值