2007年04月22日

在上学期就很想去大学城玩了,想去那踩二人单车, 也想去各个校区看看, 只是那时有人不屑理偶的这个小小愿望, 而部门的小伙们又要考试没时间成行,一直拖到现在,终于终于实现了小小的这么个简单的愿望了. 踩着单车,沿着外环,再偶尔进去某个学校打扰一下,偶尔进去宿舍区TK那的PPMM….

9点半正门出发,到广工与华工中间的综合商业南区那租单车,等齐人,一行12人就冲向外环,那个夕阳就如同于上了电动似的,疯狂地往最前冲着,呵,偶也很想冲啦,无奈基于两个不公平:体力不公平,与单车的不公平,就是只能小居第二了,哈哈..

下面贴图:(有个专业摄影师在旁照相就是不一样阿..)

到达第一个点- 华工

这是偶们从拐进外环后到达的第一个点,也就是偶们亲爱的大学城华工校区的正门啦,一个与北校区如出一辙的校门,一群华工人,.来了第一个大合影,我们的出发!

在路上

在路上的我们,.大学城的路况真的非常好,加上租来的单车也挺不错的,迎着风,踩着,真的很是舒服,,,就是这么一点,又在我心中,为广州加了一个砝码….那时心里头冒着的几个字就是 "I love 广州!"..

广外小桥

广外校区,一开始转入广外,大家嬉笑着要进去看美女,入口处没有任何关于广外的标牌,而进去的那个平淡无奇的甚至于称得上简陋的广场,让我大失所望,可是没想到就在左手边,那小河上,那河上面的三座也桥, 还有那河边的风景,让偶直喊我想在这过我的本科四年! 如果如果,我现在才是高中,我要先来大学城上本科,然后再到市区上研究生,呵呵..跟着另一帅哥两人抢先骑车在三座桥跑了个来回, 抢先enjoy了一把..

广外建筑

广外边上的一处建筑,这样照很漂亮..大学城真的是投入了好多好多的M,单从建筑上就可看出,有些并不是出于实用性,而是还要这么讲究造型的…..而且很多地方更是因为着大把的空间利用就大量地使用些特别的手法,虽然视觉确实比较独特,可是也是实实在在的浪费空间哪..

我们的阵型- 踩直线

我们的阵型,踩直线.

我们的阵型- 曲线

我们的阵型

我们的阵型- 回旋

就是我啦,留下罪证一个,在黄埔军校前面…我们骑车到了黄埔军校,但并没有进去,这是来广州这么久第一次来这,可是依旧没有进去,木有兴趣,,,

两个喜欢跑来跑去的帅哥,那个那个摆得一幅潇洒样子的就是这次的头驴—夕阳MM啦~~

再一次的合影,在我们离开黄埔军校之前..

从黄埔军校回去的路上,再去了一山清水秀的地方走了一下,然后就回到大学城,把车还了,然后还小试了二人单车,,总算总算又过二人单车的体会啦..接着就又是杀人,杀人,,晚上再去广工边上吃了烧烤,一行人再杀回市区, ..

2007年04月20日

做了一个月的猪的我,居然居然失眠了.而且是一失到底.直接一晚没睡,过来实验室玩

难道就我昨晚喝的茶太有效了?难道就我昨晚精神过于兴奋了?然后睡不着还喝了杯朱古力味麦片…

话说,舍友们不知怎么扯到了’虒子’这种早已离我们N多光年的小物种,然后就把偶小时候一大把一大把的记忆都扯了出来,跟她们大聊起小时我们是怎么与这小动物战斗,并怎么屡屡成功地将其除去.

说完了这小物种,早就到了睡觉时间了,于是躺下正想舒服睡去,谁知那些童年趣事全都争着冒出来,那些早就给我忘记了的小事,全跑出来提醒小时候的偶是怎么怎么样的开心,怎么怎么样的无忧无虑….于是乎,这个傻女人就这样躺着,傻傻地笑,….然后就使劲地把小时那些那些事挖出来,挖着挖着就睡不着了…净想着怎么样把这些简单而又快乐的事写出来.

更惨的是,这边才想了一些,另一些关于以后的想法也赶来凑热闹了,干嘛哪,以前和以后,现在我需要的是睡觉叻! 继续着在那想得美美的,美得更加睡不着了..

过了一会,英语单词也来凑热闹了,有个昨天和前天才看过的单词,还有一个应该非常熟悉的单词,突然间就死活都记不起来是咋样,这俩单词就在那吵着我,吵得我精神大好..

