asm, c, c++ are my all
-- Core In Computer
posts - 139,  comments - 123,  trackbacks - 0

转载自天蝎之巢:Windows编程中SetViewportOrg与SetWindowOrg的理解
                                        
最近突然又很有激情的开始看Jeff Prosise的那本"Programming Windows with MFC, 2 ed."。尽管是英文版的,但是感觉这本书上手比喉结的那本所谓的 深入浅出MFC 要容易理解的多。候同学给人一种故弄玄虚故作深沉的感觉,而Jeff Prosise的这本书才真正的称得上是深入浅出。

尽管如此,其中有关GDI绘图中的坐标映射部分还是有一个问题没有搞清楚,那就是SetWindowOrg和SetViewportOrg这两个函数到底应该如何理解。潘爱民翻译的那本VC内幕没有讲清楚;Jeff Prosise的这本书没有讲清楚;MSDN上的东西看的也是一头雾水;Charles Petzold的那本书还没有来得及看。因为这个问题,昨天晚上是带着遗憾的困惑入睡的。

总的来说,我对这两个函数的理解导致的结果是与实际程序运行的结果截然相反。依据MSDN上的解释,有一个很严重的问题没有阐述清楚,那就是:所谓的SetWindowOrg(x, y)函数,到底是表示set window origin to (x, y)还是set window origin as (x, y);to和as在执行的时候,其操作的效果是截然相反的。

set window origin to (x, y)表示将坐标原点设置到(x, y);即以(x, y)作为坐标原点,此时原点坐标不再为(0, 0);
set window origin as (x, y)表示将原来的原点(0, 0)的坐标改为(x, y);即将所有点的坐标增加(+x, +y);

现在我的理解是:应该是 set window origin to (x, y)。这种理解基于以下几个前提:
1. 所有绘图语句中给出的坐标,全部是逻辑坐标,即在 window 中的坐标(相对于viewport所表示的设备坐标而言);
2. 所有用户能看到的点,其设备坐标一定是位于(0, 0)和(1024, 768)范围内;(假设显示器为输出设备,采用MM_TEXT映射方式,且屏幕分辨率为1024*768);
3. 所谓“(0,0)就原点,原点的坐标一定就是(0,0)”这种理解,是错误的;
4. Viewport中的坐标表示设备坐标;Window中的坐标表示逻辑坐标;
5. 当在逻辑坐标中指定新的原点后,在执行映射时,设备坐标的原点一定要与逻辑坐标的新原点重合;反过来也是一样,即两个坐标系的原点一定要重合。

下面举例说明:(MM_TEXT映射模式)

(1)
CRect rect(0, 0, 200, 200);
dc.rectangle(rect);
上面的语句在屏幕的最左上角绘制一个正方形;(因为此时逻辑坐标与设备坐标没有偏移)

(2)
dc.SetViewportOrg(100, 100);
CRect rect(0, 0, 200, 200);
dc.rectangle(rect);
将设备坐标的原点设置到(100, 100);即设备坐标的原点不在(0, 0)处,而是在(100, 100)处;此时若执行映射的话,逻辑坐标的原点(0, 0)需要与设备坐标的原点(100, 100)重合(参考前提5);那么此时绘制的矩形(0, 0, 200, 200)的坐标(为逻辑坐标,参考前提1)在设备坐标中就会映射为(100, 100, 300, 300),最终我们在显示器上看到的会是一个向右下方偏移(100, 100)的一个边长为200的正方形(用户看到的点是在设备坐标中的,参考前提2)

(3)
dc.SetWindowOrg(100, 100);
CRect rect(0, 0, 200, 200);
dc.rectangle(rect);
将逻辑坐标的原点设置到(100, 100);即逻辑坐标的原点不在(0, 0)处,而是在(100, 100)处;此时若执行映射的话,设备坐标的原点(0, 0)需要与逻辑坐标的原点(100, 100)重合(参考前提5);那么此时绘制的矩形(0, 0, 200, 200)的坐标(为逻辑坐标,参考前提1)在设备坐标中就会映射为(-100, -100, 100, 100),最终我们在显示器上看到的会是一个只有1/4个大小的矩形的一部分(事实上相当于向左上方偏移(100, 100)的一个边长为200的正方形。注意:用户看到的点是在设备坐标中的,参考前提2)

posted @ 2006-07-11 04:11 Jerry Cat 阅读(352) | 评论 (0)编辑 收藏
替意大利高兴, 为法国队惋惜!
posted @ 2006-07-10 05:38 Jerry Cat 阅读(405) | 评论 (4)编辑 收藏
/********************************************\
|    欢迎转载, 但请保留作者姓名和原文链接, 祝您进步并共勉!     |
\********************************************/


读VC++内幕之体悟 - 05

作者: Jerry Cat
时间: 2006/07/09
链接: http://www.cppblog.com/jerysun0818/archive/2006/07/09/9612.html


5.   ActiveX控件不像普通控件那样,发送以WM_打头的通知消息给它的包容器,而是“激发事件”。事件有一个符号化的名字及一组任意次序的参数,它实际上是有控件调用的包容器函数。对于客户类来说,事件与控件的通知消息是一样的。
posted @ 2006-07-09 19:59 Jerry Cat 阅读(410) | 评论 (0)编辑 收藏

/********************************************\
|    欢迎转载, 但请保留作者姓名和原文链接, 祝您进步并共勉!     |
\********************************************/


美国人挂在嘴边的句子

作者: Jerry Cat
时间: 2006/07/09
链接:
http://www.cppblog.com/jerysun0818/archive/2006/07/09/9611.html

1-----You can't argue with success

Though you may tell someone they are doing something in a wrong way, you have to stop criticizing them if their method works.


2-----Nothing succeeds like success

Like money in a savings account, success seems to compound itself. A person who has a small success expects it to be followed by a bigger one.


3-----The end justifies the means

It does not matter how you succeed. Any method is all right if it works for you. This proverb is not always accepted. Often one hears the opposite, " the end doesn't justifies the means."


4-----If you can't beat them, join them

If you cannot compete successfully with a person or a group, stop competing and go join them. Then you can share in their success.


5-----Always a day late and a dollar short

A criticism of a person who never succeeds. The failures may not be drastic but the pattern of small failures is annoying to others, especially in two areas that Americans value as highly as time and money.


6-----One thing at a time

Concentration leads to success. The person who tires to do too many things at once may fail at all of them.


7-----We'll cross that bridge when we come to it

We will not discuss or worry about a future problem. If and when the problem becomes urgent, we will deal with it.


8-----Don't put the cart before the hourse

Do things in a sensible order. For example, do something to impress your boss before you ask for a raise in pay. Don't ask for the raise first.


9-----All's fair in love and war

Do not trust a rival or an enemy at all. His or her desire to succeed will overrule everything else. Such a people may lie, cheat, attack or do many other things far more terrible than he or she would normally do.


10-----When in Rome do as the romans do

Flexibility leads to success in unfamiliar circumstances. People may changes their normal way of doing things in order to fit in better with those they are visiting.


11------Easy does it

Some things require gentleness for success. One should not push too hard. Force may cause damage

12-----The bigger they are, the harder they fall

Do not be discouraged by the size of your problem or the fame of your competitor. (the saying is traced to a boxer preparing to fight an opponent much larger than he was.)


13-----All is well that ends well

If we can come to a successful conclusion, let us forget about the pain and mistakes along the way.


14-----Go for it

Go ahead and try to achieve your goal. Don't worry about failing. Similar to this proverb--God provides food to every bird, but he won't cast to its nest, you got to earn it.


15-----Every little bit helps

If someone apologizes for giving only a small gift, the recipient may encourage the giver by quoting this proverb. This is especially true if there is a huge job to do or a huge amount of money to be raised from many people.


16-----Look before you leap

Don't jump into a situation carelessly. You may land in difficulty.


17-----All that glitters is not gold

Do not be fooled by worthless things that seem valuable or look attractive.

"Fool's gold " is the popular name for a kind of stone that glitters like gold but contains no gold at all.


18------Curiosity killed the cat

Do not ask too many questions or become too curious about things. You may get yourself into trouble like a cat that does not see the danger in a new situation.


19-----Don't put all your eggs in one basket

Do not risk everything in one place or on one project. Divide your sources that one failure will not ruin you. Similar to this proverb---Do not use both feet to test the depth of the river.


20-----Don't bite off more than you can chew

Do not attempt something too large for you to handle.


21-----Too good to be ture

This is often used to warn about advertising. An offer looks good but turns out to be misleading.


22-----Flattery will get you nowhere

If flattery (insincere praise) is recognized, it will not succeed. One sometimes hears the opposite, Flattery will get you everywhere.


23-----There is no such thing as a free lunch

If someone you do not know offers you a free lunch or other gift, watch out. The gift may be a method of getting something from you.


24------Pride goes before a fall

Do not be over-confident and careless. Your circumstances may change quickly and the emptiness of your bragging will be exposed.


25------Better safe than sorry

It is better not to take a risk than to take a risk foolishly.


26-----Winning isn't everything

One may enjoy the process of playing a game whether one wins or not. This traditional proverb is now often heard in the opposite form, Winning isn't everything. It's the only thing!


27------Time will tell

Wait and see how something will work out. Don't trust a person or thing too much right now.


28-----The burned child shuns fire

Some of life's lessons are learned the hard way. The person who has had to pay for a mistake will be careful not to make that mistake again.


29-----There are other fish in the sea

There are opportunities! For example, this may be used to encourage someone who has just broken off a relationship with a sweetheart.


30-----Don't count your chickens before they are hatched

Do not become too confident of success before you can see that progress is happening.


31-----Rome wasn't built in a day

Do not be discouraged if your goal still seems far away. On a big project, success takes time!


32-----There is more here than meets the eye

Be careful. People are hiding something in order to protect themselves or take advantage of you.


33-----The customer is always right

Businesses instruct their clerks not to do anything that might threaten a customer's self-esteem, no matter how unreasonable the customer is. Any complaint of any customer must be carefully and politely heard by any employee. The customer must not be made to feel ignorant.


34-----Be true to yourself

Do not compromise yourself or your beliefs in order to please other people or fit in with a system. Know who you are. Let other people know what you stand for. Do not give in to pressure to conform or to do things you do not agree with.


35-----Once bitten, twice shy

This may be used to explain the behavior of a person who is overly cautious about something. The wise person makes mistakes but does not usually make the same mistake twice.


36-----It isn't over till the fat lady sings

I refuse to admit defeat yet. Though right now it looks like I may fall, there is still time for things to change. (The "fat lady" is an insulting reference to an opera soloist, opera often end with a female solo.)


37-----To each his own

Each individual should be allowed to have his or her own preferences. people will naturally choose different activities, goals, life-s, etc.


38-----Looking out for number one

Looking out for one's own personal welfare more than anything else. This is sometimes used to criticize a person who has abused or taken advantage of someone else, "All he was doing was looking out for number one." Or it may be used to defend himself or herself, "There is nothing wrong with what I did. I was just looking out for number one."


39-----When the going gets tough, the tough get going

When situation is difficult, only the determined people can handle it. They don't give up!


40-----Times flies when you are having fun

A day seems shot when it is full of enjoyable things but it seems like an eternity if one is idle or stuck with a boring job.


