C puzzles详解【13-15题】
第十三题
int CountBits(unsigned int x)
{
int count=;
while(x)
{
count++;
x = x&(x-);
}
return count;
}
知识点讲解
- 位运算
关于位运算的一些例子参考:
http://www.ugcs.caltech.edu/~wnoise/base2.html
题目讲解
x&(x-1)常见的两种应用:
1)计算x二进制形式中1的个数,每循环一次,将x二进制形式最右边的1变成0;
2)判断x是否是2的幂,若x&(x-1)==0,x为2的幂。
第十四题
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 :
#include <stdio.h>
void foobar1(void)
{
printf("In foobar1\n");
} void foobar2()
{
printf("In foobar2\n");
} int main()
{
char ch = 'a';
foobar1();
foobar2(, ch);
return ;
}
Program :
#include <stdio.h>
void foobar1(void)
{
printf("In foobar1\n");
} void foobar2()
{
printf("In foobar2\n");
} int main()
{
char ch = 'a';
foobar1(, ch);
foobar2();
return ;
}
知识点讲解
- foo()和foo(void)是不一样的
调用foo()时,可以传入任意个数,任意类型的参数,编译器不会关心传给foo的参数,传入的参数对foo函数的执行没有影响;
调用foo(void)时,不可传入参数,否则编译不通过;
void foo() {}是定义无参数函数的一种过时的用法,故日常编写代码时,若函数没有参数,最好写成foo(void)的形式。
题目讲解
Program 1能编译通过,运行后正常打印两个字符串;
Program 2编译不通过,提示foobar1参数过多。
第十五题
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 ;
}
知识点讲解
- printf中的%f读取sizeof(double)个字节;
#include <stdio.h> int main()
{
int a = , b = , c = ;
printf("%f, %d\n", a, b, c);
return ;
}
输出:0.000000, 30
调用printf时,双引号后面的所有参数从右往左依次入栈,然后将栈中的数据根据双引号中的格式从低地址向高地址依次读取并打印出来。
上述代码调用printf时,c,b,a依次入栈,%f读取sizeof(double)=8个字节,
即a,b所占的区域,转换成浮点数为0.000000,%d继续读取下面4个字节,即c所占的区域,转换为整型数为30。
- printf中传入的float型参数自动转换成double型;
#include <stdio.h> int main()
{
float a = 1.2;
int b = ;
printf("%x, %x, %d\n", a, b);
return ;
}
输出:40000000, 3ff33333, 10
调用printf时,参数a被转为double型后再传入printf,printf的前两个%x读取的是a所占的8个字节,%d读取的是b所占的4个字节。
gcc –S test.c命令可以生成汇编代码,上例的汇编代码主体如下:
main:
pushl %ebp
movl %esp, %ebp
andl $-, %esp
subl $, %esp
movl $0x3f99999a, %eax
movl %eax, (%esp)
movl $, (%esp)
flds (%esp)
movl $.LC1, %eax
movl (%esp), %edx
movl %edx, (%esp)
fstpl (%esp)
movl %eax, (%esp)
call printf
movl $, %eax
leave
ret
“flds 28(%esp)”,flds将28(%esp)地址处的单精度浮点数即0x3f99999a加载到浮点寄存器,“fstpl 4(%esp)”即将浮点寄存器中的浮点数转换成double型后放到4(%esp)处。
- printf中的%c读取4个字节,printf的char型参数先转换为int再入栈;
#include <stdio.h> int main()
{
char a = ;
int b = ;
printf("%c, %d\n", a, b);
return ;
}
输出:a, 20
上述c代码的汇编代码主体为:
main:
pushl %ebp
movl %esp, %ebp
andl $-, %esp
subl $, %esp
movb $, (%esp)
movl $, (%esp)
movsbl (%esp), %edx
movl $.LC0, %eax
movl (%esp), %ecx
movl %ecx, (%esp)
movl %edx, (%esp)
movl %eax, (%esp)
call printf
movl $, %eax
leave
ret
“movl %edx, 4(%esp)”在栈中压了4个字节。
- sizeof(‘a’)=4;
#include <stdio.h> int main()
{
char a = 'a';
printf("%d, %d\n", sizeof(a), sizeof('a'));
return ;
}
sizeof求类型的大小,sizeof(a)即sizeof(char),sizeof(‘a’)即sizeof(int),‘a’自动转换为int型。
题目讲解
“printf("%d\n", a);”,a转换为double型再入栈,%d读取double型数据的低4个字节;
“printf("%d\n", *(int *)&a);”float占4个字节,*(int *)&a将a在内存中存放值转换为整型数后再传入printf。
浮点数在内存中如何表示参考第九题讲解。
C puzzles详解【13-15题】的更多相关文章
- C puzzles详解【1-5题】
第一题 #include<stdio.h> #define TOTAL_ELEMENTS (sizeof(array) / sizeof(array[0])) ,,,,,,}; int m ...
- C puzzles详解【38-45题】
第三十八题 What is the bug in the following program? #include <stdlib.h> #include <stdio.h> # ...
- C puzzles详解【9-12题】
第九题 #include <stdio.h> int main() { float f=0.0f; int i; ;i<;i++) f = f + 0.1f; if(f == 1.0 ...
- C puzzles详解【51-57题】
第五十一题 Write a C function which does the addition of two integers without using the '+' operator. You ...
- C puzzles详解【46-50题】
第四十六题 What does the following macro do? #define ROUNDUP(x,n) ((x+n-1)&(~(n-1))) 题目讲解: 参考:http:// ...
- C puzzles详解【34-37题】
第三十四题 The following times. But you can notice that, it doesn't work. #include <stdio.h> int ma ...
- C puzzles详解【31-33题】
第三十一题 The following is a simple C program to read and print an integer. But it is not working proper ...
- C puzzles详解【26-30题】
第二十六题(不会) The following is a simple program which implements a minimal version of banner command ava ...
- C puzzles详解【21-25题】
第二十一题 What is the potential problem with the following C program? #include <stdio.h> int main( ...
- C puzzles详解【16-20题】
第十六题 The following is a small C program split across files. What do you expect the output to be, whe ...
随机推荐
- 在win7电脑中如何查看运行进程的PID标识符
在介绍技巧方法之前,咱们还是先来介绍一下什么是PID标识符,这个PID标识符就是系统对运行中的程序自动分配的一个编号,是用来识别对应进程的,而且这个编号也是一一对应,不会有重复的,只有当系统结束运行的 ...
- http请求的referer属性
HTTP Referer是header的一部分,当浏览器向web服务器发送请求的时候,一般会带上Referer,告诉服务器我是从哪个页面链接过来的,服务器籍此可以获得一些信息用于处理.比如从我主页上链 ...
- C#EasyHook例子C# Hook 指定进程C#注入指定进程 z
http://bbs.msdn5.com/thread-75-1-1.html http://pan.baidu.com/s/1pJDgHcR
- Heka–>Elasticsearch 索引数据过程的优化
Heka 的参数配置跟Elasticsearch的参数没有关系,Heka只负责按照配置发送数据,所以索引的优化主要在 Elaticsearch端来完成. 下面是Elasticsearch的一些相关概念 ...
- 安装jdk java -version 不是自己所需要的版本
原服务器安装有1.4的jdk,应用需要安装1.6的jdk.安装完毕后在/etc/profile里配置1.6jdk的环境变量后使用命令java -version显示还是原来的1.4的版本. 解决办法: ...
- POJ 2104 【主席树】【区间第K大】
#include<stdio.h> #include<algorithm> #include<string.h> #define MAXN 100010 #defi ...
- php 分享两种给图片加水印的方法
本文章向码农们介绍 php 给图片加水印的两种方法,感兴趣的码农可以参考一下本文章的源代码. 方法一:PHP最简单的加水印方法 <?php // http://www.manongjc.com ...
- 玩转JS插件系列
说明:本系列文章只是通过学习JS插件源码来巩固自己的JS知识,不涉及任何商业目的,如有侵犯版权请尽快告知 一.UI 背景 对话框和灯箱 筛选及排序 反馈 弹出层 悬停 布局 图表 加载 圆边 滚动 标 ...
- 网站注册(css)
<! DOCTYPE HTML><html><head><meta charset="utf-8"><title>作业2 ...
- 覆盖原有div或者Input的鼠标移上去描述
<input onmouseover="this.title='我是描述内容'" />