好吧,下床跟某个习惯夜行的女人聊天,可她不大鸟我,也是,这夜深人静的,怎么能聊天呢,会吵到人的…只能在那晃来晃去,要命的是没电脑可用,以前偶可是通过电脑来解决失眠问题的.这次好了,在我喝了一杯麦片,小修了下眼镜(没修好),把明天包里的东西准备了下,非常认真地研究了好又多的购物单,再小修下眉毛,写了篇日记后,精神更加好了! 好吧,接着就边听MP3,边把书柜来个大整理,把桌面上的布置再改改,还创造性制作了一个小摆饰(没像机,要不就拍上来了:( )….

晃阿晃,终于到了5点多,也该告一断落了,好,眼睛告诉我它们很困了,上床睡觉..这时肚子不同意了,大大声地叫了好久在那抗议它的长时间遭受的忽略..天就这么慢慢地亮了,,不一会广播也响起来了,…天阿,偶还是睡不着!!!! 丫的! 偶不睡了!………….

睡神呀,快来找我,把我叫回去宿舍睡觉吧

2007年04月15日

终于正式升格当阿姨了,还是个"鳄鱼"(二姨)..
虽然好奇你的样子,不过现在你肯定还红红丑丑的,
过些天再回家看看这家里的小宝贝吧.
乖乖地,好好地,
虽然俺们又是一女孩身,
不过照样不会比他们男的差的..
我想你这小家伙肯定是一鬼灵精怪的..
在你妈妈肚子里的时候就那么喜欢动了.
这样的女孩子俺最喜欢啦,
HOHO.白羊座的女孩子..
你那臭美老爹说你长相结合了你爸妈的优点,
等偶验过再说吧,哈哈..

快乐与毅力,
嗯…快快乐乐,做事有毅力..

2007年04月07日

临睡前无聊地跑到lqqm看贴子,偶然间看到love置底的"我救了他,他抢了我的老婆". 一看欲罢不能,超过1k行的贴子,很长很长,,又想一次性看完,于是…看到5点过才爬上床睡觉.

文章是来源于现实,又有别于现实.

 当一个人沉迷于某些东西时就会忘记了自己身边最为宝贵的东西,甚至为了沉迷而一而再再而三地去伤害最为亲爱的人,最为宝贝的东西. 只到梦醒,却一切不可重来.任凭你再如何挽回,再如何心碎都无济于事..

文里的男主人公确实是很知道自己想要什么的人,在面对这事的时候,大多时间总是能保持冷静,(在现实中有人也能这么冷静么?) 面对着本以为完美的妻子的背叛,在选择怎么应对叛离的人,以及选择继续还是放手…有时候,即使即使你再怎么不舍得放手,不舍得那么多年的感情,以及面对两个家庭和周围人的眼光, 毅然选择放手,只因知道那永远是自己无法不去在意的伤,….

当一人沉迷了一种心情,沉迷(另一种说法是专注)于一种事物时,总是容易忽略其它的一些人一些事…只有时间和生活能让他/她在某一时刻清醒地认识到这么一种沉迷.

 

向左走?还是向右走?
不同的方向,不同的路,不同的生活.

今天爸爸过来,陪着他去见他的一个朋友,
席间又谈到了偶的工作问题,
于是乎,又把我从逃避状态抓回现实中…
学校or企业?
各有各好,各有各坏,
真的不知道如何取舍,
也因不到非取舍不可的时候而不去作选择,
广州or 另一城市?
又是两种不同生活的选择..

从去年开始,就被告知要在这一年里想清楚这个问题,
自己一直的郁闷也归根于此,
是天秤座的犹豫?还是懒惰?
让我久久放不下..

嗯…自己做选择的同时,或许别人也会帮你做选择…
时候到了自然会有所选择…..为什么大家都喜欢稳定?
为什么都喜欢轻松悠闲的工作?
生活除了工作还有很多..
让生活见鬼去吧! 我参不透!
好,继续不想….
暂时我还可以随意地走,管它向左还是向右………..哈哈…

2007年03月15日

引言
    在C++的消息公告板上经常可以看到出现ASSERT错误的求助信息。虽然这通常是希望消除ASSERT错误的帮助请求,但是几乎所有的求助者都认为ASSERT本身是罪恶的。我完全能理解一个ASSERT错误给程序员新手带来的沮丧。你的程序正在运行,通常如你所愿,突然一声巨响——一个ASSERT错误!
    那么就让我们来看看ASSERT们,为什么他们会出现在那里以及我们能从他们那里得到什么信息。我应该强调一下,这篇文章讨论MFC如何处理ASSERT。

语言学
    打开google搜索,输入“define assert”,然后单击搜索。WordNet中“ASSERT”有四种意思:
    1.断言、声称、主张……(直接了当的陈述)
    2.确认、查证、承认、宣誓……(正式而严肃的宣告某事属实,如:“Before God I swear I am innocent”——“在上帝面前我发誓我是清白的”)
    3. 坚持己见大胆地或强有力地提出(自己)的观点,以使其为大家所知。(“Women should assert themselves more!”)
    4.强调、表明(表明事实,“The letter asserts a free society”)
    上面的意思都很接近,但是第4个意思字面上更加接近我们的ASSERT。ASSERT表明条件已经被强调为真。如果条件不为真,则程序将处于严重故障中,而你——程序员,则应该收到这个警告。

ASSERT在代码中的意思
    当一个程序员写一条ASSERT就表明他在说“这个条件必须为真,否则我们将发生错误”。比如你正在写一个函数,希望得到一个字符串指针。
void CMyClass::MyFunc(LPCTSTR szStringPtr)
{
    if (*szStringPtr == ’7’)
        DoSomething();
}
这个函数读取这个指针所指向的内存段,因此它最好是指向一段合法有效的内存。否则你的程序将崩溃!如果你传递一个空指针给这个函数,那么任何程序在调用这个函数时都将发生错误。如果现在那个指针就是空的,而且你的程序崩溃了,你就没有足够的信息出处理它。仅仅只有一个消息框,告诉你一个代码地址和你曾尝试读取0×00000000段的内存。关联这个代码地址到你实际代码的那一行并不是一件轻松的事,尤其你对于处理这种情况还很生疏。
    那么让我们对这个函数做一个小小的修改。
void CMyClass::MyFunc(LPCTSTR szStringPtr)
{
    ASSERT(szStringPtr);

    if (*szStringPtr == ’7’)
        DoSomething();
}
这里所做的就是测试szStringPtr。如果为空则马上崩溃。崩溃?是的。但是如果你正用DEBUG编译程序它会以一种受控的方式崩溃。MFC拥有一些build-in plumbing能够捕捉受控的崩溃,并将其和编译器的副本联系到一起。如果你正运行这个程序的DEBUG,并且ASSERT失败,你将会看到一个与此类似的消息框。


这向你表明哪个文件哪一行触发了ASSERT.你可以选择abort,中止程序;也可以选择ignore忽略这个错误,有时这样做也奏效;或者你可以选择retry,重试。只要你的计算机上安装了调试器,即使单独运行这个程序这条语句也会起作用。

release和debug之间的区别
    懂得ASSERT是编译助手很重要。如果你用DEBUG编译你的程序,编译器就会包含ASSERT(…)中的所有代码。如果你选择RELEASE编译,那么ASSERT本身以及圆括号中的所有代码都会消失。它认为你已经测试过你程序的DEBUG版了,并且捕获了所有可能的错误。如果你不幸漏掉了一个错误,并且发布了一个带有BUG的程序,你只能祈祷它能蹒跚着一路平安了。有时乐观也是一件好事!
    有时也会有这种情况出现,你希望在DEBUG版里强调某条件为真,而有一些你又希望不论是在DEBUG版里还是在RELEASE版里都希望你所强调条件的代码被编译到程序里去。这时就要用到VERIFY了。在DEBUG版里VERIFY能让你跳到编译器中条件不满足的事件那里。在RELEASE版里,VERIFY中的代码仍然被包含在可执行文件中。举例来说:
VERIFY(MoveFile(szOriginalFilename, szNewFileName));
以上语句在DEBUG版里,如果MoveFile()函数失败则会产生一个调试ASSERT.无论选择那种方式编译程序,MoveFile()函数的调用都会被包含到程序中。但是在RELEASE版里,调用失败会简单地被忽略。与下面这条语句作个比较:
ASSERT(MoveFile(szOriginalFilename, szNewFileName));
在DEBUG版里,MoveFile()会被编译和执行。而在RELEASE版里这一行就完全消失了,没有任何文件试图被移动。

在MFC中跟踪ASSERT
    如果你现在还在继续往下读,希望从中了解ASSERT错误,比较大的可能是你正在调试的ASSERT并不是来自你自己的代码。如果你够幸运,它会来自MFC,因为你拥有它的源代码。
    需要记住的第一件事是它不太可能是由MFC中的BUG造成的。我不否认MFC中存在BUG,但是在我使用MFC的十多年中,我从来没有遇到过一个ASSERT是由MFC的BUG造成的。
    第二件需要记住的事是ASSERT的出现一定有原因。你需要检查触发ASSERT错误的那一行代码,并且弄明白它在测试什么。
    举例说来,相当一部分MFC类是围绕WINDOWS控件的。许多情况下,封装函数将一个SendMessage调用转化得看起来像一般函数,以此来简化你的编码。比如,CTreeCtrl::SortChildren()函数,接受一个树形句柄,并对其子项进行分类。在你的代码中可能类似下面的语句:
m_myTreeCtrl.SortChildren(hMyNode);
事实上,这个类向树形控件发送了一条消息。你只是简单的调用了一个函数,而MFC则具体传递那条消息需要用到的参数。下面是MFC源码中重新格式过的函数代码:
_AFXCMN_INLINE BOOL CTreeCtrl::SortChildren(HTREEITEM hItem)
{
    ASSERT(::IsWindow(m_hWnd));
    return (BOOL)::SendMessage(m_hWnd, TVM_SORTCHILDREN,0, (LPARAM)hItem);
}
它做的第一件事是表明你的CTreeCtrl对象中的窗口句柄是合法有效的!现在我真的不知道如果你试图送一个TVM_SORTCHILDREN消息到一个不存在的窗口会有什么坏事情发生。我所知道的是:在我正在尝试那么做的时候,我希望被告知。如果我正在做一些没有成功希望的事情,ASSERT在这里可以直接警告我。
    因此如果你在调用类似那样的函数时遇到了ASSERT错误,你最好看看失败的那一行,并会发现它正在强调窗口句柄必须是一个存在的窗口。那是它唯一强调的事情。如果它失败,唯一的可能就是那个句柄窗口并不存在。那些就是你跟踪错误的线索。
    上面是一个简洁的例子说明MFC是如何使用ASSERT的,以及你如何在你的工程中发现MFC的ASSERT原因。现在让我们来看看如何在自己的代码中应用ASSERT。
void CMyClass::MyFunc(LPCTSTR szStringPtr)
还是来看这个函数,前面我提到用一个简单的检查来使所传递的指针非空。事实上我们可以比上面做得更好。MFC和WINDOWS本身都提供了一串函数,我们可以使用它们来测定一个指针是否指向一段有效内存。
void CMyClass::MyFunc(LPCTSTR szStringPtr)
{
    ASSERT(szStringPtr);
    ASSERT(AfxIsValidString(szStringPtr));

    if (*szStringPtr == ’7’)
        DoSomething();
}
第一条语句仅仅捕获一种错误,即是否空指针。加上第二条语句我们就可以测试指针是否指向有效内存。这个测试检查你是否拥有读取该段内存的权限,并且该内存段包含字符串的结束符。一个相关的函数是AfxIsValidAddress,它检查你是否有权访问前面调用中声明过大小的内存块。你也能够检查是否有这个块的读或者写权限。

其它的ASSERT检查
    除了前面提到的两种检查,还可能用到检查一个传递的对象是否某个特定类型。如果你正在写一个处理CEmployee对象和CProduct对象的程序,显然他们不能互换。因此需要确认处理CEmployee对象的函数只接受相应类型的对象。在MFC中你可以像下面这样做:
void CMyClass::AnotherFunc(CEmployee *pObj)
{
    ASSERT(pObj);    //it can’t be a NULL
    ASSERT_KINDOF(CEmployee, pObj);
}
像前面一样,我们首先确认这个指针不是空的。然后我们检查这个对象指针的类型是不是CEmployee型。只有对于从CObject派生的类才能这样处理,并且需要添加runtime支持。幸运的是添加runtime支持真的微不足道。
    你必须已经声明这个对象至少是dynamic。解释一下,在MFC中你能够声明一个类包含runtime类信息。你可以通过在类声明中包含DECLARE_DYNAMIC(ClassName)宏和在执行处包含IMPLEMENT_DYNAMIC(ClassName,BaseClassName)来完成这一操作。
class CMyReallyTrivialClass : public CObject
{
    DECLARE_DYNAMIC(CMyReallyTrivialClass)
public:

    //  Various class members and functions…
};
and the implementation file
IMPLEMENT_DYNAMIC(CMyReallyTrivialClass,CObject);
.
.
.
// Other class functions…

    如果你只是想使用ASSERT_KINDOF宏,这两行已经足够了。现在,当你写程序时,你可以在任何地方使用ASSERT_KINDOF宏来检查一个传递给你的对象指针是否你要的类型。如果不是,你的程序将如前所述以一种受控的方式崩溃,并收到调试器给的一个ASSERT失败。
    如果你的对象已经包含DECLARE_DYNCREATE宏或者DECLARE_SERIAL宏,你就不需要使用DECLARE_DYNAMIC了,因为这些宏包含了ASSERT_KINDOF宏需要的runtime类信息。

结论
    以上阐述了如何用ASSERT捕获runtime错误并将你带到调试器中导致ASSERT错误的行。我们看到了如何追溯ASSERT失败原因的方法。沿着这个思路,我们学会了如何测试我们自己的代码中指向内存的指针的有效性;如何检查我们得到的对象指针是否是代码需要的。
    最近几年,我一直在我的代码中使用ASSERT作为runtime检查器,感觉受益匪浅。我很少遇到需要处理由空指针或者错误类型的对象指针所造成的程序崩溃。

作者Blog:http://blog.csdn.net/no_frost/
2007年03月14日

1.是不是一个父类写了一个virtual 函数,如果子类覆盖它的函数不加virtual ,也能实现多态?

virtual修饰符会被隐形继承的。

private 也被集成,只事派生类没有访问权限而已

virtual可加可不加

子类的空间里有父类的所有变量(static除外)

同一个函数只存在一个实体(inline除外)

子类覆盖它的函数不加virtual ,也能实现多态。

在子类的空间里,有父类的私有变量。私有变量不能直接访问。

————————————————————————–
2.输入一个字符串,将其逆序后输出。(使用C++,不建议用伪码)

#include <iostream>
using namespace std;

void main()
{
  char a[50];memset(a,0,sizeof(a));
  int i=0,j;
  char t;
  cin.getline(a,50,’\n’);
  for(i=0,j=strlen(a)-1;i<strlen(a)/2;i++,j–)
  {
   t=a[i];
      a[i]=a[j];
   a[j]=t;
  }
  cout<<a<<endl; 
}

//第二种

string str;
cin>>str;
str.replace;
cout<<str;

————————————————————————–
3.请简单描述Windows内存管理的方法。

内存管理是操作系统中的重要部分,两三句话恐怕谁也说不清楚吧~~
我先说个大概,希望能够抛砖引玉吧

当程序运行时需要从内存中读出这段程序的代码。代码的位置必须在物理内存中才能被运行,由于现在的操作系统中有非常多的程序运行着,内存中不能够完全放下,所以引出了虚拟内存的概念。把哪些不常用的程序片断就放入虚拟内存,当需要用到它的时候在load入主存(物理内存)中。这个就是内存管理所要做的事。内存管理还有另外一件事需要做:计算程序片段在主存中的物理位置,以便CPU调度。

内存管理有块式管理,页式管理,段式和段页式管理。现在常用段页式管理

块式管理:把主存分为一大块、一大块的,当所需的程序片断不在主存时就分配一块主存空间,把程 序片断load入主存,就算所需的程序片度只有几个字节也只能把这一块分配给它。这样会造成很大的浪费,平均浪费了50%的内存空间,但时易于管理。

页式管理:把主存分为一页一页的,每一页的空间要比一块一块的空间小很多,显然这种方法的空间利用率要比块式管理高很多。

段式管理:把主存分为一段一段的,每一段的空间又要比一页一页的空间小很多,这种方法在空间利用率上又比页式管理高很多,但是也有另外一个缺点。一个程序片断可能会被分为几十段,这样很多时间就会被浪费在计算每一段的物理地址上(计算机最耗时间的大家都知道是I/O吧)。

段页式管理:结合了段式管理和页式管理的优点。把主存分为若干页,每一页又分为若干段。好处就很明显,不用我多说了吧。

各种内存管理都有它自己的方法来计算出程序片断在主存中的物理地址,其实都很相似。

这只是一个大概而已,不足以说明内存管理的皮毛。无论哪一本操作系统书上都有详细的讲解

————————————————————————–
4.
#include "stdafx.h"
#define SQR(X) X*X

int main(int argc, char* argv[])
{
 int a = 10;
 int k = 2;
 int m = 1;

 a /= SQR(k+m)/SQR(k+m);
 printf("%d\n",a);

 return 0;
}
这道题目的结果是什么啊?

define 只是定义而已,在编择时只是简单代换X*X而已,并不经过算术法则的

a /= (k+m)*(k+m)/(k+m)*(k+m);
=>a /= (k+m)*1*(k+m);
=>a = a/9;
=>a = 1;

————————————————————————–
5.
const 符号常量;
(1)const char *p
(2)char const *p
(3)char * const p
说明上面三种描述的区别;

如果const位于星号的左侧,则const就是用来修饰指针所指向的变量,即指针指向为常量;
如果const位于星号的右侧,const就是修饰指针本身,即指针本身是常量。

(1)const char *p

一个指向char类型的const对象指针,p不是常量,我们可以修改p的值,使其指向不同的char,但是不能改变它指向非char对象,如:
const char *p;
char c1=’a';
char c2=’b';
p=&c1;//ok
p=&c2;//ok
*p=c1;//error

(2)char const *p
(3)char * const p

这两个好象是一样的,此时*p可以修改,而p不能修改。

(4)const char * const p
这种是地址及指向对象都不能修改。

————————————————————————–
6.下面是C语言中两种if语句判断方式。请问哪种写法更好?为什么?
 int n;
 if (n == 10) // 第一种判断方式
 if (10 == n) // 第二种判断方式

如果少了个=号,编译时就会报错,减少了出错的可能行,可以检测出是否少了=

————————————————————————–
7.下面的代码有什么问题?
void DoSomeThing(…)
{
 char* p;
 …
 p = malloc(1024);  // 分配1K的空间
 if (NULL == p)
  return;
 …
 p = realloc(p, 2048); // 空间不够,重新分配到2K
 if (NULL == p)
  return;
 …
}

A:
p = malloc(1024);     应该写成: p = (char *) malloc(1024);
        没有释放p的空间,造成内存泄漏。

————————————————————————–
8.下面的代码有什么问题?并请给出正确的写法。
void DoSomeThing(char* p)
{
 char str[16];
 int n;
 assert(NULL != p);
 sscanf(p, "%s%d", str, n);
 if (0 == strcmp(str, "something"))
 {
  …
 }
}

A:
sscanf(p, "%s%d", str, n);   这句该写成: sscanf(p, "%s%d", str, &n);

————————————————————————–
9.下面代码有什么错误?
Void test1()
{
 char string[10];
 char *str1="0123456789";
 strcpy(string, str1);
}

数组越界

————————————————————————–
10.下面代码有什么问题?
Void test2()
{
  char string[10], str1[10];
  for(i=0; i<10;i++)
  {
     str1[i] =’a';
  }
  strcpy(string, str1);
}

数组越界

————————————————————————–
11.下面代码有什么问题?
Void test3(char* str1)
{
  char string[10];
  if(strlen(str1)<=10)
  {
    strcpy(string, str1);
  }
}

==数组越界
==strcpy拷贝的结束标志是查找字符串中的\0 因此如果字符串中没有遇到\0的话 会一直复制,直到遇到\0,上面的123都因此产生越界的情况
 
建议使用 strncpy 和 memcpy

————————————————————————–
12.下面代码有什么问题?

#define MAX_SRM 256

DSN get_SRM_no()
{
  static int SRM_no; //是不是这里没赋初值?
  int I;
  for(I=0;I<MAX_SRM;I++,SRM_no++)
  {
    SRM_no %= MAX_SRM;
    if(MY_SRM.state==IDLE)
    {
      break;
    }
  }
  if(I>=MAX_SRM)
    return (NULL_SRM);
  else
    return SRM_no;
}

系统会初始化static int变量为0,但该值会一直保存,所谓的不可重入…

————————————————————————–
13.写出运行结果:
{// test1
    char str[] = "world"; cout << sizeof(str) << ": ";
    char *p    = str;     cout << sizeof(p) << ": ";
    char i     = 10;      cout << sizeof(i) << ": ";
    void *pp   = malloc(10);  cout << sizeof(p) << endl;
}

6:4:1:4

————————————————————————–
14.写出运行结果:
{// test2
    union V {
 struct X {
  unsigned char s1:2;
  unsigned char s2:3;
  unsigned char s3:3;
 } x;

 unsigned char c;
    } v;

    v.c = 100;
    printf("%d", v.x.s3);

}

3

————————————————————————–
15.用C++写个程序,如何判断一个操作系统是16位还是32位的?不能用sizeof()函数

A1:
16位的系统下,
int i = 65536;
cout << i; // 输出0;
int i = 65535;
cout << i; // 输出-1;

32位的系统下,
int i = 65536;
cout << i; // 输出65536;
int i = 65535;
cout << i; // 输出65535;

A2:

int a = ~0;
if( a>65536 )
{
    cout<<"32 bit"<<endl;
}
else
{
    cout<<"16 bit"<<endl;
}

————————————————————————–
16.C和C++有什么不同?

从机制上:c是面向过程的(但c也可以编写面向对象的程序);c++是面向对象的,提供了类。但是,
c++编写面向对象的程序比c容易

从适用的方向:c适合要求代码体积小的,效率高的场合,如嵌入式;c++适合更上层的,复杂的;  llinux核心大部分是c写的,因为它是系统软件,效率要求极高。

从名称上也可以看出,c++比c多了+,说明c++是c的超集;那为什么不叫c+而叫c++呢,是因为c++比
c来说扩充的东西太多了,所以就在c后面放上两个+;于是就成了c++

C语言是结构化编程语言,C++是面向对象编程语言。
C++侧重于对象而不是过程,侧重于类的设计而不是逻辑的设计。

————————————————————————–
17.在不用第三方参数的情况下,交换两个参数的值
#include <stdio.h>

void main()
{
        int i=60;
        int j=50;
        i=i+j;
        j=i-j;
        i=i-j;
        printf("i=%d\n",i);
        printf("j=%d\n",j);
}

方法二:
i^=j;
j^=i;
i^=j;

方法三:
// 用加减实现,而且不会溢出
a = a+b-(b=a)

————————————————————————–
18.有关位域的面试题(为什么输出的是一个奇怪的字符)

a.t = ‘b’;效果相当于 a.t= ‘b’ & 0xf;

‘b’ –> 01100010
‘b’ & 0xf –>>00000010
所以输出Ascii码为2的特殊字符

char t:4;就是4bit的字符变量,同样
unsigned short i:8;就是8bit的无符号短整形变量

————————————————————————–
19.int i=10, j=10, k=3; k*=i+j; k最后的值是?

60

————————————————————————–
20.进程间通信的方式有?

进程间通信的方式有 共享内存, 管道 ,Socket ,消息队列 , DDE等

————————————————————————–
21.
struct A
{
char t:4;
char k:4;
unsigned short i:8;
unsigned long m;
}
sizeof(A)=?(不考虑边界对齐)

7

struct CELL             // Declare CELL bit field
{
   unsigned character  : 8;  // 00000000 ????????
   unsigned foreground : 3;  // 00000??? 00000000
   unsigned intensity  : 1;  // 0000?000 00000000
   unsigned background : 3;  // 0???0000 00000000
   unsigned blink      : 1;  // ?0000000 00000000
} screen[25][80];       // Array of bit fields
二、位结构
    位结构是一种特殊的结构, 在需按位访问一个字节或字的多个位时, 位结构
比按位运算符更加方便。
    位结构定义的一般形式为:
     struct位结构名{
          数据类型 变量名: 整型常数;
          数据类型 变量名: 整型常数;
     } 位结构变量;
    其中: 数据类型必须是int(unsigned或signed)。 整型常数必须是非负的整
数, 范围是0~15, 表示二进制位的个数, 即表示有多少位。
    变量名是选择项, 可以不命名, 这样规定是为了排列需要。
    例如: 下面定义了一个位结构。
     struct{
          unsigned incon: 8;  /*incon占用低字节的0~7共8位*/
          unsigned txcolor: 4;/*txcolor占用高字节的0~3位共4位*/
          unsigned bgcolor: 3;/*bgcolor占用高字节的4~6位共3位*/
          unsigned blink: 1;  /*blink占用高字节的第7位*/
     }ch;
    位结构成员的访问与结构成员的访问相同。
    例如: 访问上例位结构中的bgcolor成员可写成:
      ch.bgcolor
 
    注意:
    1. 位结构中的成员可以定义为unsigned, 也可定义为signed,  但当成员长
度为1时, 会被认为是unsigned类型。因为单个位不可能具有符号。
    2. 位结构中的成员不能使用数组和指针, 但位结构变量可以是数组和指针,
如果是指针, 其成员访问方式同结构指针。
    3. 位结构总长度(位数), 是各个位成员定义的位数之和,  可以超过两个字
节。
    4. 位结构成员可以与其它结构成员一起使用。
    例如:
     struct info{
          char name[8];
          int age;
          struct addr address;
          float pay;
          unsigned state: 1;
          unsigned pay: 1;
          }workers;
    上例的结构定义了关于一个工人的信息。其中有两个位结构成员, 每个位结
构成员只有一位, 因此只占一个字节但保存了两个信息, 该字节中第一位表示工
人的状态, 第二位表示工资是否已发放。由此可见使用位结构可以节省存贮空间。

————————————————————————–
22.下面的函数实现在一个固定的数上加上一个数,有什么错误,改正
int add_n(int n)
{
  static int i=100;
  i+=n;
  return i;
}

答:
因为static使得i的值会保留上次的值。
去掉static就可了

————————————————————————–
23.下面的代码有什么问题?
class A
{
public:
  A() { p=this; }
  ~A() { if(p!=NULL) { delete p; p=NULL; } }

  A* p;
};

答:
会引起无限递归

————————————————————————–
24.
union a {
 int a_int1;
 double a_double;
 int a_int2;
};

typedef struct
{
 a a1;
 char y;
} b;

class c
{
 double c_double;
 b b1;
 a a2;

};

输出cout<<sizeof(c)<<endl;的结果?

答:
VC6环境下得出的结果是32

另:
我(sun)在VC6.0+win2k下做过试验:
short – 2
int-4
float-4
double-8
指针-4

sizeof(union),以结构里面size最大的为union的size

解析C语言中的sizeof

一、sizeof的概念 
  sizeof是C语言的一种单目操作符,如C语言的其他操作符++、–等。它并不是函数。sizeof操作符以字节形式给出了其操作数的存储大小。操作数可以是一个表达式或括在括号内的类型名。操作数的存储大小由操作数的类型决定。 

二、sizeof的使用方法 
  1、用于数据类型 

  sizeof使用形式:sizeof(type) 

  数据类型必须用括号括住。如sizeof(int)。 

  2、用于变量 

  sizeof使用形式:sizeof(var_name)或sizeof var_name 

  变量名可以不用括号括住。如sizeof (var_name),sizeof var_name等都是正确形式。带括号的用法更普遍,大多数程序员采用这种形式。 

  注意:sizeof操作符不能用于函数类型,不完全类型或位字段。不完全类型指具有未知存储大小的数据类型,如未知存储大小的数组类型、未知内容的结构或联合类型、void类型等。 

  如sizeof(max)若此时变量max定义为int max(),sizeof(char_v) 若此时char_v定义为char char_v [MAX]且MAX未知,sizeof(void)都不是正确形式。 

三、sizeof的结果 
  sizeof操作符的结果类型是size_t,它在头文件

中typedef为unsigned int类型。该类型保证能容纳实现所建立的最大对象的字节大小。 

  1、若操作数具有类型char、unsigned char或signed char,其结果等于1。 

  ANSI C正式规定字符类型为1字节。 

  2、int、unsigned int 、short int、unsigned short 、long int 、unsigned long 、float、double、long double类型的sizeof 在ANSI C中没有具体规定,大小依赖于实现,一般可能分别为2、2、2、2、4、4、4、8、10。 

  3、当操作数是指针时,sizeof依赖于编译器。例如Microsoft C/C++7.0中,near类指针字节数为2,far、huge类指针字节数为4。一般Unix的指针字节数为4。 

  4、当操作数具有数组类型时,其结果是数组的总字节数。 

  5、联合类型操作数的sizeof是其最大字节成员的字节数。结构类型操作数的sizeof是这种类型对象的总字节数,包括任何垫补在内。 

  让我们看如下结构: 

  struct {char b; double x;} a; 

  在某些机器上sizeof(a)=12,而一般sizeof(char)+ sizeof(double)=9。 

  这是因为编译器在考虑对齐问题时,在结构中插入空位以控制各成员对象的地址对齐。如double类型的结构成员x要放在被4整除的地址。 

  6、如果操作数是函数中的数组形参或函数类型的形参,sizeof给出其指针的大小。 

四、sizeof与其他操作符的关系 
  sizeof的优先级为2级,比/、%等3级运算符优先级高。它可以与其他操作符一起组成表达式。如i*sizeof(int);其中i为int类型变量。 

五、sizeof的主要用途 
  1、sizeof操作符的一个主要用途是与存储分配和I/O系统那样的例程进行通信。例如: 

  void *malloc(size_t size), 

  size_t fread(void * ptr,size_t size,size_t nmemb,FILE * stream)。 

  2、sizeof的另一个的主要用途是计算数组中元素的个数。例如: 

  void * memset(void * s,int c,sizeof(s))。 

六、建议 
  由于操作数的字节数在实现时可能出现变化,建议在涉及到操作数字节大小时用sizeof来代替常量计算。

=============================================================
本文主要包括二个部分,第一部分重点介绍在VC中,怎么样采用sizeof来求结构的大小,以及容易出现的问题,并给出解决问题的方法,第二部分总结出VC中sizeof的主要用法。

1、 sizeof应用在结构上的情况

请看下面的结构:

struct MyStruct

{

double dda1;

char dda;

int type

};

对结构MyStruct采用sizeof会出现什么结果呢?sizeof(MyStruct)为多少呢?也许你会这样求:

sizeof(MyStruct)=sizeof(double)+sizeof(char)+sizeof(int)=13

但是当在VC中测试上面结构的大小时,你会发现sizeof(MyStruct)为16。你知道为什么在VC中会得出这样一个结果吗?

其实,这是VC对变量存储的一个特殊处理。为了提高CPU的存储速度,VC对一些变量的起始地址做了"对齐"处理。在默认情况下,VC规定各成员变量存放的起始地址相对于结构的起始地址的偏移量必须为该变量的类型所占用的字节数的倍数。下面列出常用类型的对齐方式(vc6.0,32位系统)。

类型
对齐方式(变量存放的起始地址相对于结构的起始地址的偏移量)

Char
偏移量必须为sizeof(char)即1的倍数

int
偏移量必须为sizeof(int)即4的倍数

float
偏移量必须为sizeof(float)即4的倍数

double
偏移量必须为sizeof(double)即8的倍数

Short
偏移量必须为sizeof(short)即2的倍数

 

各成员变量在存放的时候根据在结构中出现的顺序依次申请空间,同时按照上面的对齐方式调整位置,空缺的字节VC会自动填充。同时VC为了确保结构的大小为结构的字节边界数(即该结构中占用最大空间的类型所占用的字节数)的倍数,所以在为最后一个成员变量申请空间后,还会根据需要自动填充空缺的字节。

下面用前面的例子来说明VC到底怎么样来存放结构的。

struct MyStruct

{

double dda1;

char dda;

int type

};

为上面的结构分配空间的时候,VC根据成员变量出现的顺序和对齐方式,先为第一个成员dda1分配空间,其起始地址跟结构的起始地址相同(刚好偏移量0刚好为sizeof(double)的倍数),该成员变量占用sizeof(double)=8个字节;接下来为第二个成员dda分配空间,这时下一个可以分配的地址对于结构的起始地址的偏移量为8,是sizeof(char)的倍数,所以把dda存放在偏移量为8的地方满足对齐方式,该成员变量占用sizeof(char)=1个字节;接下来为第三个成员type分配空间,这时下一个可以分配的地址对于结构的起始地址的偏移量为9,不是sizeof(int)=4的倍数,为了满足对齐方式对偏移量的约束问题,VC自动填充3个字节(这三个字节没有放什么东西),这时下一个可以分配的地址对于结构的起始地址的偏移量为12,刚好是sizeof(int)=4的倍数,所以把type存放在偏移量为12的地方,该成员变量占用sizeof(int)=4个字节;这时整个结构的成员变量已经都分配了空间,总的占用的空间大小为:8+1+3+4=16,刚好为结构的字节边界数(即结构中占用最大空间的类型所占用的字节数sizeof(double)=8)的倍数,所以没有空缺的字节需要填充。所以整个结构的大小为:sizeof(MyStruct)=8+1+3+4=16,其中有3个字节是VC自动填充的,没有放任何有意义的东西。

下面再举个例子,交换一下上面的MyStruct的成员变量的位置,使它变成下面的情况:

struct MyStruct

{

char dda;

double dda1;  

int type

};

这个结构占用的空间为多大呢?在VC6.0环境下,可以得到sizeof(MyStruc)为24。结合上面提到的分配空间的一些原则,分析下VC怎么样为上面的结构分配空间的。(简单说明)

struct MyStruct

{

  char dda;//偏移量为0,满足对齐方式,dda占用1个字节;

double dda1;//下一个可用的地址的偏移量为1,不是sizeof(double)=8

             //的倍数,需要补足7个字节才能使偏移量变为8(满足对齐

             //方式),因此VC自动填充7个字节,dda1存放在偏移量为8

             //的地址上,它占用8个字节。

int type;//下一个可用的地址的偏移量为16,是sizeof(int)=4的倍

           //数,满足int的对齐方式,所以不需要VC自动填充,type存

           //放在偏移量为16的地址上,它占用4个字节。

};//所有成员变量都分配了空间,空间总的大小为1+7+8+4=20,不是结构

   //的节边界数(即结构中占用最大空间的类型所占用的字节数sizeof

   //(double)=8)的倍数,所以需要填充4个字节,以满足结构的大小为

   //sizeof(double)=8的倍数。

 

所以该结构总的大小为:sizeof(MyStruc)为1+7+8+4+4=24。其中总的有7+4=11个字节是VC自动填充的,没有放任何有意义的东西。

 

VC对结构的存储的特殊处理确实提高CPU存储变量的速度,但是有时候也带来了一些麻烦,我们也屏蔽掉变量默认的对齐方式,自己可以设定变量的对齐方式。

VC中提供了#pragma pack(n)来设定变量以n字节对齐方式。n字节对齐就是说变量存放的起始地址的偏移量有两种情况:第一、如果n大于等于该变量所占用的字节数,那么偏移量必须满足默认的对齐方式,第二、如果n小于该变量的类型所占用的字节数,那么偏移量为n的倍数,不用满足默认的对齐方式。结构的总大小也有个约束条件,分下面两种情况:如果n大于所有成员变量类型所占用的字节数,那么结构的总大小必须为占用空间最大的变量占用的空间数的倍数;

否则必须为n的倍数。下面举例说明其用法。

#pragma pack(push) //保存对齐状态

#pragma pack(4)//设定为4字节对齐

struct test

{

  char m1;

  double m4;

  int  m3;

};

#pragma pack(pop)//恢复对齐状态

以上结构的大小为16,下面分析其存储情况,首先为m1分配空间,其偏移量为0,满足我们自己设定的对齐方式(4字节对齐),m1占用1个字节。接着开始为m4分配空间,这时其偏移量为1,需要补足3个字节,这样使偏移量满足为n=4的倍数(因为sizeof(double)大于n),m4占用8个字节。接着为m3分配空间,这时其偏移量为12,满足为4的倍数,m3占用4个字节。这时已经为所有成员变量分配了空间,共分配了16个字节,满足为n的倍数。如果把上面的#pragma pack(4)改为#pragma pack(16),那么我们可以得到结构的大小为24。(请读者自己分析)

2、 sizeof用法总结

在VC中,sizeof有着许多的用法,而且很容易引起一些错误。下面根据sizeof后面的参数对sizeof的用法做个总结。

A.  参数为数据类型或者为一般变量。例如sizeof(int),sizeof(long)等等。这种情况要注意的是不同系统系统或者不同编译器得到的结果可能是不同的。例如int类型在16位系统中占2个字节,在32位系统中占4个字节。

B.  参数为数组或指针。下面举例说明.

int a[50];  //sizeof(a)=4*50=200; 求数组所占的空间大小

int *a=new int[50];// sizeof(a)=4; a为一个指针,sizeof(a)是求指针

                   //的大小,在32位系统中,当然是占4个字节。

C.  参数为结构或类。Sizeof应用在类和结构的处理情况是相同的。但有两点需要注意,第一、结构或者类中的静态成员不对结构或者类的大小产生影响,因为静态变量的存储位置与结构或者类的实例地址无关。

第二、没有成员变量的结构或类的大小为1,因为必须保证结构或类的每一

个实例在内存中都有唯一的地址。

下面举例说明,

Class Test{int a;static double c};//sizeof(Test)=4.

Test *s;//sizeof(s)=4,s为一个指针。

Class test1{ };//sizeof(test1)=1;

D.  参数为其他。下面举例说明。

   int func(char s[5]);

   {

     cout<<sizeof(s);//这里将输出4,本来s为一个数组,但由于做为函

                     //数的参数在传递的时候系统处理为一个指针,所

                     //以sizeof(s)实际上为求指针的大小。

     return 1;

}

sizeof(func("1234"))=4//因为func的返回类型为int,所以相当于

                     //求sizeof(int).

 

以上为sizeof的基本用法,在实际的使用中要注意分析VC的分配变量的分配策略,这样的话可以避免一些错误。

————————————————————————–
25.i最后等于多少?
int i = 1;
int j = i++;
if((i>j++) && (i++ == j)) i+=j;

答:
i = 5

————————————————————————–
26.
unsigned short array[]={1,2,3,4,5,6,7};
int i = 3;
*(array + i) = ?

答:
4

————————————————————————–
27.
class A
{
  virtual void func1();
  void func2();
}
Class B: class A
{
  void func1(){cout << "fun1 in class B" << endl;}
  virtual void func2(){cout << "fun2 in class B" << endl;}
}
A, A中的func1和B中的func2都是虚函数.
B, A中的func1和B中的func2都不是虚函数.
C, A中的func2是虚函数.,B中的func1不是虚函数.
D, A中的func2不是虚函数,B中的func1是虚函数.

答:
A

————————————————————————–
28.
数据库:抽出部门,平均工资,要求按部门的字符串顺序排序,不能含有"human resource"部门,

employee结构如下:employee_id, employee_name, depart_id,depart_name,wage

答:
select depart_name, avg(wage)
from employee
where depart_name <> ‘human resource’
group by depart_name
order by depart_name

————————————————————————–
29.
给定如下SQL数据库:Test(num INT(4)) 请用一条SQL语句返回num的最小值,但不许使用统计功能,如MIN,MAX等

答:
select top 1 num
from Test
order by num desc

————————————————————————–
30.
输出下面程序结果。

#include <iostream.h>

class A
{
public:
 virtual void print(void)
 {
    cout<<"A::print()"<<endl;
 }
};
class B:public A
{
public:
 virtual void print(void)
 {
   cout<<"B::print()"<<endl;
 };
};
class C:public B
{
public:
 virtual void print(void)
 {
  cout<<"C::print()"<<endl;
 }
};
void print(A a)
{
   a.print();
}
void main(void)
{
   A a, *pa,*pb,*pc;
   B b;
   C c;
  
   pa=&a;
   pb=&b;
   pc=&c;
  
   a.print();
   b.print();
   c.print();
  
   pa->print();
   pb->print();
   pc->print();
  
   print(a);
   print(b);
   print(c);
}

A:
A::print()
B::print()
C::print()
A::print()
B::print()
C::print()
A::print()
A::print()
A::print()

————————————————————————–
31.
试编写函数判断计算机的字节存储顺序是开序(little endian)还是降序(bigendian)

答:
bool IsBigendian()
{
 unsigned short usData = 0×1122;
 unsigned char  *pucData = (unsigned char*)&usData;

 return (*pucData == 0×22);
}

————————————————————————–
32.简述Critical Section和Mutex的不同点

答:
对几种同步对象的总结
1.Critical Section
A.速度快
B.不能用于不同进程
C.不能进行资源统计(每次只可以有一个线程对共享资源进行存取)

2.Mutex
A.速度慢
B.可用于不同进程
C.不能进行资源统计

3.Semaphore
A.速度慢
B.可用于不同进程
C.可进行资源统计(可以让一个或超过一个线程对共享资源进行存取)

4.Event
A.速度慢
B.可用于不同进程
C.可进行资源统计

 

————————————————————————–
33.一个数据库中有两个表:
一张表为Customer,含字段ID,Name;
一张表为Order,含字段ID,CustomerID(连向Customer中ID的外键),Revenue;
写出求每个Customer的Revenue总和的SQL语句。

建表
create table customer
(
ID int primary key,Name char(10)
)

go

create table [order]
(
ID int primary key,CustomerID  int foreign key references customer(id) , Revenue float
)

go

–查询
select Customer.ID, sum( isnull([Order].Revenue,0) )
from customer full join [order]
on( [order].customerid=customer.id )
group by customer.id

————————————————————————–
34.请指出下列程序中的错误并且修改
void GetMemory(char *p){
  p=(char *)malloc(100);
}
void Test(void){
  char *str=NULL;
  GetMemory=(str);
  strcpy(str,"hello world");
  printf(str);
}

A:错误–参数的值改变后,不会传回
GetMemory并不能传递动态内存,Test函数中的 str一直都是 NULL。
strcpy(str, "hello world");将使程序崩溃。

修改如下:
char *GetMemory(){
  char *p=(char *)malloc(100);
  return p;
}
void Test(void){
  char *str=NULL;
  str=GetMemory(){
  strcpy(str,"hello world");
  printf(str);
}

方法二:void GetMemory2(char **p)变为二级指针.
void GetMemory2(char **p, int num)
{
 *p = (char *)malloc(sizeof(char) * num);
}

————————————————————————–
35.程序改错
class mml
{
  private:
    static unsigned int x;
  public:
    mml(){ x++; }
    mml(static unsigned int &) {x++;}
    ~mml{x–;}
  pulic:
    virtual mon() {} = 0;
    static unsigned int mmc(){return x;}
    ……                     
 
};
class nnl:public mml
{
  private:
    static unsigned int y;
  public:
    nnl(){ x++; }
    nnl(static unsigned int &) {x++;}
    ~nnl{x–;}
  public:
    virtual mon() {};
     static unsigned int nnc(){return y;}
    ……                  
};

代码片断:
mml* pp = new nnl;
……….
delete pp;

A:
基类的析构函数应该为虚函数
virtual ~mml{x–;}

————————————————————————–
36.101个硬币100真、1假,真假区别在于重量。请用无砝码天平称两次给出真币重还是假币重的结论。

答:
101个先取出2堆,
33,33
第一次称,如果不相等,说明有一堆重或轻
那么把重的那堆拿下来,再放另外35个中的33
如果相等,说明假的重,如果不相等,新放上去的还是重的话,说明假的轻(不可能新放上去的轻)

第一次称,如果相等的话,这66个肯定都是真的,从这66个中取出35个来,与剩下的没称过的35个比
下面就不用说了

方法二:
第3题也可以拿A(50),B(50)比一下,一样的话拿剩下的一个和真的比一下。
如果不一样,就拿其中的一堆。比如A(50)再分成两堆25比一下,一样的话就在
B(50)中,不一样就在A(50)中,结合第一次的结果就知道了。

————————————————————————–
37.static变量和static 函数各有什么特点?

答:
static变量:在程序运行期内一直有效,如果定义在函数外,则在编译单元内可见,如果在函数内,在在定义的block内可见;
static函数:在编译单元内可见;

————————————————————————–
38.用C 写一个输入的整数,倒着输出整数的函数,要求用递归方法 ;

答:
void fun( int a )
{
 printf( "%d", a%10 );
 a /= 10;
 if( a <=0 )return;

 fun( a );
}

————————————————————————–
39.写出程序结果:
void Func(char str[100])
{
  printf("%d\n", sizeof(str));
}

答:
4
分析:
指针长度

————————————————————————–
40.int id[sizeof(unsigned long)];
    这个对吗?为什么??

答:

这个 sizeof是编译时运算符,编译时就确定了
可以看成和机器有关的常量。

本文主要包括二个部分,第一部分重点介绍在VC中,怎么样采用sizeof来求结构的大小,以及容易出现的问题,并给出解决问题的方法,第二部分总结出VC中sizeof的主要用法。

1、 sizeof应用在结构上的情况

请看下面的结构:

struct MyStruct

{

double dda1;

char dda;

int type

};

对结构MyStruct采用sizeof会出现什么结果呢?sizeof(MyStruct)为多少呢?也许你会这样求:

sizeof(MyStruct)=sizeof(double)+sizeof(char)+sizeof(int)=13

但是当在VC中测试上面结构的大小时,你会发现sizeof(MyStruct)为16。你知道为什么在VC中会得出这样一个结果吗?

其实,这是VC对变量存储的一个特殊处理。为了提高CPU的存储速度,VC对一些变量的起始地址做了"对齐"处理。在默认情况下,VC规定各成员变量存放的起始地址相对于结构的起始地址的偏移量必须为该变量的类型所占用的字节数的倍数。下面列出常用类型的对齐方式(vc6.0,32位系统)。

类型
对齐方式(变量存放的起始地址相对于结构的起始地址的偏移量)

Char
偏移量必须为sizeof(char)即1的倍数

int
偏移量必须为sizeof(int)即4的倍数

float
偏移量必须为sizeof(float)即4的倍数

double
偏移量必须为sizeof(double)即8的倍数

Short
偏移量必须为sizeof(short)即2的倍数

 

各成员变量在存放的时候根据在结构中出现的顺序依次申请空间,同时按照上面的对齐方式调整位置,空缺的字节VC会自动填充。同时VC为了确保结构的大小为结构的字节边界数(即该结构中占用最大空间的类型所占用的字节数)的倍?

2007年03月10日

怎么去拥有 一道彩虹
怎么去拥抱 一夏天的风
天上的星星笑地上的人
总是不能懂不能觉得足够

如果我爱上 你的笑容
要怎么收藏 要怎么拥有
如果你快乐 不是为我
会不会放手其实才是拥有
当一阵风吹来风筝飞上天空
为了你而祈祷 而祝福而感动
终于你身影消失在 人海尽头
才发现 笑着哭 最痛

那天你和我 那个山丘
那样的唱着 那一年的歌
那样的回忆 那么足够
足够我天天都品尝着寂寞

当一阵风吹来风筝飞上天空
为了你而祈祷 而祝福而感动
终于你身影消失在 人海尽头
才发现 笑着哭 最痛
当一阵风吹来风筝飞上天空
为了你而祈祷 而祝福而感动
终于你身影消失在 人海尽头
才发现 笑着哭 最痛
如果我爱上 你的笑容
要怎么收藏 要怎么拥有
如果你快乐再不是为我
会不会放手其实才是拥有
知足的快乐叫我忍受心痛
知足的快乐叫我忍受心痛

 —————————————

时不时的,总会有深深的无力感,似乎连手指都没了弯曲的感觉.
如同傻子般地躺在床上发呆,害怕外面冰冷的空气..
时间老人阿,快点救我出去吧..pls..

2007年03月05日

    众多研究生前仆后继地投了论文后收到的论文集,一般都是放在宿舍占空间之用的,可惜现在枕头业太过发达,要不还可以拿来当枕头用,就在我们以为它们一无是处的时候,今天早上终于发现了它们的一大用途,而且是极其之方便好用.

   话说,来自山东的博士师兄每年春节从家回来都会带些核桃来分,去年就收获了几个,可惜不知道如何破开,一直放到那几个核桃自动消失. 今天第一天开工,照样收到了几个核桃,正愁不知怎么解决之时,小新同学很创新地拿起论文集放在核桃上,然后手握成锤,稍微用力一下,居然核桃就碎骨了…大家依样画瓢,顺利地解决了核桃问题…

   总的来说,一是要赞小新,此同学智商极高;二是要赞小波,此同学负责做的论文集质量确实符合ISO9001或9002质量标准.

2007年03月04日

元宵这个所谓的节日是没怎么存在我概念中的,
每年也总会在元宵前就提前回校,
可能跟春节太接近了吧,
在刚过了春节这么个隆重大型的节日后,
总会不知觉去忽略这个也是家人团圆的节日.

今晚小妹和BF过来,刚好小表弟过来我这拿电脑,
一行凑了五个人去五山的相聚美食轩吃饭,
大家非常漂亮地把点的五菜一汤扫得干干净净,
席上那个说话是说得菜都凉了..
表弟拿了电脑走后,
偶就带着妹妹他们两人在学校里走走,
阿…
今晚说话说得真开心,
我觉得我越来越帅了耶,
不过也可能是越来越 "天真浪漫" 了…
不管啦,
反正就是很开心很开心的元宵节..