41-----If it feels good, do it

Live according to your desires at the moment. Forget about rules, regulations or consequences. Just have fun.


42-----Live and let live

Do not be judgmental. Do not try to control or punish other people.

You live as you like and let others live as they like.

43-----Variety is the spice of life

Variety is what makes life pleasureable. Boredom is seen as a threat and monotony is the surest route to boredom.

44------Money talks

Wealth has influence. People who make big contributions to political candidates are "talking" to the candidates and expecting them to listen.

45-----All work and no play makes Jack a dull boy

This is used to criticize someone who takes work too seriously. It affirms that play is as an essential part of human life.


46-----The more the merrier

This is a way of welcoming someone to participate. It means, the bigger the group, the bigger the party.


47------A bird in the hand is worth two in the bush

A thing you already have is worth twice as much as a thing you might get in the future.


48-----You can't have your cake and eat it too

Make up your mind. Sometimes one must choose between two very desirable things, giving up one thing in order to enjoy the other.


49-----There is more than one way to skin a cat

Any of several methods may bring about the desired result. Each person may choose the method that best suits her. If one method does not work, choose a different one and try again.


50-----One man's meat is another man's poison

Since the same thing may affect different people in different ways, each person must choose the things that will work in his or her particular case. 

51-----Love finds a way

Love is considered one of the most powerful and determined forces in the world. Two people in love will "find a way" to get together.


52-----Absence makes the heart grow fonder

When lovers are separated, they may think about each other constantly. their love may deepen.


53-----Out of sight, out of mind

This is said of someone not considered important or worthy of loyalty. One forgets about that person as soon as he or she is out of sight.


54------Love makes the world go around

Love is the driving force in all of life. Love makes life worth living. If you understand love,you understand everything about life.


55-----Marry in haste and repent at leisure

Do not rush into any long-term commitment. In the past this meant, "take your time before you commit yourself to a marriage partner." Now it means, "Do not commit yourself to anyone you will be sorry." or it may mean, "Live with a person for a while before marrying him or her." It may also apply to any long-term partnership, such as a joint business venture.


56------Talk is cheap

Talking is not doing, It is easy to talk about a plan, but this gets little respect untill one takes a risk and puts the plan into action.


57-----Love is blind

When people are in love, they do not see each other's faults.


58-----Time is money

Time can be converted to money, that is, wages are often paid per hour of work. Managers want employees to do things quickly because "time is money." If employees waste time, the company loses money.


59-----If you're so smart, why ain't you rich

This question implies that intelligence, like time, can be converted into money. It is used to cut down an ordinary person (not a rich one) who has expressed an opinion as if it is the final word on the subject.


60-----Beggars can't be choosers

Beggars have to accept whatever they get. A poor person has very few choices in life. This harsh reply may be used if people complain about the size or quality of a gift.


61-----The love of money is the root of all evil

Greed will lead a person into many other evils such as cheating, oppression and violence. (one also hears, money is the root of all evil, which places the blame more on money than on greed.)


62-----A fool and his money are soon parted

Folly will always show up in the way a fool handles money. Wise people are the ones smart enough to guard money once they have it.


63-----It isn't whether you win or lose, it's how you play the game

Playing well and fairly is more important than succeeding. This saying is sometimes used to console someone who has lost a game. The ideas is that in spite of losing, one may still feel like a success if one has played as well as possible.


64-----Money can't buy happiness

There are some things money just can't buy. This reminds people that money is not an ultimate value although it often is treated as one. The saying may be used as a comment when a wealthy but lonely and wretched person commits suicide.


65-----Nice guys finish last

Success is valued more highly than kindness and politeness. If unkindness and impoliteness contribute to one's success, they are sometimes excused as "toughness" or "what it takes." This is more often applied to men than woman.


66-----The one who dies with the most toys wins

This recent, cynical saying makes fun of three common American desires-- competing, accumulating property, and having fun.


67-----Just do it

This proverb is actually a recently invented advertising slogan for the Nike Shoe company. It may also be the best three-word summary of American cultural values. It means, "quit being indecisive, Don't bother consulting a lot of people. Don't waste much times on planning. Just do it and do it now.


68-----You only go around once in life

Enjoy life, do what you want to do, experience everything you can.


69-----Put your money where your mouth is

Get serious about what you are saying. When you have spoken in favor of something, prove that you mean it by risking some money on it in a bet or an investment.


70-----The best defense is a good offense

Be pro-active and goal-oriented, not timid or conservative. Aim to conquer, not merely to protect yourself.


71-----The road to hell is paved with good intentions

Like talking, intending is not doing. Actions matter far more than intentions. Actions determine where a person ends up.


72-----Never put off till tomorrow what you can do today

Doing is better than waiting. If you wait, you might lose your opportunity


73-----Action speak louder than words

To know people's hearts, pay more attention to what they do than what they say.


74-----Idle hands are the devil's workshop

When people have nothing constructive to do, they get into mischief. The child who is bored may pick up a crayon and color on the wall, something that would not happen if the child were happily occupied in some other activity.


75-----You've got to take the bull by the horns

Grab directly and fearlessly for the toughnest part of a problem. Don't look for an easy way out.


76-----Money doesn't grow on trees

You have to work for things. Success does not come on its own.


77-----Easy come, easy go

If you have received something without working for it, it may soon be gone. You will not be as careful with it as you will be with something you earned.


78-----Too many cooks spoil the broth

Individual action or action by the smallest group possible is better than consulting a lot of people. Too much consultation will waste time and create problems.


79-----Stand on your own two feet

Grow up; act like an adult. Don't ask me to do something for you. This may be said to a young or immature person who depends too much on others. It is like a cow kicking a grown calf that wants to suckle.


80------If you want something done right, do it yourself

This discourages people from trusting anyone except themselves. It maybe said to someone who ask another person to do a job for him/her and then complains about it was done.


81------Necessity is the mother of invention

When a person really needs something, he or she figures out some new way to get it. This creative initiative to change one's situation is considered much better than giving up and accepting things as they are.


82------First come, first served.

This saying is used when there is a limited supply of something such as tickets to an event or food at a picnic. The idea is that no matter what your status, if you want some of what is being given away or sold, you must present yourself in person and in good time.


83-----No pain no gain

one must put forth an effort in order to succeed. This saying comes from physical fitness instructors. They say that if you do not exercise hard enough to make your muscles hurt, the exercise is not doing you much good.


84-----Give him an inch and he'll take a mile

Be careful of presumptuous people who take more initiative than they should. If you do someone a small favor or delegate a little permission or a little power, he or she may take advantage of you.


85-----If it isn't broke, don't fix it

Do not bother trying to improve something if it is already working satisfactorily. That is a waste of time and you run the risk of breaking the thing while you are trying to improve it.


86-----There is no harm in trying

A person expects to be respected for making an effort even if it does not succeed.


87-----The cure is worse than the disease

While trying to solve one problem, we create an even bigger problem. We would have been better off if we had done nothing.


88-----Count to ten before you lose your temper

Do not instantly let your feelings control your actions. Slow down. Think before you react.


89-----All things come to him who waits

Sometimes patience is better than initiative.


90-----There is many a slip between the cup and the lip

This refers to a plan that has gone wrong. When one is drinking from a cup, one intends to get all the drink into the mouth, but this does not always happen. The plan is good but it can still fail.


91-----Boys will be boys

People will act according to their nature, including some mischief. This is sometimes used to describe irresponsible but not too seriously wrong behavior by men. In other words, grown men will sometimes act like little boys.


92------One bad apple can spoil the whole barrel

Do not associate with bad people. They may spoil you as a rotting apple spoils the apples next to it in the barrel.


93-----Better the devil you know than the devil you don't

People are generally not trustworthy. It is therefore better to deal with a familiar person or situation than an unknown one. That way you know what to watch out for and you can protect yourself better.

94-----Nobody is perfect

Everyone has shortcomings. This is used as an excuse for a minor Mistake that has been made.


95------The grass is always greener on the other side of the fence

People are never satisfied with what they have. They always want what someone else has.


96-----A man is only as old as he feels

A person's energy level is more important than age.


97-----A man's home is his castle

At home a man is like a king, completely free to do as he wishes.


98-----Clothes make the man

The way a man dresses will affect the way he sees himself and the way other people see him. The implication is that if you want to succeed, dress for success.


99-----Two heads are better than one

Two people are more likely to succeed than one working or thinking alone. It is better to consult than to act alone.


100-----Beauty is only skin deep

One should admire a person, particularly a woman, for her deep, inner character and not simply for her superficial beauty.


101-----Many hands make light work

Cooperation makes a job much easier.


102-----There is safety in numbers

Do not take large risks all by yourself. Do not walk alone on a dangerous street at night.


103-----Charity begins at home

One should be kind to close relatives before doing good to the community in general.


104-----There is no place like home

Home is the best place in the world. The most relaxing and enjoyable place.


105-----Silence is consent

Do not stay silent when you see a problem or an injustice. Speak out against it. Say, "Enough is enough." or people will think you do not mind the situation.


106-----What goes around comes around

What you do to others, especially if it is bad, will eventually be done to you. As you seek your own success, do not treat other people badly. They may take revenge and spoil your success.


107-----Honesty is the best policy

When one is tempted to cheat, this proverb serves as a reminder of the importance of good character. Honesty brings trust and trust leads to success.


108-----If the shoe fits, wear it

If an accusation is true, accept the blame. This saying can also mean, " if a suitable opportunity comes to you, take it!"


109-----You can lead a horse to water, but you can't make him drink

Even when given an opportunity, some people will not use it. In that case the blame is all on him.


110-----You made the bed, you lie in it

You created a certain situation so you are now responsible to take the consequences.


111-----The pot calling the kettle black

Since the pot and the kettle are equally black from the cooking fire, the pot has not right to criticize the kettle. This might be used if someone known to be a gossip criticizes someone else for gossiping.


112-----Don't get mad, get even

When someone treats you badly, do not just get angry, express your anger in action.


113-----Get a life

Do not be so unreasonably critical about tiny things. Find something better to do with your time.


114-----My country, right or wrong

I am absolutely loyal to my country whether or not I agree with its policy in a certain area.


115------There are two sides to everything

Never assume that all the blame for a conflict lies on one side, especially if you have heard only one side of the story.


116-----Forgive and forget

Conflicts should be resolved and ended, not left alone to cause years of regret, bitterness and pain.


117------Business and pleasure don't mix

When you work, work. When you play, play. It is inefficient and therefore unwise to try to mix the two.


118-----Let a sleeping dog lie

Do not meddle in something that will cause you no trouble if you leave it alone. If you wake up the "dog," it may bite you.


119------No man can serve two masters

Divided loyalty will break down sooner or later.


120-----Make it short and sweet

Speak briefly and to the point. We don't have time for the details


121-----What will be will be

Some things cannot be changed or avoided.


122-----A friend in need is a friend indeed

My true friend is the one who show loyalty to me by helping me when I am in need.


123-----People who live in glass house should not throw stones

Do not attact anyone if you have no way to defend yourself when they attact you in the same way.

124-----Opposites attract

As positive and negative magnets attract each other, so people of very different types attract each other. For example, a quiet woman marries a very outgoing man. These differences have a mixed effect on the couple, partly making them interested in each other but also leading to miscommunication and conflict.


