博文
结构体的成员变量的对齐问题(2006-04-06 17:08:00)
摘要:结构体的大小是一个令人迷惑不解的问题,不信,我出一题让你算算看:
enum DataType{IntData,CharData,VcharData};
struct Item
{
char ItemNAme[30];
DataType ItemType;
char ItemDecr[50];
int ItemLength;
};
在你使用sizeof之前你能知道它的大小吗?我想即使你用sizeof得出结果后,结果还是会让你大吃一惊的:怎么是这个?
一.为什么要对齐?
《Windows核心编程》里这样说:当CPU访问正确对齐的数据时,它的运行效率最高,当数据大小的数据模数的内存地址是0时,数据是对齐的。例如:WORD值应该是总是从被2除尽的地址开始,而DWORD值应该总是从被4除尽的地址开始,数据对齐不是内存结构的一部分,而是CPU结构的一部分。当CPU试图读取的数值没有正确的对齐时,CPU可以执行两种操作之一:产生一个异常条件;执行多次对齐的内存访问,以便读取完整的未对齐数据,若多次执行内存访问,应用程序的运行速度就会慢。在最好的情况下,是两倍的时间,有时更长。
二.成员变量对齐的原理
我花了一个上午,看了一些资料,总算把这个问题搞明白了。下面我以一些例子说明结构体成员变量的对齐问题。
对于
struct s1
{
char a;
long int d;
double c;
};
这个结构体的大小是16。编译器默认的一般是8字节对齐。a的大小是1,它就按1字节对齐(因......
C++学习笔记(一)使用友元重载运算符(2006-03-03 22:01:00)
摘要:
C++的多态性的一个重要体现是运算符重载。下面我以复数运算为例说明友元重载运算符。
首先在VC上建一个简单的win32控制台程序。程序源码如下:
class ComplexNum
{
public:
ComplexNum(); // 构造函数
ComplexNum(float Vreal,float Vimage); // 重载构造函数
friend ComplexNum operator + (ComplexNum p1,ComplexNum p2); //重载+运算符
friend ComplexNum operator - (ComplexNum p1,ComplexNum p2); //重载-运算符
friend ComplexNum operator * (ComplexNum p1,ComplexNum p2); //重载*运算符
friend ComplexNum operator / (ComplexNum p1,ComplexNum p2); //重载/运算符
void PrintComplexNum(); // 打印复数
private:
float real; &......
一个字符统计程序(2006-01-16 11:02:00)
摘要: 我编了一个程序,统计一段字符中的字母字符,数字字符、空格字符和其他字符的个数。程序运行环境:Windows2000, VC++6.0。程序如下:
#include <stdio.h>
void StatisticsSymbol2(char *pChar)
{
int i=0;
int NumberCount=0,LetterCount=0,BlankCount=0,OtherCount=0; // 初始化各个统计变量
for(i=0;pChar[i]!='\0';i++)
{
if(( pChar[i]>47 )&&( pChar[i]<58 ) ) // 假如是数字,数字计数加1
{
NumberCount++;
continue;
}
if( ( pChar[i]>64 && pChar[i]<91 ) ||( pChar[i]>96 && pChar[i]<123 ))/* 假如是字母,字母计数加1 */
{
LetterCount++;
continue;
}
if ( pChar[i]==' ') // 假如是空格,空格计数加1
......
求两数的最大公约数和最小公倍数(2006-01-15 20:44:00)
摘要: 从今天开始,我决心利用寒假把谭浩强的《C程序设计》(从第6章到第13章)的所有习题做一遍,发表在我的blog上。
算法思路: 可以有三种方法求两数的最大公约数。设m>n。
1. 让k从1变到n,能同时整除m和n的最大的k即为所求。
2. 让k从n变到1,第一个能同时整除m和n的k即为所求。
3. 使用辗转相除法。辗转相除法的算法为:首先将 m除以 n(m>n)得余数 r,再用余数 r 去除原来的除数,得新的余数,重复此过程直到余数为 0时停止,此时的除数就是m 和 n的最大公约数。 经常使用的算法是辗转相除法。 求 m和 n的最小公倍数: m和 n的积除以 m和 n 的最大公约数。我的程序使用的是辗转相除法。由于程序比较简单,所以没有加注释。程序运行环境:Windows2000, VC++6.0。
#include
void MaxandMin(long Num1,long Num2)
{
long Temp=0;
if(Num1>=Num2)
{
Temp=Num2;
while((Num1%Num2)!=0)
{
Num2=Num1%Num2;
}
printf("最大公约数为%d\n",Num2);
Temp=( Num1*Temp )/Num2;
printf("最小公倍数为%d\n",Temp);
}
else
{
Temp=Num1;
while((Num2%Num1)!=0)
{
&nb......
已知三点坐标,求圆心的坐标和半径(2005-09-09 12:50:00)
摘要:朱金灿
这是一个值得探讨一下的程序。一般实现同一程序功能往往有不同的思路。
这个程序也是如此。一般的思路是:
1、先判断三点能否构成一个圆,具体来说就是看其中一点是否在另外两点连成的直线上,三点共线的话就输出“error”;
2、如果三点不共线,接下来就是求圆心,即三点构成的三角形的其中两边的垂直平分线交点;
3、最后随便找一点与圆心即可求出半径。
实际上用两条弦的垂直平分线的交点确定圆心的方法并不好,理由如下:
假设现在假设三点为(x1,y1),(x2,y2),(x3,y3),求它们的中垂线要使用的点斜式,这样一来,要考虑的情况比较多:
1.(x1,y1),(x2,y2)连线和(x2,y2),(x3,y3)连线的斜率为0和无穷大都要考虑,二者组合就是4种,再加上某一连线斜率为0或无穷大,而另一斜线斜率不为0和无穷大,考虑的情况更多了。
一个更为简单的方法是首先判断三点是否一线,这里分为两种情况:
1.三点连成的直线没有斜率,判断条件(y1==y2)&&(y2==y3)
2.判断任意两点连成的直线斜率是否相等。
3.解方程组,设圆心坐标为(x,y)
圆心到任意两点的距离相等,由此求出x,y的表达式,代入程序。
4.求出圆心,半径迎刃而解。
有些同学用圆心到点的距离来定圆心,速度低。其实大可不必。用圆心到点的距离来定圆心速度低,这只是一个简单的计算问题,而计算能力强正是电脑的特长。
下面是我的源程序,在vc6.0编译通过。
#include<iostream.h>
#include<math.h>
int main()
{
int x1,y1,x3,y3;
d......
我们应该如何阅读代码(2005-09-06 22:41:00)
摘要:
阅读大量代码是提高编程水平的一个重要手段。初学编程的学生往往爱依样画瓢,照着书上的代码把程序敲出来,做出所谓的“成果”。这样做的结果是你还是你,程序代码还是别人的,离开书本你什么也干不了。我赞同一位专家的说法“编程水平的高低不是看你掌握了多少例程和函数,而是看你控制数据流程的水平的高低”。具体来说就是程序的具体执行过程,程序中的变量值的变化在你的脑海中有一个清晰的印象。为此我认为在阅读代码的同时写出程序的伪代码和流程图有助于提高我们的控制数据流程的水平。
......