125-----The early bird catches the worm

Punctuality is important. If you want to succeed, arrive early, like the bird that hunts worms at dawn before they go into hiding for the day.


126-----Blood is thicker than water

Blood relationship is stronger than voluntarily chosen friendship. Brothers will stick up for each other against their own friends if they have to. This proverb is not quoted much anymore because kinship is not as highly valued as it used to be.


127-----You can't teach an old dog new tricks

Once habits are learned, it is very hard to change them.


128-----To err is human

It is normal for humans to make mistakes and it is godly (or God-like) to forgive them.


129-----Haste makes waste

Through acting quickly is generally a good thing, acting too quickly may cause troulbe. This proverb is used when someone has done a job carelessly and wrongly. For example, a carpenter in a hurry may cut a board too short and have to throw it away.


130-----Make hay while the sun shines

If you do not seize the opportunity, rain may come and spoil the hay before you get into the barn.


131-----If you can't stand the heat, get out of the kitchen

Withdraw from an activity if you don't like the conflict and criticism it brings. Let other people do it without you.


132-----Everyone puts their pants on one leg at a time

This is to tell us that we are all equal.


133-----Life is a pie

It's dished out in large and small pieces and when's gone, it's gone. If we ask for more than our share, we're just begging to be disappointed.


134-----Making every minute count

Doing something productive all the time, not letting any time "slip away."

135-----A pen is mightier than the sword

A conflict maybe resolved more deeply and effectively by writing the truth than by resorting to violence.


136-----A new broom sweeps clean

A new person in power will change many things and improve the situation. change is better than leaving things as they are.


137-----Tomorrow is another day (or, Tomorrow is a new day.)

No matter how bad things are right now, a person may hope for better prospects in the morning. New opportunities will come.


138-----Opportunity only knocks once

Opportunity is like an unexpected stranger passing by. It knocks on someone's door. If the person fails to answer the door, opportunity goes away and knocks on someone else's door. It does not return to the same person.


139-----Business is business

Do business with strangers as if they were brothers and with brothers as if they were strangers.


140-----History repeats itself

There are patterns in history. Nations rise and fall for similar reasons. Nations do not change their ways or learn from the mistakes of others. They repeat them.


141-----People are people

Their human nature is predictable. They respond to stimulus and incentives.


142-----Keep your friends close, keep your enemies closer

A man without enemy is a man without quality. Think not? Even Jesus Christ had many, many enemies.


143-----Better late than never

Though being on time is better than being late, doing something late is better than giving up or doing nothing.


144-----Punish one, teach a hundred

People problems sometimes must be dealt with harshly. When you make an example of someone, make sure that everyone knows what the lesson is.


145-----Attitude is everything

A pessimist sees a glass half-empty, An optimist sees it half-full.


146-----Like father, like son

A son will be like his father. This may be quoted whenever the son has done something that reminds people of the father. Whether it is good or bad.


147-----When the cat's away the mice will play

People will take advantage of a situation if they can. Employees will get lazy if the supervisor is not keeping an eye on them. A teenage son or daughter might hold a wild party at home during a weekend when the parents have gone out of town.


148-----Praise when praise is due (sometimes even when it isn't)

Do not criticise beyond necessity and seldom in public. And always precede criticism with a few words of praise.


149-----Turnabout is fair play

If a person is taking advantage of someone else, the situation may change. The one on top may end up on the bottom. Then the one who has turned the tables will say, "I am only doing to you what you did to me.


150-----Here today, gone tomorrow

Things may change quickly. This is said as a criticism of a person who changes quickly for no good reason. It may also be said of a thing or situation which does not last. Change is not good when it indicates unreliability.

posted @ 2006-07-09 19:51 Jerry Cat 阅读(1085) | 评论 (1)编辑 收藏

C/C+语言struct深层探索

出处:PConline

1. struct的巨大作用
  面对一个人的大型C/C++程序时,只看其对struct的使用情况我们就可以对其编写者的编程经验进行评估。因为一个大型的C/C++程序,势必要涉及一些(甚至大量)进行数据组合的结构体,这些结构体可以将原本意义属于一个整体的数据组合在一起。从某种程度上来说,会不会用struct,怎样用struct是区别一个开发人员是否具备丰富开发经历的标志。

  在网络协议、通信控制、嵌入式系统的C/C++编程中,我们经常要传送的不是简单的字节流(char型数组),而是多种数据组合起来的一个整体,其表现形式是一个结构体。

  经验不足的开发人员往往将所有需要传送的内容依顺序保存在char型数组中,通过指针偏移的方法传送网络报文等信息。这样做编程复杂,易出错,而且一旦控制方式及通信协议有所变化,程序就要进行非常细致的修改。

  一个有经验的开发者则灵活运用结构体,举一个例子,假设网络或控制协议中需要传送三种报文,其格式分别为packetA、packetB、packetC:

struct structA
{
int a;
char b;
};

struct structB
{
char a;
short b;
};

struct structC
{
int a;
char b;
float c;
}
  优秀的程序设计者这样设计传送的报文:

struct CommuPacket
{
int iPacketType;  //报文类型标志
union      //每次传送的是三种报文中的一种,使用union
{
  struct structA packetA;
  struct structB packetB;
  struct structC packetC;
}
};
  在进行报文传送时,直接传送struct CommuPacket一个整体。

  假设发送函数的原形如下:

// pSendData:发送字节流的首地址,iLen:要发送的长度
Send(char * pSendData, unsigned int  iLen);
发送方可以直接进行如下调用发送struct CommuPacket的一个实例sendCommuPacket:
Send( (char *)&sendCommuPacket , sizeof(CommuPacket) );
假设接收函数的原形如下:
// pRecvData:发送字节流的首地址,iLen:要接收的长度
//返回值:实际接收到的字节数
unsigned int Recv(char * pRecvData, unsigned int  iLen);
  接收方可以直接进行如下调用将接收到的数据保存在struct CommuPacket的一个实例recvCommuPacket中:

Recv( (char *)&recvCommuPacket , sizeof(CommuPacket) );
  接着判断报文类型进行相应处理:

switch(recvCommuPacket. iPacketType)
{
    case PACKET_A:
    …    //A类报文处理
    break;
    case PACKET_B:
    …   //B类报文处理
    break;
    case PACKET_C:
    …   //C类报文处理
    break;
}
  以上程序中最值得注意的是

Send( (char *)&sendCommuPacket , sizeof(CommuPacket) );
Recv( (char *)&recvCommuPacket , sizeof(CommuPacket) );
  中的强制类型转换:(char *)&sendCommuPacket、(char *)&recvCommuPacket,先取地址,再转化为char型指针,这样就可以直接利用处理字节流的函数。

  利用这种强制类型转化,我们还可以方便程序的编写,例如要对sendCommuPacket所处内存初始化为0,可以这样调用标准库函数memset():

memset((char *)&sendCommuPacket,0, sizeof(CommuPacket));

2. struct的成员对齐
  Intel、微软等公司曾经出过一道类似的面试题:
1. #include <iostream.h>
2. #pragma pack(8)
3. struct example1
4. {
5. short a;
6. long b;
7. };
8. struct example2
9. {
10. char c;
11. example1 struct1;
12. short e;   
13. };
14. #pragma pack()
15. int main(int argc, char* argv[])
16. {
17. example2 struct2;
18. cout << sizeof(example1) << endl;
19. cout << sizeof(example2) << endl;
20. cout << (unsigned int)(&struct2.struct1) - (unsigned int)(&struct2) << endl;
21. return 0;
22. }
  问程序的输入结果是什么?
  答案是:
8
16
4
  不明白?还是不明白?下面一一道来:
2.1 自然对界
  struct是一种复合数据类型,其构成元素既可以是基本数据类型(如int、long、float等)的变量,也可以是一些复合数据类型(如array、struct、union等)的数据单元。对于结构体,编译器会自动进行成员变量的对齐,以提高运算效率。缺省情况下,编译器为结构体的每个成员按其自然对界(natural alignment)条件分配空间。各个成员按照它们被声明的顺序在内存中顺序存储,第一个成员的地址和整个结构的地址相同。
  自然对界(natural alignment)即默认对齐方式,是指按结构体的成员中size最大的成员对齐。
  例如:
struct naturalalign
{
char a;
short b;
char c;
};
  在上述结构体中,size最大的是short,其长度为2字节,因而结构体中的char成员a、c都以2为单位对齐,sizeof(naturalalign)的结果等于6;
  如果改为:
struct naturalalign
{
char a;
int b;
char c;
};
  其结果显然为12。

2.2指定对界
  一般地,可以通过下面的方法来改变缺省的对界条件:
  · 使用伪指令#pragma pack (n),编译器将按照n个字节对齐;
  · 使用伪指令#pragma pack (),取消自定义字节对齐方式。
  注意:如果#pragma pack (n)中指定的n大于结构体中最大成员的size,则其不起作用,结构体仍然按照size最大的成员进行对界。
  例如:
#pragma pack (n)
struct naturalalign
{
char a;
int b;
char c;
};
#pragma pack ()
  当n为4、8、16时,其对齐方式均一样,sizeof(naturalalign)的结果都等于12。而当n为2时,其发挥了作用,使得sizeof(naturalalign)的结果为8。
  在VC++ 6.0编译器中,我们可以指定其对界方式,其操作方式为依次选择projetct > setting > C/C++菜单,在struct member alignment中指定你要的对界方式。
  另外,通过__attribute((aligned (n)))也可以让所作用的结构体成员对齐在n字节边界上,但是它较少被使用,因而不作详细讲解。

2.3 面试题的解答
  至此,我们可以对Intel、微软的面试题进行全面的解答。
  程序中第2行#pragma pack (8)虽然指定了对界为8,但是由于struct example1中的成员最大size为4(long变量size为4),故struct example1仍然按4字节对界,struct example1的size为8,即第18行的输出结果;
  struct example2中包含了struct example1,其本身包含的简单数据成员的最大size为2(short变量e),但是因为其包含了struct example1,而struct example1中的最大成员size为4,struct example2也应以4对界,#pragma pack (8)中指定的对界对struct example2也不起作用,故19行的输出结果为16;
  由于struct example2中的成员以4为单位对界,故其char变量c后应补充3个空,其后才是成员struct1的内存空间,20行的输出结果为4。

posted @ 2006-07-06 21:20 Jerry Cat 阅读(271) | 评论 (0)编辑 收藏
[转]WTL之父Nenad Stefanovic访谈录

   作为现代C++最重要的特色技术,template正在各个传统领域攻城略地。从基本算法与数据结构,到正则表达式与XML解析,从高性能数学计算,到资源的分配与管理,从网络分布式计算环境,到组件模型创建,从静态多态性的维度扩展,到设计模式的自动生成,神奇的template显示出其令人叹为观止的强劲实力,如果不是有一个隐隐的痛处,template爱好者简直可以去狂欢了。

这个隐隐的痛处,就是在GUI编程领域。

   现有的大部分成熟GUI框架和工具库,其定型时间都在90年代早期,不管是因为什么原因,总之我们根本看不到template技术在这些环境中的任何重要运用。无论是专有MFC和OWL,还是开源的wxWindow和Mozilla, 以至于是专有还是开源都说不清楚的Qt,它们在其他方面有着诸多不同,偏偏倒是在对待模板技术上空前一致:严格限制在底层的数据结构领域内,抵制模板技术流入GUI主体结构。最过分的wxWindow和Mozilla,在代码编写规范里严厉禁止使用1990年之后发展出来的任何C++特性,模板、异常、多继承、STL等等,均在黑名单上。诸位有兴趣,不妨去看看,那与其说是一份C++代码编写规范,倒不如说是对C++现代特性在GUI领域应用的一份不公正的判决书。

难道模板技术真的在GUI领域无用武之地吗?

WTL给出了一个响亮的回答。

   WTL是微软ATL开发组成员Nenad Stefanovic先生在ATL Windowing机制上发展起来的一整套GUI框架,运用template技术组织和创建GUI对象,构筑了精致的面向对象框架(没错,在这里object oriented与template达成了精致的融合)。虽然没有获得微软的官方支持,虽然其使用者人数很少,但是确实是“用过的都说好”,有位微软MVP人士甚至说,这是微软有史以来推出的最优秀的一个framework。真是一个有趣的讽刺,最好的东西居然不被官方支持。有关于WTL的流言不少,比如这东西原本是微软内部专用,只是因为不小心才被泄漏出来等等,这更加剧它的神秘色彩。相信大家对它一定有不少问题。我们特别邀请到了WTL之父Nenad Stefanovic先生,进行了一次网上的访谈,希望能帮助大家了解WTL的真面目。

【C++ View】:I think most of our readers are not very familiar with you, so would you please tell us your story here? We are very fond of that. What do you think about China and Chinese people?

【C++ View】:我想,可能我们的读者中有很多人对您还不是很熟悉,您能不能在此给我们简单介绍一下您自己呢?我们将非常乐意听到您的自述。还有,您能不能也对我们讲述一下您对于中国以及中国人民的基本看法呢?

【Nenad】: I am a software developer at Microsoft. Your readers will probably know me as a creator of Windows Template Library, WTL. I am from former Yugoslavia, where I finished school and started working on software development. I've been living in US for 10 years now.

I am intrigued and impressed by the Chinese culture and tradition. I think that China is now in a great position of progress as a country and a nation. I discovered that, being from former Yugoslavia, I already know many things about China, and getting to know people from China gave me a bit of the "everyday" life perspective as well. I'd like to learn more, so I hope to visit China one day.

【Nenad】:好的。我现在在Microsoft工作,是它里面的一个软件开发人员。你们杂志的读者中可能有人知道,我就是Windows Template Library (WTL)的创作者。我来自于前南斯拉夫,在那我完成了我的学业并开始了我作为软件开发人员的工作生涯。现在,我在美国居住的时间已经超过了10年了。

   中国的文化以及传统给我留下了极为深刻的印象,我对此十分感兴趣。我想,作为一个国家以及民族,中国已经处于一个伟大并且不断在成长中的位置上。作为一个从前南斯拉夫来的人,我早就了解到关于中国的很多事情。在与来自中国的人民的接触过程中,我还了解到了你们日常生活的一些状况。我还想了解更多(有关中国的事情),希望有一天我可以到中国来游览。

【C++ View】:When and why did you first think about WTL? What's its original purpose? How do you see its future?

【C++ View】:您是什么时候开始想起要开发WTL呢?为什么?您在开发它时的最初目的是什么?您又是如何地看待它未来的发展呢?

【Nenad】:WTL was born while I was working on ATL (Active Template Library). We were extending ATL to support ActiveX controls, and I was working on the windowing support. I started thinking that the same techniques can be applied to much broader windowing support, for the much richer UI for controls, components, and also applications. So, WTL was created as a part of ATL that would extend ATL to support any kind of UI related component or application. It did not ship with ATL in Visual Studio, however, so I decided to ship it as a standalone library that extends ATL.

I think that WTL will continue to be a great option for developers writing Windows applications and components. I don't see big changes or additions to WTL, because one of the design principles for WTL was to follow the Win32 UI API and design. It will continue to do so.

【Nenad】:WTL是我在从事ATL (Active Template Library)开发工作时的产物。那时我们正在扩展ATL,使之得以支持ActiveX control,而我负责的就是其中对于窗口机制部分的支持。这时,我就开始想,是不是可以把同样的技术应用到更为广泛的窗口机制中,以获得更丰富的UI控制、组件、以至于应用程序呢?于是,作为ATL的一部分,WTL被开发出来了。它将ATL进行了扩展,以使得它可以支持各种类型的与UI相关的组件或者应用程序。然而,它并没有随着ATL一同集成在Visual Studio中被发布,于是我就决定将它作为一个单独的ATL扩展库发布出去。

我认为WTL将一直是那些在Windows下开发应用程序以及组件的开发者的一个很好的选择。我并不认为在以后,我们会对WTL有一个大的改动(或者增添),因为WTL的一个设计宗旨就是“遵循Win32 UI的API及其设计”。现在如此,将来还是会如此下去。

【C++ View】:I first heard about WTL in July, 2000. At that time, I thought: "No official support, no documentation, no commercial hype, it will die in 6 months." Now, fifteen months passed, it spreads wider and be more vigorous. Lots of C++ programmers, esp. the ones we regard them as "gurus and masters" involved in WTL. I know it's surely because WTL is a wonderful library, but it must be more than a wonderful library to gain such attentions without official force.What do you think WTL's relative success? What's the reason?

【C++ View】:我第一次接触WTL是在2000年7月。在那时,我就想:“没有官方的支持,没有文档,也没有商业吹捧,它最多只能够存活6个月。”但现在15个月过去了,它反而流传得更为广泛,更加的生机勃勃。许多C++程序员,尤其是一些我们所认知的“专家”以及“大师”,都在使用WTL。我当然知道这主要是因为WTL的出色,但我想,能够在没有官方的力量牵涉的情况下吸引如此多的注意,WTL一定还有更出色的东西,请问您是如何看待WTL的成功呢?它成功的原因又是什么?

【Nenad】: I think that the main reason of WTL's success is that it did fit the need of developers at the right time. More and more developers started using ATL, and it was natural for them to start using WTL when they needed more UI support. It seems that WTL was perceived as a more open project than others, judging by the support provided by other parties in the development community. Many people did a wonderful job of creating samples, documentation and support for WTL. The support from the programming community is very important part of the acceptance and success of WTL.

【Nenad】:我认为WTL成功的最主要原因就是,它确实而且及时地满足了开发者的需求。越来越多的开发人员开始使用ATL,当他们需要更多的UI支持时,他们很自然的就会开始使用WTL。 从其他的开发团队所提供支持来看,WTL看起来似乎要比其他的项目更加开放。许许多多人为WTL做了大量工作,如:创建示例代码,撰写文档等。WTL之所以能够被广为接受并获得如此大的成功,来自于这些开发团队的支持绝对是一个重要的因素。

【C++ View】:What do you think about MFC? Do you like it? If you don't, why? And the most confusing thing is Managed C++, is it C++? Do the leaders of MC++ really think some C++ users will go to learn it? Do you believe?

【C++ View】:请问您对于MFC是怎么看的?您喜欢它吗?如果不,为什么呢?还有,最让人迷惑不解的就是Managed C++了,它是不是C++呢?MC++的提倡者是不是真的认为会有一些C++的用户转而去学习它呢?您的看法又是如何呢?

【Nenad】: I think that MFC is a great framework library. Don't forget that MFC was designed at the time that C++ compiler was rather limited, and the main platform was 16-bit Windows. Unfortunately, because MFC was designed as a framework, it was really hard to evolve it to use better C++ support in newer compilers, and to add support for new features added to Windows in the meantime. What I don't like about MFC is the DLL approach, which causes many compatibility problems, and framework design, which dictates too many things about app design.

Managed C++ is an extension to C++ which allows C++ programs to use managed code. It is very important to understand that you can compile your existing C++ code using MC++ without any changes. MC++ allows developers to use both familiar non-managed C++ and managed code in the same module. That provides an excellent way to extend existing code to interact with managed code, as well to create new projects that can use both managed and traditional C++.

【Nenad】:我认为MFC是一个了不起的框架库。请不要忘了,在MFC被设计出来初期,那时的C++编译器还具有很多的限制,并且那时主要的平台还只是16位的Windows。不幸的是,由于MFC被设计成为一个框架,使得我们很难利用新编译器中那些更好的C++特性来改进它,也很难将Windows中的很多新特性添加到MFC中。我不喜欢MFC的地方是它高度依赖DLL的特性——因为它将导致许多兼容性方面的问题;还有就是MFC的整个框架设计——它在应用程序的设计中限定了太多东西。

Managed C++是C++的一个扩展,它允许C++程序得以使用受管(managed)代码。我们需要了解的一个很重要的特性就是,我们可以使用MC++来编译已有的C++代码而无需对它们进行任何改动。MC++允许开发者同时使用他们所熟悉的非受管代码以及受管代码来开发同一个模块。这就提供了一个非常好的途径,使已有的代码与新的受管代码相互作用,并也可使得我们创建一个项目,同时使用受管的和传统的C++代码。

【C++ View】:In the past 15 years or more, C and C++ is the base of almost all Microsoft's technologies(OS, COM, etc.). We C++ user paid a lot of hard work to catch them, because we felt what we paid was worthy(?). Now, it seems the climate changed. .NET is coming, the world is going to be full of CLRs and/or JVMs. There has been a decampment from C++. So what do you think about the future of C++ (not MC++) in Mircosoft technologies? Will it go away? Will it become a marginal language?

【C++ View】:在过去的15年中(甚至更长的一段时间内),C以及C++构成了几乎所有Microsoft技术的基础(如:OS,COM等)。我们这些C++用户花费了大量的时间来熟悉并掌握它们(C以及C++),因为我们相信我们所付出的一定会有回报(?)。但现在的风向好像有了很大的改变。.NET出现了,世界似乎就要充斥CLR (Common Language Runtime,公共语言运行库)以及/或JVM (Java Virtual Machine,Java虚拟机)。现在C++已经出现了退潮的迹象。那么,请问您对于C++(不是MC++)在Microsoft技术中的前景如何看待?它是否会由此消亡?还是就此沦落为一门边缘语言?

【Nenad】:Well, the world is changing too. The new type of development for Web services and connected applications is on the horizon. I think that new languages, like Java, C#, and VB.NET, were developed to address two main issues - to simplify software development and to provide better support for Internet development. Simplifying software development allows more developers to write good applications and cuts down on time needed to finish a project. Supporting Internet development is obviously very important in this time when Internet is used more and more in every part of everyday life.

I think that C++ will continue to be an important language, especially for ISV's and for system development. On the other hand, I believe that .NET will be very important platform soon. .NET has the potential to be the main programming platform for the future, but it is reasonable to expect that the transition will take some time.

【Nenad】:是的,世界也已经发生了变化。对于网络服务以及连接这样的新型应用程序的开发已经浮上了水面。我认为那些新的编程语言(如Java,C#,以及VB.NET)都是针对以下两个主要的问题而开发出来的——简化软件的开发过程以及对于Internet应用程序开发提供更好的的支持。简化软件的开发过程使得更多的开发者可以写出更多更好的应用程序并减少完成开发项目所需要的时间。而支持Internet的开发,对于这个Internet越来越深入到我们的日常生活中的时代来说,毫无疑问是一件非常重要的事情。

我认为C++会继续作为一门重要的编程语言发挥作用,尤其是对那些独立软件开发商和那些系统级开发来说更是如此。从另一方面来说,我相信.NET将会在不久以后成为另外一个非常重要的开发平台。对于未来来说,.NET拥有成为主流编程平台的潜力,但我们必须认识到,这样的过渡阶段肯定要持续一段时间。

【C++ View】:There a lots of beginners in our readers, after they learn (standard) C++, they want to seek a path to master enought Microsoft technologies to be practical and proficient programmers. Could you recommend such a path? Should they learn Win32 API programming? Is it worthy of studying MFC? Is WTL/ATL/STL a reliable solution? Or goto C# directly? Many many people will thank you if you give them frank advice.

【C++ View】:我们的读者中有很多是初学者,在他们学习完(标准)C++后,他们希望能够找到一条道路,掌握到足够多的Microsoft的技术使自己成为经验丰富的、熟练的程序员。您能不能给我们指出这样的一条道路来呢?我们是不是应该学习Win32 API编程?学习MFC是否是值得的?WTL/ATL/STL算得上是一个可靠的解决方案吗?又或是我们应该直接学习C#?如果您能够给我们一些建议,相信会有很多的人为此而感激您的。

【Nenad】:I think that depends on their plans and ambitions. The more of those things you do, the better you are off in the long run. But, you also have to balance that with the practical issues. So, I think that people who see their future in the Internet development can go directly to C# or VB.NET, and study .NET platform. Those who would like to have more knowledge of the Windows platform and services it provides should certainly learn more about Win32 API and libraries that support Windows programming.

【Nenad】:我认为这主要取决于他们的计划以及雄心。你所做的越多,在长时间竞争中你就越占据优势。不过你也要注意保持与实际问题的平衡。我建议那些决心以后只做Internet相关开发的人可以直接去学习C#或者VB.NET,同时学习.NET平台。而那些更多地了解Windows平台以及它所提供的服务方面知识的人,当然就必须需要更多地了解有关Win32 API以及那些支持Windows编程的库相关的知识。

【C++ View】:Soon after I began to learn WTL, a warm-hearted man posted me a email. He wrote: "You won't be a good WTL programmer if not a good ATL programmer, you won't be a good ATL programmer if not a COM programmer. And once you decide to learn COM, you are beginning your travel to hell." Is COM so difficult to learn? How to study WTL? We must learn API, COM, ATL and WTL in sequence, do we? And what about COM, will it remain to be the core technology of Microsoft, or just be substituted by .NET and dismiss?

【C++ View】:在我刚开始学习WTL后不久,有一位热心人给我发了份邮件。他写道:“如果你不是一个好的ATL程序员的话,你就不可能成为一个好的WTL程序员;如果你不会COM编程的话,你就不可能成为一个好的ATL程序员;但一旦你决定开始学习COM,你就迈出了踏向地狱的第一步。”COM是不是真的那么难学?我们应该如何地来学习WTL呢?我们是不是应该按照这样的顺序学下来呢,API->COM->ATL->WTL?还有,COM将会变得如何?他是不是还能够保持Microsoft的核心技术这一头衔,抑或是被.NET给替换掉然后就此消失?

【Nenad】:I don't think it is necessary to master COM to use and understand WTL. Win32 UI knowledge is more important than COM to understand WTL. But it is true that knowledge of ATL is required, and ATL mainly supports COM. So, COM knowledge is desirable, but not required.

I don't think that COM is hell, but it sure does require a lot to learn to be an expert. Keep in mind that many people don't have to be COM experts to use COM, or to use WTL. Just understanding basic principles of COM is enough to use it, and then people can learn more when needed.

【Nenad】:我不认为使用和理解WTL就一定要掌握COM。相比于COM来说,Win32 UI的知识对于理解WTL显得更为重要。但毫无疑问的是,ATL的相关知识是必不可少的。由于ATL主要任务就是支持COM,所以,有COM的知识只是会更好一些而已,但它们并不是必需的。

我也不认为COM是一个噩梦,但毫无疑问的是,想要成为一个COM专家,要学的东西实在是太多了。但请记住一件事情,很多使用COM或者WTL的人并不都是COM方面的专家。要想使用它们,人们所需了解的只是一些COM的基本原理就够了,其他的相关的知识则可以在需要时再去学习。

【C++ View】:What do you think about Generic Programming? Is it a whole different paradigm from OOP, or just OOP's supplemental facility? Can we combine GP and OOP? In the hard work of design and implement WTL, you must had got an insight about the relationship between OOP and GP, what's it?

【C++ View】:请问您对于泛型程序设计是如何看待的?它到底是OOP的一个补充呢,还是完全不同于OOP的另外一个程序设计范型呢?我们是否可以将GP以及OOP一同联合使用?我想,在设计和实作出WTL的艰苦过程中,对于OOP以及GP之间的关系,您一定有了自己的看法,您能不能给我们说一下呢?

【Nenad】:Generic Programming and OOP are very different, mostly because Generic Programming doesn't explicitly express relationships between design elements. They can, however, be used together very efficiently.

WTL uses a combination of Generic Programming and OOP design. Templates are mostly used to implement traditional OOP classes. I'd like to point out that WTL doesn't use any "pure" design, and it doesn't strictly follow any design guidelines or styles. I do think, though, that WTL does use one of the main strengths of the C++ language - it uses appropriate paradigm that is the most suitable for a particular problem.

【Nenad】:GP和OOP非常不同,这主要是由于GP从不显式地表达出设计元素之间的关联来。然而,它们也可以被非常高效地组合运用。

WTL中使用了一种GP连同OOP的设计。我在其中大量使用了模板来实作出传统的OOP中的类。我很乐意指出的是,WTL中并没有使用一种“纯”设计,它也没有遵循任何的设计指导方针或者设计规格。可是,我还是认为WTL使用到了C++语言中的最主要的精髓处——对于一个特定的问题使用一种最适合它的适当典范。

【C++ View】:Recently, the famous C++ pioneer Stanley Lippman joined Microsoft and became a member of Visual C++.NET group. How do you think about this? What message do you think your company like to pass to public? Does this mean Microsoft want to make VC.NET a full-standardized C++ compiler and hold C++ as your core system language?

【C++ View】:最近,著名的C++元老级大师Stanley Lippman加入了Microsoft并成为其VC.NET开发小组中的一员。请问您对于此事是如何看待的?您认为Microsoft试图向公众传播一种什么样的信息呢?这是否也意味着Microsoft希望VC.NET成为一个完全标准化的C++编译器,并继续保持C++的核心系统语言地位呢?

【Nenad】:I think that shows that Microsoft is committed to advance the C++ compiler and language, and ready to get the best people to help. I am sure that VC++.NET will continue to be powerful tool for developing applications, and that it will also include additional capabilities for the .NET development. Compliance with the C++ Standard is an ongoing work, and we will see further improvements there, too.

【Nenad】:我认为这显示了Microsoft对于促进C++编译器以及语言继续发展的决心,并为此找到了最佳人选来获取帮助。我确信VC.NET将会继续是开发应用程序的强有力工具,并且它同时还将包含有.NET开发能力。目前我们正在进行兼容C++标准方面的工作,不久我们就会看到成效。

【C++ View】:I'm learning WTL and ATL, since you are the author of WTL and a member of ATL group, can you give me some advice?

【C++ View】:我现在正在学习WTL以及ATL,既然您是WTL的作者,同时又是ATL开发小组中的一员,您能不能给我一些建议呢?

【Nenad】:There are several areas of programming that are very important for WTL and ATL: knowledge of the C++ language in general, understanding of templates, COM for ATL, and Windows UI programming for WTL. Solid knowledge in these areas is very beneficial for WTL and ATL developers, and it also helps to understand the source code for both libraries.

I would also like to encourage everybody to write programs. That is the best way to learn how to use any library, or a programming language or operating system. Writing programs often brings problems that must be solved that are not addressed in books. Reading about something is very useful to start learning, writing programs is the best next step.

【Nenad】:对于WTL和ATL来说,有好几个编程方面的领域是十分重要的:大体上的C++语言知识,了解模板,COM(对ATL而言),以及Windows UI编程(对WTL而言)。在这些领域有着坚实的基础对于WTL以及ATL开发人员来说有着很大的好处,同时对于理解这两个的源代码也能够起到帮助作用。

我同样也很乐意去鼓励大家多写程序。这也是学习如何使用一个程序库,或者一门编程语言,或者一个操作系统的一个最好的方法。在写程序的过程中经常会出现一些书本上没有提及但又必须被解决的问题。在开始学习时读一些东西是很有用的,而写程序则是向纵深发展的最佳方式。

【C++ View】:They say we are in the gate of Post-PC times, it will be a embedded world, and there will be embedded smart device everywhere, and the embedded industry will build a far large market compare to PC's. Do you believe it? Do you think WTL and other C++ template libraries are available and appropriate for embedded development? Are there available for Internet development?

【C++ View】:有人说,我们现在已经处于后PC时代的门口,未来将会是一个嵌入系统的世界,嵌入式的智能设备将会无所不在,并且对比PC来说,嵌入系统的产业将会是一个更大的市场。您是否相信这些呢?您是否认为WTL以及其他的一些C++模板库对于嵌入式开发也适用呢?它们是否适合Internet开发?

【Nenad】:Yes, I think that large number of various devices that we use everyday will become small, specialized computers. That doesn't mean that the number and importance of PCs will go down, just that there are many other devices that will be enhanced to be programmable and connected. Those new devices will provide a great opportunity for software developers, because they will all have software and somebody has to write it.

Many of the C++ libraries are quite appropriate for embedded development, and WTL would also be in cases where Windows based user interface is important (for example, Pocket PC platform). Great flexibility and small footprint are always very important features for embedded development, so template libraries are in the very good position there.

【Nenad】:是的,我认为我们现今所使用的各种设备中的大部分在以后都将会演变成为一些小的,具有专门用途的计算机。但这并不意味着PC的数目以及重要性将会由此降低,只不过是表明还有着许多其他的设备需要被加强以使得我们可以对其进行编程并且连接。由于必须需要有软件的支持,而软件又需要有人来写,这些新的设备将会给软件开发人员带来极大的机遇。

有许多的C++函数库都可用于嵌入系统的开发,WTL也将会在那些Windows用户界面较为重要的开发中(例如,在Pocket PC平台上面开发)占有一席之地。对于嵌入式开发来说,良好的弹性,微小的内存耗用永远都会是很重要的特性,而模板库在这方面占据了一个非常好的地位。

【C++ View】:In the past 7 years or more, COM is Microsoft's core technology. And we now can see that in the next decade, the core role may be .NET. My question is, what's wrong with COM? Where will COM be? Will it disappear? Will it be substituted by something else? What's the relationship between COM and .NET? Is .NET based on COM? Is it worthy of learning COM now?

【C++ View】:在过去的7年(甚至更长的一段时间)内,COM都是Microsoft中的核心技术。现在我们可以预见到,在下一个十年间,这个核心将会变为.NET。我的问题就是,COM有什么过错?COM将何去何从?它是否会逐渐消失呢,还是会被其他的一些技术给替代?COM和.NET之间的关系是什么样的情况?.NET是否是基于COM之上呢?现在学习COM是不是还值得?

【Nenad】:Maybe you shouldn't ask what is wrong with COM, but just think of .NET as the evolution of COM. .NET extends what was started with COM- creating reusable binary components - and brings additional important features: rich metadata, great run-time, built-in security, versioning, etc. All of these new features are important for development today, and it is really great that .NET has extensive support for them. Interoperability between .NET and COM is also provided, so that the previously developed COM components can still be used in the .NET environment.

I still think that it is a good idea to learn COM - it is a great first step even for people who want to learn .NET, and it also provides better understanding of the design and implementation of .NET itself.

【Nenad】:或许你不应该问COM有什么过错,而是应该把.NET看成COM的进化。.NET扩展了COM最初的目的——创建可重用的二进制程序组件——并向其中添加了很多重要的特性:丰富的元数据,了不起的运行库,内建的安全机制,版本机制等。对于现今的软件开发来说,所有的这些新的特性都非常重要,所以.NET能够广泛地支持它们,是一件很伟大的产品。Microsoft同时也提供了在.NET和COM之间进行互操作的能力,这使得以前所开发出来的COM组件在.NET环境中同样也能够得到使用。

我仍然认为学习COM是一个很好的主意——它甚至对于那些希望学习.NET的人们来说也是一个很好的开端,学习COM同时也有助于我们更深入地理解 .NET本身的设计和实现。

【C++ View】:I know you must be a C++ fan. Now the language is facing lots of challenges. To counterattack, Dr. Stroustrup suggest to develop many useful libraries, and teach the programmers to use C++ as a high level language. Now there are several wonderful modern C++ libraries. Aside of ATL, WTL and STL, there are still Boost library, MTL, ACE/TAO, DTL, etc. It seems the C++ community is preparing a movement. Do you think the movement will success? Why? What are your colleagues'(in Microsoft VC.NET group) attitude towards such a movement?

【C++ View】:我猜想您肯定是一个C++爱好者。现在这门语言面对着许多的挑战。作为反击措施,Stroustrup博士提议开发许多有用的库,并引导C++程序员把C++当作一门高级语言来使用。现在我们已经可以得到好几个极好的现代的C++库,除去ATL、WTL以及STL之外,还有Boost库、MTL、ACE/TAO、DTL等。一切都显示着C++社区正在酝酿着一次变革。请问您觉得这场变革能否成功?为什么?您的那些Microsoft中的VC.NET开发小组中的同事对于此态度是怎样的?

【Nenad】:C++ is a great language and its importance remains high, even with the new challenges. Libraries are an excellent addition to the language itself, as they provide very useful reusable code for developers. The existence of many great C++ libraries shows the size and strength of the C++ community. I think that is already a success, and that it will continue. You can be sure that the VC++.NET group is aware of the existing libraries, and I expect them to continue to enhance the support for them.

【Nenad】:C++是一门伟大的语言,即便遇到了新的挑战,它仍然将是非常重要的。程序库对于语言本身是极好的补充,它们为开发者提供了一些十分有用的可重用代码。存在如此众多的、了不起C++程序库,这件事情本身就表明了C++社区的庞大和强大。我认为这场变革已经成功了,并且会一直成功下去。你们可以放心,VC.NET开发组是不会对这些已有的程序库熟视无睹的,我预期他们会不断地加强对于这些库的支持。

【C++ View】:The last question. Since lots of people don’t acquaint themselves with WTL, now we have a chance for you, the father of WTL, to introduce WTL in a short speech here. What would you like to speak?

【C++ View】:最后一个问题。既然许多人并不了解WTL,作为WTL之父,您现在有机会在这里做一个演讲,请简短地介绍一下WTL。

【Nenad】:WTL is a template based library for user interface development. It extends ATL to provide classes for implementing user interface for applications, components, and controls. It provides classes for various user interface elements: top-level windows, MDI, standard and common controls, common dialogs, property sheets and pages, GDI objects, UI updating, scrollable windows, splitter windows, command bars, etc.

WTL is implemented using the same template architecture as ATL, so it is a natural fit for ATL developers. It also doesn't alter or hide Windows specific constructs, thus allowing Windows programmers to use WTL without surprises. The important design goal of WTL was to avoid inter-dependencies - classes themselves do not reference other WTL classes. That means that your program will contain just the code that you actually use, and nothing else. Coupled with the use of templates, this allows creation of very small programs without run-time dependencies.

WTL delivers the object oriented way to program for the Windows user interface, while keeping the code size small. It also provides a great foundation that developers can extend with their own classes.

And finally - WTL was written with a hope that developers will enjoy using it. I hope you will use it and enjoy it, too.

WTL是一个基于模板的、专为开发用户界面的程序库。它扩展了ATL,并提供了一些类用来实现应用程序的用户界面、组件和控件。它提供了各种类来支持各种各样的用户界面元素:顶级窗口、MDI、标准控件和通用控件、通用的对话框、属性表以及属性页、GDI对象、UI更新、可卷动的窗口、分割窗口、命令条等等……

WTL的实现使用了和ATL一样的模板架构,所以对于ATL开发者显得很自然。同时它并没有改变或者是隐藏那些Windows相关结构,那些Windows程序员在使用WTL时也不会感到很吃惊。WTL的一个主要设计原则就是避免在没有引用到其他WTL类时,出现不必要的内部依赖。这意味着我们的程序将只包含有我们实际上所使用的代码,除此之外再无其他的东西。加上了模板的使用后,这样做得到的结果就是一些非常小的,不依赖于运行库的程序。

WTL专注于用面向对象的方法来编写Windows的用户界面程序,同时保持代码的尺寸很小。同时,它也为开发者提供了一个很好的基础,可以写新的类来扩展WTL。

最后,我在编写WTL时就希望开发者能够喜欢在开发中使用它。我同样也希望您能够使用它并喜欢上它。

posted @ 2006-07-05 23:15 Jerry Cat 阅读(168) | 评论 (0)编辑 收藏
[转]Run time type Information

一                 dynamic_cast
< type-id > ( expression )
  type-id :必须是指针或者引用
  expression:必须是指针或者一个左值
基本上是用来做 子对象间的转换
1.基本的用法
				class B { ... };
class C : public B { ... };
class D : public C { ... };

void f(D* pd)
{
   C* pc = dynamic_cast<C*>(pd);   // ok: C is a direct base class
                                 // pc points to C subobject of pd 

   B* pb = dynamic_cast<B*>(pd);   // ok: B is an indirect base class
                                 // pb points to B subobject of pd 
   ...
}
		

This type of conversion is called an "upcast" because it moves a pointer up a class hierarchy, from a derived class to a class it is derived from. An upcast is an implicit conversion.

If type-id is void*, a run-time check is made to determine the actual type of expression. The result is a pointer to the complete object pointed to by expression. For example:

				class A { ... };

class B { ... };

void f()
{
   A* pa = new A;
   B* pb = new B;
   void* pv = dynamic_cast<void*>(pa);
   // pv now points to an object of type A
   ...
   pv = dynamic_cast<void*>(pb);
   // pv now points to an object of type B
}
		

If type-id is not void*, a run-time check is made to see if the object pointed to by expression can be converted to the type pointed to by type-id.

If the type of expression is a base class of the type of type-id, a run-time check is made to see if expression actually points to a complete object of the type of type-id. If this is true, the result is a pointer to a complete object of the type of type-id. For example:

				class B { ... };
class D : public B { ... };

void f()
{
   B* pb = new D;                     // unclear but ok
   B* pb2 = new B;

   D* pd = dynamic_cast<D*>(pb);      // ok: pb actually points to a D
   ...
   D* pd2 = dynamic_cast<D*>(pb2);   // pb2 points to a B not a D
                                    // cast was bad so pd2 == NULL
   ...
}
		

This type of conversion is called a "downcast" because it moves a pointer down a class hierarchy, from a given class to a class derived from it.
小结:
  a     实际指向对象 和   b 目标对象,  b 是a 的 基类(子对象),或者是2者 同级转换才成功
否则 目标为NULL;也就是说不能向下转



2   多重非虚的继承模式

Class Hierarchy Showing Multiple Inheritance

A pointer to an object of type D can be safely cast to B or C. However, if D is cast to point to an A object, which instance of A would result? This would result in an ambiguous casting error. To get around this problem, you can perform two unambiguous casts. For example:

				void f()
{
   D* pd = new D;
   A* pa = dynamic_cast<A*>(pd);      // error: ambiguous
   B* pb = dynamic_cast<B*>(pd);      // first cast to B
   A* pa2 = dynamic_cast<A*>(pb);   // ok: unambiguous
}
		

Further ambiguities can be introduced when you use virtual base classes. Consider the class hierarchy shown in the following figure.

    也就是说在2意性下会失败
3.子对象间的转换

Class Hierarchy Showing Duplicate Base Classes

    //pd 指向 e 对象
void f(D* pd)
{
   E* pe = dynamic_cast<E*>(pd);
   B* pb = pe;      // upcast, implicit conversion
   A* pa = pb;      // upcast, implicit conversion
}

//pd 指向 e 对象
void f(D* pd)
{
   B* pb = dynamic_cast<B*>(pd);      // cross cast
   A* pa = pb;                  // upcast, implicit conversion
}

  也就是  所谓 cross cast

二  typeid( type-id )     typeid( expression ) 
   此操作符返回个  const type_info & 
            expression 必须指向一个多态类型(带虚函数    ),并且要解引用

#include <iostream>
#include <typeinfo.h>

class Base {
public:
   virtual void vvfunc() {}
};

class Derived : public Base {};

using namespace std;
int main()
{
   Derived* pd = new Derived;
   Base* pb = pd;
   cout << typeid( pb ).name() << endl;   //prints "class Base *"
   cout << typeid( *pb ).name() << endl;   //prints "class Derived"
   cout << typeid( pd ).name() << endl;   //prints "class Derived *"
   cout << typeid( *pd ).name() << endl;   //prints "class Derived"
   delete pd;
}
// compile with: /GR /EHsc

在模版中使用
template < typename T > T max( T arg1, T arg2 ) {
   cout << typeid( T ).name() << "s compared." << endl;
   return ( arg1 > arg2 ? arg1 : arg2 );
}

-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=

还不知道dynamic_cast<void*>()能转换成真实类型的指针。有这个功能,真太好了。
等C++0x出来后,就可以用:
auto pv = dynamic_cast<void*>(...)来获取真实类型了。

posted @ 2006-07-04 21:03 Jerry Cat 阅读(235) | 评论 (0)编辑 收藏
一次关于旨在降低编译时间的整改工作(vc++)
[转自]天爬者


由于工程的文件的日益庞大和第3方库(ACE Loki Boost等等)的使用增多
我所工作的项目系统构建时间从最初的3分钟变为现在的8分钟
程序员的机器配置已经很不错了,3。0 的主频1g的内存,但是常常由于一个小的修改导致5分钟甚至更长的编译时间来验证效果。

按照《Joel on software》的说法,其直接后果是可怕的:
程序员们在这8分钟内无所事事,只有查看网页,或者qqmsn,打断先前的思路从他们的上下文环境里面脱离了出来,离开了“顺势工作时间”,等到他们编译好了验证再修改的时候,他们又得花不少的时间来回到刚才的思路

“顺势工作时间”大致意思就是说2个不连续的半小时的效果远不如一个连续沉浸的1小时的工作效果,如果一个人不能连续沉浸的思考,那么他就很可能陷入在不停的上下文环境切换和浅表思考当中。人的多线程处理和机器是一样的环境的切换不能够不考虑

所以,在当前机器配置已经没有什么提升空间的情况下,我在项目组内部组织了一次整改活动,旨在降低编译构建时间


1。目标:将完全重新编译时间从8分钟降低到4分钟以下
2。原则:通过和主程序的沟通,并参考了《C++ coding Standards》出了一下几条整改原则:
     首先是关于include的,因为包含头文件相当于将代码复制到本文件来编译,而头文件又经常是用来被别人包含的,所以工程文件多了,每个文件都有include链(包含的文件又include了其他文件),该链条不会止步于你工程,而会延伸到你所有使用的第3方库里面

     A.
能够去掉的include就去掉。

     B.能够在cpp
里面include的头文件不要在头文件里面include。
     
说明:尽量去掉每个cpp会被串起来的头文件膨胀的机会

     
C.能够用前向声明的就不要include,头文件里面也是一样
     说明:在头文件里面用前向声明然后保存指针或者引用,在具体实现的cpp里面再包含头文件,虽然看起来和《C++ coding Standards》“
Make header files self-sufficient ”有些冲突(前两天另外cppblog一位朋友讲过 http://www.cppblog.com/flyingxu/archive/2006/06/23/8908.html )但是在一些核心的.h(被很多类include的)里面作改造工作,还是能够收到很大的降低编译时间效果,而付出的代价就是原来只需要包含该头文件就可以编译成功的cpp需要额外包含一些头文件。

举个例子: Foo类头文件使用了前向申明保存了A类和B类的指针或者引用为成员变量,在Foo类的cpp里面才包含A和B的头文件,而当C类需要使用Foo类时候包含Foo类的头文件,但是操作中又需要调用A的成员函数,C不同时包含A的头文件的花就会出现编译失败。

虽然表面上是让代码更加复杂了,但是除却带来降低编译时间的好处之外,代码也在强迫你进行解耦合,如果说你cpp里面需要包含的头文件越多,说明你这个类需要知道的对象就越多,你可以乘机检查一下自己的代码又没有不必要的耦合,为什么这个cpp需要知道那么多的本来可能属于别的类的细节.....

      D。
把大多数模块都要使用的库文件或者稳定类的头文件include放到预编译头文件“stdafx.h”里面
      
说明:由于预编译头文件里面include的内容只会compile一次而被link多次,把一些常用类放到这里会降低很多编译时间,但也不能乱来,要点在于 “大多数”和“稳定”,如果一个头文件经常变化,他的一次小改动都会引起整个工程rebuild,哪怕只是一个注释,因为所有的cpp文件都包含了stdafx.h而stdafx.h又包含了这个容易变动的头文件。
      
      
E.使用Pimpl惯用法
      说明:关于Pimpl大家可以查下资料,《C++ coding Standards》里面也有讲解,基本上就是采用一个私有的前向申明的stuct指针把所有protect成员都封装起来起来.基本上是一个最终极的解决方案,但是对我们现有架构改造太大,不敢全面实行,我们只选择了数个最有价值的类进行了改造,打算以后在其他项目里面再全面应用。

3。实施: 通过半个小时的沟通,让项目组程序员了解原则,并采取结队修改的方式来降低引入新bug的风险,在以通过原有单元测试用例的条件下,进行修改-测试-提交的迭代。
   

4。结果:   编
译时间降低到了6分钟以内。。。虽没有达到预期,但也算有效果,没有完全达标的主要原因还是没有完整的测试方案包括单元测试和验收测试,怕有些改动过大影响系统健壮性,局部放弃了一些实施的原则。


把这个整改的工作写出来,一方面作个记录,另外一方面希望和大家讨论,相互多多交流:)
posted @ 2006-07-04 03:38 Jerry Cat 阅读(393) | 评论 (1)编辑 收藏
[转]Windows进程中的内存结构

在阅读本文之前,如果你连堆栈是什么多不知道的话,请先阅读文章后面的基础知识。
 
 接触过编程的人都知道,高级语言都能通过变量名来访问内存中的数据。那么这些变量在内存中是如何存放的呢?程序又是如何使用这些变量的呢?下面就会对此进行深入的讨论。下文中的C语言代码如没有特别声明,默认都使用VC编译的release版。
 
 首先,来了解一下 C 语言的变量是如何在内存分部的。C 语言有全局变量(Global)、本地变量(Local),静态变量(Static)、寄存器变量(Regeister)。每种变量都有不同的分配方式。先来看下面这段代码:
 
 #include <stdio.h>
 
 int g1=0, g2=0, g3=0;
 
 int main()
 {
 static int s1=0, s2=0, s3=0;
 int v1=0, v2=0, v3=0;
 
 //打印出各个变量的内存地址
 
 printf("0x%08x\n",&v1); //打印各本地变量的内存地址
 printf("0x%08x\n",&v2);
 printf("0x%08x\n\n",&v3);
 printf("0x%08x\n",&g1); //打印各全局变量的内存地址
 printf("0x%08x\n",&g2);
 printf("0x%08x\n\n",&g3);
 printf("0x%08x\n",&s1); //打印各静态变量的内存地址
 printf("0x%08x\n",&s2);
 printf("0x%08x\n\n",&s3);
 return 0;
 }
 
 编译后的执行结果是:
 
 0x0012ff78
 0x0012ff7c
 0x0012ff80
 
 0x004068d0
 0x004068d4
 0x004068d8
 
 0x004068dc
 0x004068e0
 0x004068e4
 
 输出的结果就是变量的内存地址。其中v1,v2,v3是本地变量,g1,g2,g3是全局变量,s1,s2,s3是静态变量。你可以看到这些变量在内存是连续分布的,但是本地变量和全局变量分配的内存地址差了十万八千里,而全局变量和静态变量分配的内存是连续的。这是因为本地变量和全局/静态变量是分配在不同类型的内存区域中的结果。对于一个进程的内存空间而言,可以在逻辑上分成3个部份:代码区,静态数据区和动态数据区。动态数据区一般就是“堆栈”。“栈(stack)”和“堆(heap)”是两种不同的动态数据区,栈是一种线性结构,堆是一种链式结构。进程的每个线程都有私有的“栈”,所以每个线程虽然代码一样,但本地变量的数据都是互不干扰。一个堆栈可以通过“基地址”和“栈顶”地址来描述。全局变量和静态变量分配在静态数据区,本地变量分配在动态数据区,即堆栈中。程序通过堆栈的基地址和偏移量来访问本地变量。
 
 
 ├———————┤低端内存区域
 │ …… │
 ├———————┤
 │ 动态数据区 │
 ├———————┤
 │ …… │
 ├———————┤
 │ 代码区 │
 ├———————┤
 │ 静态数据区 │
 ├———————┤
 │ …… │
 ├———————┤高端内存区域
 
 
 堆栈是一个先进后出的数据结构,栈顶地址总是小于等于栈的基地址。我们可以先了解一下函数调用的过程,以便对堆栈在程序中的作用有更深入的了解。不同的语言有不同的函数调用规定,这些因素有参数的压入规则和堆栈的平衡。windows API的调用规则和ANSI C的函数调用规则是不一样的,前者由被调函数调整堆栈,后者由调用者调整堆栈。两者通过“__stdcall”和“__cdecl”前缀区分。先看下面这段代码:
 
 #include <stdio.h>
 
 void __stdcall func(int param1,int param2,int param3)
 {
 int var1=param1;
 int var2=param2;
 int var3=param3;
 printf("0x%08x\n",¶m1); //打印出各个变量的内存地址
 printf("0x%08x\n",¶m2);
 printf("0x%08x\n\n",¶m3);
 printf("0x%08x\n",&var1);
 printf("0x%08x\n",&var2);
 printf("0x%08x\n\n",&var3);
 return;
 }
 
 int main()
 {
 func(1,2,3);
 return 0;
 }
 
 编译后的执行结果是:
 
 0x0012ff78
 0x0012ff7c
 0x0012ff80
 
 0x0012ff68
 0x0012ff6c
 0x0012ff70
 
 
 
 ├———————┤<—函数执行时的栈顶(ESP)、低端内存区域
 │ …… │
 ├———————┤
 │ var 1 │
 ├———————┤
 │ var 2 │
 ├———————┤
 │ var 3 │
 ├———————┤
 │ RET │
 ├———————┤<—“__cdecl”函数返回后的栈顶(ESP)
 │ parameter 1 │
 ├———————┤
 │ parameter 2 │
 ├———————┤
 │ parameter 3 │
 ├———————┤<—“__stdcall”函数返回后的栈顶(ESP)
 │ …… │
 ├———————┤<—栈底(基地址 EBP)、高端内存区域
 
 
 上图就是函数调用过程中堆栈的样子了。首先,三个参数以从又到左的次序压入堆栈,先压“param3”,再压“param2”,最后压入“param1”;然后压入函数的返回地址(RET),接着跳转到函数地址接着执行(这里要补充一点,介绍UNIX下的缓冲溢出原理的文章中都提到在压入RET后,继续压入当前EBP,然后用当前ESP代替EBP。然而,有一篇介绍windows下函数调用的文章中说,在windows下的函数调用也有这一步骤,但根据我的实际调试,并未发现这一步,这还可以从param3和var1之间只有4字节的间隙这点看出来);第三步,将栈顶(ESP)减去一个数,为本地变量分配内存空间,上例中是减去12字节(ESP=ESP-3*4,每个int变量占用4个字节);接着就初始化本地变量的内存空间。由于“__stdcall”调用由被调函数调整堆栈,所以在函数返回前要恢复堆栈,先回收本地变量占用的内存(ESP=ESP+3*4),然后取出返回地址,填入EIP寄存器,回收先前压入参数占用的内存(ESP=ESP+3*4),继续执行调用者的代码。参见下列汇编代码:
 
 ;--------------func 函数的汇编代码-------------------
 
 :00401000 83EC0C sub esp, 0000000C //创建本地变量的内存空间
 :00401003 8B442410 mov eax, dword ptr [esp+10]
 :00401007 8B4C2414 mov ecx, dword ptr [esp+14]
 :0040100B 8B542418 mov edx, dword ptr [esp+18]
 :0040100F 89442400 mov dword ptr [esp], eax
 :00401013 8D442410 lea eax, dword ptr [esp+10]
 :00401017 894C2404 mov dword ptr [esp+04], ecx
 
 ……………………(省略若干代码)
 
 :00401075 83C43C add esp, 0000003C ;恢复堆栈,回收本地变量的内存空间
 :00401078 C3 ret 000C ;函数返回,恢复参数占用的内存空间
 ;如果是“__cdecl”的话,这里是“ret”,堆栈将由调用者恢复
 
 ;-------------------函数结束-------------------------
 
 
 ;--------------主程序调用func函数的代码--------------
 
 :00401080 6A03 push 00000003 //压入参数param3
 :00401082 6A02 push 00000002 //压入参数param2
 :00401084 6A01 push 00000001 //压入参数param1
 :00401086 E875FFFFFF call 00401000 //调用func函数
 ;如果是“__cdecl”的话,将在这里恢复堆栈,“add esp, 0000000C”
 
 聪明的读者看到这里,差不多就明白缓冲溢出的原理了。先来看下面的代码:
 
 #include <stdio.h>
 #include <string.h>
 
 void __stdcall func()
 {
 char lpBuff[8]="\0";
 strcat(lpBuff,"AAAAAAAAAAA");
 return;
 }
 
 int main()
 {
 func();
 return 0;
 }
 
 编译后执行一下回怎么样?哈,“"0x00414141"指令引用的"0x00000000"内存。该内存不能为"read"。”,“非法操作”喽!"41"就是"A"的16进制的ASCII码了,那明显就是strcat这句出的问题了。"lpBuff"的大小只有8字节,算进结尾的‘\0‘,那strcat最多只能写入7个"A",但程序实际写入了11个"A"外加1个‘\0‘。再来看看上面那幅图,多出来的4个字节正好覆盖了RET的所在的内存空间,导致函数返回到一个错误的内存地址,执行了错误的指令。如果能精心构造这个字符串,使它分成三部分,前一部份仅仅是填充的无意义数据以达到溢出的目的,接着是一个覆盖RET的数据,紧接着是一段shellcode,那只要着个RET地址能指向这段shellcode的第一个指令,那函数返回时就能执行shellcode了。但是软件的不同版本和不同的运行环境都可能影响这段shellcode在内存中的位置,那么要构造这个RET是十分困难的。一般都在RET和shellcode之间填充大量的NOP指令,使得exploit有更强的通用性。
 
 
 ├———————┤<—低端内存区域
 │ …… │
 ├———————┤<—由exploit填入数据的开始
 │ │
 │ buffer │<—填入无用的数据
 │ │
 ├———————┤
 │ RET │<—指向shellcode,或NOP指令的范围
 ├———————┤
 │ NOP │
 │ …… │<—填入的NOP指令,是RET可指向的范围
 │ NOP │
 ├———————┤
 │ │
 │ shellcode │
 │ │
 ├———————┤<—由exploit填入数据的结束
 │ …… │
 ├———————┤<—高端内存区域
 
 
 windows下的动态数据除了可存放在栈中,还可以存放在堆中。了解C++的朋友都知道,C++可以使用new关键字来动态分配内存。来看下面的C++代码:
 
 #include <stdio.h>
 #include
 #include <windows.h>
 
 void func()
 {
 char *buffer=new char[128];
 char bufflocal[128];
 static char buffstatic[128];
 printf("0x%08x\n",buffer); //打印堆中变量的内存地址
 printf("0x%08x\n",bufflocal); //打印本地变量的内存地址
 printf("0x%08x\n",buffstatic); //打印静态变量的内存地址
 }
 
 void main()
 {
 func();
 return;
 }
 
 程序执行结果为:
 
 0x004107d0
 0x0012ff04
 0x004068c0
 
 可以发现用new关键字分配的内存即不在栈中,也不在静态数据区。VC编译器是通过windows下的“堆(heap)”来实现new关键字的内存动态分配。在讲“堆”之前,先来了解一下和“堆”有关的几个API函数:
 
 HeapAlloc 在堆中申请内存空间
 HeapCreate 创建一个新的堆对象
 HeapDestroy 销毁一个堆对象
 HeapFree 释放申请的内存
 HeapWalk 枚举堆对象的所有内存块
 GetProcessHeap 取得进程的默认堆对象
 GetProcessHeaps 取得进程所有的堆对象
 LocalAlloc
 GlobalAlloc
 
 当进程初始化时,系统会自动为进程创建一个默认堆,这个堆默认所占内存的大小为1M。堆对象由系统进行管理,它在内存中以链式结构存在。通过下面的代码可以通过堆动态申请内存空间:
 
 HANDLE hHeap=GetProcessHeap();
 char *buff=HeapAlloc(hHeap,0,8);
 
 其中hHeap是堆对象的句柄,buff是指向申请的内存空间的地址。那这个hHeap究竟是什么呢?它的值有什么意义吗?看看下面这段代码吧:
 
 #pragma comment(linker,"/entry:main") //定义程序的入口
 #include <windows.h>
 
 _CRTIMP int (__cdecl *printf)(const char *, ...); //定义STL函数printf
 /*---------------------------------------------------------------------------
 写到这里,我们顺便来复习一下前面所讲的知识:
 (*注)printf函数是C语言的标准函数库中函数,VC的标准函数库由msvcrt.dll模块实现。
 由函数定义可见,printf的参数个数是可变的,函数内部无法预先知道调用者压入的参数个数,函数只能通过分析第一个参数字符串的格式来获得压入参数的信息,由于这里参数的个数是动态的,所以必须由调用者来平衡堆栈,这里便使用了__cdecl调用规则。BTW,Windows系统的API函数基本上是__stdcall调用形式,只有一个API例外,那就是wsprintf,它使用__cdecl调用规则,同printf函数一样,这是由于它的参数个数是可变的缘故。
 ---------------------------------------------------------------------------*/
 void main()
 {
 HANDLE hHeap=GetProcessHeap();
 char *buff=HeapAlloc(hHeap,0,0x10);
 char *buff2=HeapAlloc(hHeap,0,0x10);
 HMODULE hMsvcrt=LoadLibrary("msvcrt.dll");
 printf=(void *)GetProcAddress(hMsvcrt,"printf");
 printf("0x%08x\n",hHeap);
 printf("0x%08x\n",buff);
 printf("0x%08x\n\n",buff2);
 }
 
 执行结果为:
 
 0x00130000
 0x00133100
 0x00133118
 
 hHeap的值怎么和那个buff的值那么接近呢?其实hHeap这个句柄就是指向HEAP首部的地址。在进程的用户区存着一个叫PEB(进程环境块)的结构,这个结构中存放着一些有关进程的重要信息,其中在PEB首地址偏移0x18处存放的ProcessHeap就是进程默认堆的地址,而偏移0x90处存放了指向进程所有堆的地址列表的指针。windows有很多API都使用进程的默认堆来存放动态数据,如windows 2000下的所有ANSI版本的函数都是在默认堆中申请内存来转换ANSI字符串到Unicode字符串的。对一个堆的访问是顺序进行的,同一时刻只能有一个线程访问堆中的数据,当多个线程同时有访问要求时,只能排队等待,这样便造成程序执行效率下降。
 
 最后来说说内存中的数据对齐。所位数据对齐,是指数据所在的内存地址必须是该数据长度的整数倍,DWORD数据的内存起始地址能被4除尽,WORD数据的内存起始地址能被2除尽,x86 CPU能直接访问对齐的数据,当他试图访问一个未对齐的数据时,会在内部进行一系列的调整,这些调整对于程序来说是透明的,但是会降低运行速度,所以编译器在编译程序时会尽量保证数据对齐。同样一段代码,我们来看看用VC、Dev-C++和lcc三个不同编译器编译出来的程序的执行结果:
 
 #include <stdio.h>
 
 int main()
 {
 int a;
 char b;
 int c;
 printf("0x%08x\n",&a);
 printf("0x%08x\n",&b);
 printf("0x%08x\n",&c);
 return 0;
 }
 
 这是用VC编译后的执行结果:
 0x0012ff7c
 0x0012ff7b
 0x0012ff80
 变量在内存中的顺序:b(1字节)-a(4字节)-c(4字节)。
 
 这是用Dev-C++编译后的执行结果:
 0x0022ff7c
 0x0022ff7b
 0x0022ff74
 变量在内存中的顺序:c(4字节)-中间相隔3字节-b(占1字节)-a(4字节)。
 
 这是用lcc编译后的执行结果:
 0x0012ff6c
 0x0012ff6b
 0x0012ff64
 变量在内存中的顺序:同上。
 
 三个编译器都做到了数据对齐,但是后两个编译器显然没VC“聪明”,让一个char占了4字节,浪费内存哦。
 
 
 基础知识:
 堆栈是一种简单的数据结构,是一种只允许在其一端进行插入或删除的线性表。允许插入或删除操作的一端称为栈顶,另一端称为栈底,对堆栈的插入和删除操作被称为入栈和出栈。有一组CPU指令可以实现对进程的内存实现堆栈访问。其中,POP指令实现出栈操作,PUSH指令实现入栈操作。CPU的ESP寄存器存放当前线程的栈顶指针,EBP寄存器中保存当前线程的栈底指针。CPU的EIP寄存器存放下一个CPU指令存放的内存地址,当CPU执行完当前的指令后,从EIP寄存器中读取下一条指令的内存地址,然后继续执行。
 
 
 参考:《Windows下的HEAP溢出及其利用》by: isno
              《windows核心编程》by: Jeffrey Richter
posted @ 2006-07-02 20:57 Jerry Cat 阅读(291) | 评论 (0)编辑 收藏

/********************************************\
|    欢迎转载, 但请保留作者姓名和原文链接, 祝您进步并共勉!     |
\********************************************/


c语言中的类型转换与复合类型

作者: Jerry Cat
时间: 2006/07/01
链接: http://www.cppblog.com/jerysun0818/archive/2006/07/01/9274.html

数据类型转换是C语言中颇具争议的一个话题,这里不多加评论,单就其中整形与浮点型之间的转换做一些解说. 
由于表示范围的原因,你可能认为把整型数转换为浮点型一定是安全的,但实际上不是这么简单。因为浮点型存储的数值虽然大但却受精度的限制。
如unsigned int u=4294967295;
float f=u;
接过f变成了4294967296.000000
所以要把一个整形换成float在转换回来还要和原先的数相同,则这个数只能有6位有效数字。否则会有精度损失。而要把浮点换成整形,首先可以肯定小数部分被舍掉了。另外还要注意,转换的第一步必须是以下的一种类型:
int     unsigned     long     unsigned long     long long     unsigned long long  
如:
float f=12345.678;
int i=f;
short s=i;
否则直接转换到short 得到的就根本不是12345了。(与平台有关,windows不存在这个问题)

对于复合类型,主要是要注意由于数据对齐要求而导致的存储空间浪费。这里举一个例子:
struct s
{
    char x;
    int y;
    char z;
    int u;
};             /*s占16个字节*/
struct s
{
    int y;    /*4*/
    int u;    /*4*/
    char x;    /*1*/
    char z;    /*3*/
};             /*s占12个字节*/
注意这里第二个定义中为什么不是10,这还是由于数据对齐的原因,因为不能只考虑单个变量的情况,还有可能是结构体数组变量,struct s array[10],知道原因了吧。另外一种可能就是在函数调用中,结构体变量作为一个参数要压栈,是以4字节为一个单元压栈的。

posted @ 2006-07-01 18:49 Jerry Cat 阅读(742) | 评论 (1)编辑 收藏
仅列出标题
共14页: First 4 5 6 7 8 9 10 11 12 Last 

<2006年5月>
30123456
78910111213
14151617181920
21222324252627
28293031123
45678910

常用链接

留言簿(7)

随笔档案

最新随笔

搜索

  •  

最新评论

阅读排行榜

评论排行榜