• <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>
            asm, c, c++ are my all
            -- Core In Computer
            posts - 139,  comments - 123,  trackbacks - 0

            /********************************************\
            |????歡迎轉(zhuǎn)載, 但請(qǐng)保留作者姓名和原文鏈接, 祝您進(jìn)步并共勉!???? |
            \********************************************/


            連綿不斷的析取流

            作者: Jerry Cat
            時(shí)間: 2006/04/24
            鏈接: http://www.shnenglu.com/jerysun0818/archive/2006/04/25/6214.html


            /*
            精巧的ostream和<<機(jī)制, 不僅具有面向?qū)ο蟮亩嘀乩^承和重載, 且性能不輸C的IO庫函數(shù)

            cout, 表示標(biāo)準(zhǔn)輸出(standard output)的ostream類對(duì)象.cout使我們可以向設(shè)備輸出或者寫數(shù)據(jù).
            輸出主要由重載的析取操作符(<<)來完成, 輸入主要由重載的插入操作符(>>)完成:

            >>a表示將數(shù)據(jù)放入a對(duì)象中.
            <<a表示將a對(duì)象中存儲(chǔ)的數(shù)據(jù)拿出到流中, 最終匯入流對(duì)象ostream.
            */

            e.g.: cout <<"Destroying..." <<i <<endl;

            //連綿不斷的析取流, 下面是其中ostream成員函數(shù)<<析取符函數(shù)重載的一個(gè)實(shí)現(xiàn)
            //函數(shù)指針_f代表符合"該函數(shù)指針參數(shù)類型,返回值類型和調(diào)用規(guī)范類型的"某些C++標(biāo)準(zhǔn)例程比如endl的偏移地址
            inline ostream& ostream::operator<<(ostream& (__cdecl * _f)(ostream&))
            {?????????????????????
            ??? (*_f)(*this); //此處的*this是ostream對(duì)象之引用,即當(dāng)前流對(duì)象之引用ostream&
            ??? return *this; //返回當(dāng)前流對(duì)象之引用
            }

            posted @ 2006-04-25 03:54 Jerry Cat 閱讀(568) | 評(píng)論 (0)編輯 收藏

            /********************************************\
            |????歡迎轉(zhuǎn)載, 但請(qǐng)保留作者姓名和原文鏈接, 祝您進(jìn)步并共勉!???? |
            \********************************************/

            C++對(duì)象模型(3) - An Object Distinction
            ?
            作者: Jerry Cat
            時(shí)間: 2006/04/23
            鏈接: http://www.shnenglu.com/jerysun0818/archive/2006/04/24/6114.html


            1.3 An Object Distinction
            -------------------------
            intercede in a and b:在a和b間進(jìn)行調(diào)解
            The most common inadvertent mixing of idioms occurs when a concrete instance of a base class, such as

            Library_materials thing1;
            is used to program some aspect of polymorphism:

            // class Book : public Library_materials { ...};
            Book book;

            // Oops: thing1 is not a Book!
            // Rather, book is "sliceD" — thing1就是個(gè)只保留book的上半身的殘廢東西
            // thing1 remains a Library_materials

            thing1 = book;

            // Oops: invokes
            // Library_materials::check_in()
            thing1.check_in();
            rather than a pointer or reference of the base class:

            // OK: thing2 now references book, 因?yàn)榛惡团缮惖牟季质?基部重合在一起的", 派生類還是超集哩!
            // 基類在"上"(低址處), 派生類多出的部分緊接著"連"在下面; 引用(本質(zhì)上是指針)和指針對(duì)這兩種數(shù)據(jù)類型
            // 有類似匯編中word ptr 和 dword ptr的關(guān)系, 它倆的首址是相同的. 編譯器會(huì)自動(dòng)鑒別基類和子類從而調(diào)整
            // 類似word ptr 和 dword ptr的這種類的"類型尋址"操作
            // 而且Scott Meyer說過它們是一種"is a"的關(guān)系:"The derived is a base class"
            // 向上(基類方向)轉(zhuǎn)換沒問題的, 向下轉(zhuǎn)換一般不可 - 簡(jiǎn)直"無中生有"嘛! 但MFC中對(duì)動(dòng)態(tài)類對(duì)象CDerived(用
            // DECLARE_DYNCREATE宏 和 IMPLEMENT_DYNCREATE宏在程序運(yùn)行時(shí)而非編譯動(dòng)態(tài)生成)倒可用DYNAMIC_DOWNCAST
            // 宏來完成將指向CBase的指針Downcast成指向它:
            // CDerived * pDerived = DYNAMIC_DOWNCAST(CDerived, pBase); //CBase *pBase;
            // 原型為DYNAMIC_DOWNCAST( class, pointer )

            Library_materials &thing2 = book;//本質(zhì)是地址,用起來象對(duì)象! 對(duì)象別名也,從這角度就是對(duì)象了嘛^_^

            // OK: invokes Book::check_in()
            thing2.check_in();

            只有指針和引用才能"救多態(tài)"!
            Although you can manipulate a base class object of an inheritance hierarchy either directly or indirectly, only the indirect manipulation of the object through a pointer or reference supports the polymorphism necessary for OO programming. The definition and use of thing2 in the previous example is a well-behaved instance of the OO paradigm. The definition and use of thing1 falls outside the OO idiom; it reflects a well-behaved instance of the ADT paradigm. Whether the behavior of thing1 is good or bad depends on what the programmer intended. In this example, its behavior is very likely a surprise.

            // represent objects: uncertain type
            Library_materials *px = retrieve_some_material();
            Library_materials &rx = *px;

            // represents datum: no surprise
            Library_materials dx = *px;
            it can never be said with certainty what the actual type of the object is that px or rx addresses. It can only be said that it is either a Library_materials object or a subtype rooted by Library_materials class. dx, however, is and can only be an object of the Library_materials class. Later in this section, I discuss why this behavior, although perhaps unexpected, is well behaved.

            Although the polymorphic manipulation of an object requires that the object be accessed either through a pointer or a reference, the manipulation of a pointer or reference in C++ does not in itself necessarily result in polymorphism! For example, consider

            // no polymorphism
            int *pi;

            // no language supported polymorphism
            void *pvi;

            // ok: class x serves as a base class
            x *px;
            多態(tài)只存在于
            In C++, polymorphism exists only within individual public class hierarchies. px, for example, may address either an object of its own type or a type publicly derived from it (not considering ill-behaved casts). Nonpublic derivation and pointers of type void* can be spoken of as polymorphic, but they are without explicit language support; that is, they must be managed by the programmer through explicit casts. (One might say that they are not first-class polymorphic objects.)

            The C++ language supports polymorphism in the following ways:
            1. Through a set of implicit conversions, such as the conversion of a derived class pointer to a pointer of its public base type:
            shape *ps = new circle();

            2. Through the virtual function mechanism:
            ps->rotate();

            3. Through the dynamic_cast and typeid operators:
            if ( circle *pc = dynamic_cast< circle* >( ps )) ...//象MFC中DYNAMIC_DOWNCAST和DECLARE_DYNCREATE,
            //IMPLEMENT_DYNCREATE, IsKindOf(RUNTIME_CLASS(class))的組合拳

            // example for CObject::IsKindOf
            /* BOOL IsKindOf( const CRuntimeClass* pClass ) const; */
            CAge a(21); // Must use IMPLEMENT_DYNAMIC or IMPLEMENT_SERIAL
            ASSERT( a.IsKindOf( RUNTIME_CLASS( CAge ) ) );
            ASSERT( a.IsKindOf( RUNTIME_CLASS( CObject ) ) );

            // example for RUNTIME_CLASS
            /* RUNTIME_CLASS( class_name ) */
            Use this macro to get the run-time class structure from the name of a C++ class.

            RUNTIME_CLASS returns a pointer to a CRuntimeClass structure for the class specified by class_name. Only CObject-derived classes declared with DECLARE_DYNAMIC, DECLARE_DYNCREATE, or DECLARE_SERIAL will return pointers to a CRuntimeClass structure.

            CRuntimeClass* prt = RUNTIME_CLASS( CAge );
            ASSERT( lstrcmp( prt->m_lpszClassName, "CAge" )? == 0 );

            =-=-=-=-=-=-=-=-=-==-=-=-=-=-=-=-=-=-==-=-=-=-=-=-=-=-=-=
            The memory requirements to represent a class object in general are the following:

            1.) The accumulated size of its nonstatic data members
            2.) Plus any padding (between members or on the aggregate boundary itself) due to alignment constraints (or simple efficiency)
            3.) Plus any internally generated overhead to support the virtuals

            The memory requirement to represent a pointer, [2] however, is a fixed size regardless of the type it addresses. For example, given the following declaration of a ZooAnimal class:

            ? [2]Or to represent a reference; internally, a reference is generally implemented as a pointer and the object syntax transformed into the indirection required of a pointer.
            class ZooAnimal {
            public:
            ?? ZooAnimal();
            ?? virtual ~ZooAnimal();

            ?? // ...

            ?? virtual void rotate();
            protected:
            ?? int loc;
            ?? String name;
            };

            ZooAnimal za( "Zoey" );
            ZooAnimal *pza = &za;

            a likely layout of the class object za and the pointer pza is pictured in Figure 1.4. (I return to the layout of data members in Chapter 3.)

            Figure 1.4. Layout of Object and Pointer of Independent Class


            layout1.GIF

            The Type of a Pointer:
            =-=-=-=-=-=-=-=-=-=-=
            But how, then, does a pointer to a ZooAnimal differ from, say, a pointer to an integer or a pointer to a template Array instantiated with a String?

            ZooAnimal *px;
            int *pi
            Array< String > *pta;
            In terms of memory requirements, there is generally no difference: all three need to be allocated sufficient memory to hold a machine address (usually a machine word). So the difference between pointers to different types rests neither in the representation of the pointer nor in the values (addresses) the pointers may hold. The difference lies in the type of object being addressed. That is, the type of a pointer instructs the compiler as to how to interpret the memory found at a particular address and also just how much memory that interpretation should span:

            An integer pointer addressing memory location 1000 on a 32-bit machine spans the address space 1000—1003.

            The ZooAnimal pointer, if we presume a conventional 8-byte String (a 4-byte character pointer and an integer to hold the string length), spans the address space 1000—1015.

            Hmm. Just out of curiosity, what address space does a void* pointer that holds memory location 1000 span? That's right, we don't know. That's why a pointer of type void* can only hold an address and not actually operate on the object it addresses.

            So a cast in general is a kind of compiler directive. In most cases, it does not alter the actual address a pointer contains. Rather, it alters only the interpretation of the size and composition of the memory being addressed.

            Adding Polymorphism
            =-=-=-=-=-=-=-=-=-=
            Now, let's define a Bear as a kind of ZooAnimal. This is done, of course, through public inheritance:

            class Bear : public ZooAnimal {
            public:
            ?? Bear();
            ?? ~Bear();
            ?? // ...
            ?? void rotate();
            ?? virtual void dance();
            ?? // ...
            protected:
            ?? enum Dances { ... };

            ?? Dances dances_known;
            ?? int cell_block;
            };

            Bear b( "Yogi" );
            Bear *pb = &b;
            Bear &rb = *pb;
            What can we say about the memory requirements of b, pb, and rb? Both the pointer and reference require a single word of storage (4 bytes on a 32-bit processor). The Bear object itself, however, requires 24 bytes (the size of a ZooAnimal [16 bytes] plus the 8 bytes Bear introduces). A likely memory layout is pictured in Figure 1.5.

            Figure 1.5. Layout of Object and Pointer of Derived Class

            layout2.GIF

            Okay, given that our Bear object is situated at memory location 1000, what are the real differences between a Bear and ZooAnimal pointer?

            Bear b;
            ZooAnimal *pz = &b;
            Bear *pb = &b;
            Each addresses the same first byte of the Bear object. The difference is that the address span of pb encompasses the entire Bear object, while the span of pz encompasses only the ZooAnimal subobject of Bear.

            pz cannot directly access any members other than those present within the ZooAnimal subobject, except through the virtual mechanism:

            // illegal: cell_block not a member
            // of ZooAnimal, although we ``know''
            // pz currently addresses a Bear object
            pz->cell_block;
            // okay: an explicit downcast
            (( Bear* )pz)->cell_block;

            // better: but a run-time operation
            if ( Bear* pb2 = dynamic_cast< Bear* >( pz ))
            ?? pb2->cell_block;

            // ok: cell_block a member of Bear
            pb->cell_block;
            When we write

            pz->rotate();
            the type of pz determines the following at compile time:

            The fixed, available interface (that is, pz may invoke only the ZooAnimal public interface)

            The access level of that interface (for example, rotate() is a public member of ZooAnimal)

            The type of the object that pz addresses at each point of execution determines the instance of rotate() invoked. The encapsulation of the type information is maintained not in pz but in the link between the object's vptr and the virtual table the vptr addresses (see Section 4.2 for a full discussion of virtual functions).
            So, then, why is it that, given

            Bear b;
            ZooAnimal za = b;

            // ZooAnimal::rotate() invoked
            za.rotate();
            the instance of rotate() invoked is the ZooAnimal instance and not that of Bear? Moreover, if memberwise initialization copies the values of one object to another, why is za's vptr not addressing Bear's virtual table?

            The answer to the second question is that the compiler intercedes in the initialization and assignment of one class object with another. The compiler must ensure that if an object contains one or more vptrs, those vptr values are not initialized or changed by the source object .
            子類是基類, 基類非子類. 兒子是老子(生的), 老子非兒子(生的).
            The answer to the first question is that za is not (and can never be) a Bear; it is (and can never be anything but) a ZooAnimal. Polymorphism, the potential to be of more than one type, is not physically possible in directly accessed objects. Paradoxically, direct object manipulation is not supported under OO programming. For example, given the following set of definitions:
            {
            ?? ZooAnimal za;
            ?? ZooAnimal *pza;

            ?? Bear b;
            ?? Panda *pp = new Panda;

            ?? pza = &b;
            }
            one possible memory layout is pictured in Figure 1.6.

            Figure 1.6. Memory Layout of Sequence of Definitions

            layout3.GIF

            Assigning pz the address of either za, b, or that contained by pp is obviously not a problem. A pointer and a reference support polymorphism because they do not involve any type-dependent commitment of resources. Rather, all that is altered is the interpretation of the size and composition of the memory they address.

            Any attempt to alter the actual size of the object za, however, violates the contracted resource requirements of its definition. Assign the entire Bear object to za and the object overflows its allocated memory. As a result, the executable is, literally, corrupted, although the corruption may not manifest itself as a core dump.

            When a base class object is directly initialized or assigned with a derived class object, the derived object is sliced to fit into the available memory resources of the base type. There is nothing of the derived type remaining. Polymorphism is not present, and an observant compiler can resolve an invocation of a virtual function through the object at compile time, thus by-passing the virtual mechanism. This can be a significant performance win if the virtual function is defined as inline.
            多態(tài)是面向?qū)ο驩O的實(shí)質(zhì)
            To summarize, polymorphism is a powerful design mechanism that allows for the encapsulation of related types behind an abstract public interface, such as our Library_materials hierarchy. The cost is an additional level of indirection, both in terms of memory acquisition and type resolution. C++ supports polymorphism through class pointers and references. This style of programming is called object-oriented.
            ADT抽象數(shù)據(jù)類型是基于對(duì)象OB
            C++ also supports a concrete ADT style of programming now called object-based (OB)—nonpolymorphic data types, such as a String class. A String class exhibits a nonpolymorphic form of encapsulation; it provides a public interface and private implementation (both of state and algorithm) but does not support type extension. An OB design can be faster and more compact than an equivalent OO design. Faster because all function invocations are resolved at compile time and object construction need not set up the virtual mechanism, and more compact because each class object need not carry the additional overhead traditionally associated with the support of the virtual mechanism. However, an OB design also is less flexible.

            posted @ 2006-04-24 03:45 Jerry Cat 閱讀(695) | 評(píng)論 (0)編輯 收藏

            [轉(zhuǎn)]AT&T x86 asm 語法

            創(chuàng)建時(shí)間:2001-04-09
            文章屬性:翻譯

            DJGPP 使用AT&T格式的匯編語法。和一般的intel格式的語法有點(diǎn)不同。主要不同點(diǎn)如下:

            AT&T 語法顛倒了源和目的操作數(shù)的位置, 目的操作數(shù)在源操作數(shù)之后。寄存器操作數(shù)要有個(gè)%的前綴,? 立即數(shù)操作數(shù)要有個(gè)$符號(hào)的前綴。存

            儲(chǔ)器操作數(shù)的大小取決于操作碼的最后一個(gè)字符。 它們是b (8-bit), w (16-bit), 和 l (32-bit).
            這里有一些例子。 左邊部分是intel指令格式,右邊是at&t格式。
            ??? movw %bx, %ax??????? // mov ax, bx
            ??? xorl %eax, %eax??????? // xor eax, eax
            ??? movw $1, %ax??????? // mov ax,1
            ??? movb X, %ah??????? // mov ah, byte ptr X
            ??? movw X, %ax??????? // mov ax, word ptr X
            ??? movl X, %eax??????? // mov eax, X
            大部分操作指令,at%t和intel都是差不多的,除了這些:
            ??? movsSD???????????? // movsx
            ??? movzSD???????????? // movz

            S和D分辨代表源和目的操作數(shù)后綴。
            ??? movswl %ax, %ecx??? // movsx ecx, ax
            ??? cbtw??????????????? // cbw
            ??? cwtl??????????????? // cwde
            ??? cwtd??????????????? // cwd
            ??? cltd??????????????? // cdq
            ??? lcall $S,$O???????? // call far S:O
            ??? ljmp $S,$O????????? // jump far S:O
            ??? lret $V???????????? // ret far V
            操作嘛前綴不能與他們作用的指令寫在同一行。 例如, rep 和stosd應(yīng)該是兩個(gè)相互獨(dú)立的指令, 存儲(chǔ)器的情況也有一點(diǎn)不同。通常intel格

            式的如下:

            section:[base + index*scale + disp]

            被寫成:

            section:disp(base, index, scale)

            這里有些例子:

            ??? movl 4(%ebp), %eax??????????????? // mov eax, [ebp+4])
            ??? addl (%eax,%eax,4), %ecx????????? // add ecx, [eax + eax*4])
            ??? movb $4, %fs:(%eax)?????????????? // mov fs:eax, 4)
            ??? movl _array(,%eax,4), %eax??????? // mov eax, [4*eax + array])
            ??? movw _array(%ebx,%eax,4), %cx??? // mov cx, [ebx + 4*eax + array])

            Jump 指令通常是個(gè)短跳轉(zhuǎn)。 可是, 下面這些指令都是只能在一個(gè)字節(jié)的范圍內(nèi)跳轉(zhuǎn): jcxz, jecxz, loop, loopz, loope, loopnz 和loopne

            。象在線文檔所說的那樣,一個(gè)jcxz foo可以擴(kuò)展成以下工作:
            ??? jcxz cx_zero
            ??? jmp cx_nonzero
            cx_zero:
            ??? jmp foo
            cx_nonzero:
            文檔也注意到了mul和imul指令。 擴(kuò)展的乘法指令只用一個(gè)操作數(shù),例如, imul $ebx, $ebx將不會(huì)把結(jié)果放入edx:eax。使用imul %ebx中的

            單操作數(shù)來獲得擴(kuò)展結(jié)果。


            --------------------------------------------------------------------------------

            Inline Asm
            我將首先開始inline asm, 因?yàn)樗坪蹶P(guān)于這方面的疑問非常多。這是最基本的語法了, 就象在線幫助信息中描述的:
            __asm__(asm statements : outputs : inputs : registers-modified);

            這四個(gè)字段的含義是:

            asm statements - AT&T 的結(jié)構(gòu), 每新行都是分開的。
            outputs - 修飾符一定要用引號(hào)引起來, 用逗號(hào)分隔
            inputs - 修飾符一定要用引號(hào)引起來, 用逗號(hào)分隔
            registers-modified - 名字用逗號(hào)分隔
            一個(gè)小小的例子:
            ??? __asm__("
            ??????? pushl %eax\n
            ??????? movl $1, %eax\n
            ??????? popl %eax"
            ??? );
            假如你不用到特別的輸入輸出變量或者修改任何寄存器的值,一般來說是不會(huì)使用到其他的三個(gè)字段的,
            讓我們來分析一下輸入變量。

            ??? int i = 0;

            ??? __asm__("
            ??????? pushl %%eax\n
            ??????? movl %0, %%eax\n
            ??????? addl $1, %%eax\n
            ??????? movl %%eax, %0\n
            ??????? popl %%eax"
            ??? :
            ??? : "g" (i)
            ??? );??? // increment i
            不要為上面的代碼所困擾! 我將盡力來解釋它。我們想讓輸入變量i加1,我們沒有任何輸出變量, 也沒有改變寄存器值(我們保存了eax值)。

            因此,第二個(gè)和最后一個(gè)字段是空的。 因?yàn)橹付溯斎胱侄? 我們?nèi)孕枰A粢粋€(gè)空的輸出字段, 但是沒有最后一個(gè)字段, 因?yàn)樗鼪]被使用

            。在兩個(gè)空冒號(hào)之間留下一個(gè)新行或者至少一個(gè)空格。

            下面讓我們來看看輸入字段。 附加描述符可以修正指令來讓你給定的編譯器來正確處理這些變量。他們一般被附上雙引號(hào)。那么這個(gè)"g"是用

            來做什么的呢?? 只要是合法的匯編指令,"g"就讓編譯器決定該在哪里加載i的值。一般來說,你的大部分輸入變量都可以被賦予 "g", 讓編

            譯器決定如何去加載它們 (gcc甚至可以優(yōu)化它們!)。 其他描述符使用"r" (加載到任何可用的寄存器去), "a" (ax/eax), "b" (bx/ebx),

            "c" (cx/ecx), "d" (dx/edx), "D" (di/edi), "S" (si/esi), 等等。

            我們將要提到一個(gè)在asm代碼里面的如%0的輸入變量。如果我們有兩個(gè)輸入, 他們會(huì)一個(gè)是%0一個(gè)是%1, 在輸入段里按順序排列 (如下一個(gè)例

            子)。假如N個(gè)輸入變量且沒有輸出變量, 從%0 到%N-1將和輸入字段里的變量相對(duì)應(yīng), 按順序排列。

            如果任何的輸入, 輸出, 寄存器修改字段被使用, 匯編代碼里的寄存器名必須用兩個(gè)%來代替一個(gè)%。對(duì)應(yīng)于第一個(gè)沒有使用最后三個(gè)字段的例

            子。

            讓我們看看兩個(gè)輸入變量且引入了"volatile"的例子:

            ??? int i=0, j=1;
            ??? __asm__ __volatile__("
            ??????? pushl %%eax\n
            ??????? movl %0, %%eax\n
            ??????? addl %1, %%eax\n
            ??????? movl %%eax, %0\n
            ??????? popl %%eax"
            ??? :
            ??? : "g" (i), "g" (j)
            ??? );??? // increment i by j
            Okay, 現(xiàn)在我們已經(jīng)有了兩個(gè)輸入變量了。沒問題了, 我們只需要記住%0對(duì)應(yīng)第一個(gè)輸入變量(在這個(gè)例子中是i), %1對(duì)應(yīng)在i后面的列出的j


            Oh yeah, 這個(gè)volatile到底是什么意思呢? 它防止你的編譯器修改你的匯編代碼,就是不進(jìn)行優(yōu)化(紀(jì)錄, 刪除, 結(jié)合,等等優(yōu)化手段。), 不

            改變代碼原樣來匯編它們。建議一般情況下使用volatile選項(xiàng)。

            讓我們來看看輸出字段:

            ??? int i=0;
            ??? __asm__ __volatile__("
            ??????? pushl %%eax\n
            ??????? movl $1, %%eax\n
            ??????? movl %%eax, %0\n
            ??????? popl %%eax"
            ??? : "=g" (i)
            ??? );??? // assign 1 to i
            這看起來非常象我們前面提到的輸入字段的例子; 確實(shí)也沒有很大的不同。所有的輸出修飾符前面都應(yīng)該加上=字符,他們同樣在匯編代碼里

            面用%0到%N-1來表示, 在輸出字段按順序排列。你一定會(huì)問如果同時(shí)有輸入和輸出字段會(huì)怎么排序的呢? 好,下面一個(gè)例子就是讓大家知道

            如何同時(shí)處理輸入輸出字段的。
            ??? int i=0, j=1, k=0;
            ??? __asm__ __volatile__("
            ??????? pushl %%eax\n
            ??????? movl %1, %%eax\n
            ??????? addl %2, %%eax\n
            ??????? movl %%eax, %0\n
            ??????? popl %%eax"
            ??? : "=g" (k)
            ??? : "g" (i), "g" (j)
            ??? );??? // k = i + j
            Okay, 唯一個(gè)不清楚的地方就是匯編代碼中的變量的個(gè)數(shù)。我馬上來解釋一下。
            當(dāng)同時(shí)使用輸入字段和輸出字段的時(shí)候:

            %0 ... %K 是輸出變量

            %K+1 ... %N 是輸入變量

            在我們的例子中, %0 對(duì)應(yīng)k, %1 對(duì)應(yīng)i, %2對(duì)應(yīng)j。很簡(jiǎn)單,是吧?

            到現(xiàn)在為止我們都沒有使用最后一個(gè)字段(registers-modified)。如果我們要在我們的匯編代碼里使用任何寄存器, 我們要明確的用push和

            pop指令來保存它們, 或者列到最后一個(gè)字段里面讓gcc來處理它們。

            這是前面的一個(gè)例子, 沒有明確的保留和存貯eax。

            ??? int i=0, j=1, k=0;
            ??? __asm__ __volatile__("
            ??????? pushl %%eax\n??? /*譯者注:好像原文說的有點(diǎn)問題,明明是保存了eax的值,:(*/
            ??????? movl %1, %%eax\n
            ??????? addl %2, %%eax\n
            ??????? movl %%eax, %0\n
            ??????? popl %%eax"
            ??? : "=g" (k)
            ??? : "g" (i), "g" (j)
            ??? : "ax", "memory"
            ??? );??? // k = i + j
            我們讓gcc來保存和存貯eax, 如果必要的話。一個(gè)16-bit寄存器名代表了32-, 16-或8-bit寄存器。 如果我們要改寫內(nèi)存 (寫入一個(gè)變量等。

            ), 建議在register-modified字段里面來指定"memroy"修飾符。這意味著除了第一個(gè)例子我們都應(yīng)該加上這個(gè)修飾符, 但是直到現(xiàn)在我才提出

            來, 是為了更簡(jiǎn)單易懂。

            在你的內(nèi)聯(lián)匯編里面定位標(biāo)號(hào)應(yīng)該使用b或f來作為終止符, 尤其是向后向前的跳轉(zhuǎn)。(譯者注:b代表向后跳轉(zhuǎn),f代表向前跳轉(zhuǎn))

            For example,

            ??? __asm__ __volatile__("
            ??????? 0:\n
            ??????????? ...
            ??????????? jmp 0b\n
            ??????????? ...
            ??????????? jmp 1f\n
            ??????????? ...
            ??????? 1:\n
            ??????????? ...
            ??? );
            這里有個(gè)用c代碼和內(nèi)聯(lián)匯編代碼混合寫的跳轉(zhuǎn)程序的例子(thanks to Srikanth B.R for this tip).

            void MyFunction( int x, int y )
            {
            ??? __asm__( "Start:" );
            ??? __asm__( ...do some comparison... );
            ??? __asm__( "jl Label_1" );

            ??? CallFunction( &x, &y );????
            ??? __asm__("jmp Start");

            Label_1:
            ??? return;
            }

            --------------------------------------------------------------------------------

            External Asm
            Blah... Okay fine. Here's a clue: Get some of your C/C++ files, 且用gcc -S file.c來編譯。 然后查看file.S文件。基本結(jié)構(gòu)如下:
            ??? .file "myasm.S"

            ??? .data
            ??? somedata: .word 0
            ??? ...

            ??? .text
            ??? .globl __myasmfunc
            ??? __myasmfunc:
            ??? ...
            ??? ret
            Macros, macros! 頭文件libc/asmdefs.h便于你寫asm。 在你的匯編代碼最前面包含此頭文件然后就可以使用宏了。一個(gè)例子: myasm.S:
            ??? #include <libc/asmdefs.h>

            ??? .file "myasm.S"

            ??? .data
            ??? .align 2
            ??? somedata: .word? 0
            ??? ...

            ??? .text
            ??? .align 4
            ??? FUNC(__MyExternalAsmFunc)
            ??? ENTER
            ??????????? movl?? ARG1, %eax
            ??????????? ...
            ??????????? jmp??? mylabel
            ??????????? ...
            ??????? mylabel:
            ??????????? ...
            ??? LEAVE
            這是一個(gè)好的純粹的匯編代碼框架

            posted @ 2006-04-23 17:53 Jerry Cat 閱讀(577) | 評(píng)論 (0)編輯 收藏

            /********************************************\
            |????歡迎轉(zhuǎn)載, 但請(qǐng)保留作者姓名和原文鏈接, 祝您進(jìn)步并共勉!???? |
            \********************************************/


            C與C++編程一頭一尾最重要, 無數(shù)英雄折腰, 多少豪杰翻船!

            作者: Jerry Cat
            時(shí)間: 2006/04/22
            鏈接: http://www.shnenglu.com/jerysun0818/archive/2006/04/22/6086.aspx


            #include <stdio.h>
            #include <stdlib.h>
            #include <string.h>

            //Fuction: BOOL revstr(char *str);
            //Purpose: reverse a string
            //Author:? Jerry
            //Time:???? 04/22/2006
            //Feature: This version is suitable for both sring and char array

            char* revstr(char *str)
            {
            ??? int nCnt = 0, len = strlen(str);
            ??? char* tmpstr = (char*) malloc(len+1);
            ??? if???? (tmpstr) strcpy(tmpstr, str);
            ??? else { printf("\n malloc error!\n"); return 0; }
            ??? for(--len, tmpstr = tmpstr + len; len > 0; *str++ = *tmpstr--, --len, ++nCnt);
            ??? *str = *tmpstr; //C/C++編程一頭一尾最重要, 無數(shù)英雄折腰, 多少豪杰翻船!
            ??? free(tmpstr);
            ??? return str - nCnt;
            }

            上面方法不好, 繁雜且易出錯(cuò), 經(jīng)沐楓兄指點(diǎn), 下面?zhèn)z是改進(jìn)版^_^
            char* revstr(char *str)
            {
            ??? char c, *head = str, *tail = str + strlen(str) -1;
            ??? for(; head < tail; c = *head, *head++ = *tail, *tail-- = c);
            ??? return str;
            }

            char* revstr(char *str)
            {?? //省去一變量, 時(shí)間換空間法
            ??? char *head = str, *tail = str + strlen(str) -1;
            ??? for(; head < tail; *head=*head ^ *tail, *tail=*head ^ *tail, *head=*head++ ^ *tail--);
            ??? return str;
            }
            ?

            posted @ 2006-04-22 22:20 Jerry Cat 閱讀(1129) | 評(píng)論 (7)編輯 收藏

            /********************************************\
            |????歡迎轉(zhuǎn)載, 但請(qǐng)保留作者姓名和原文鏈接, 祝您進(jìn)步并共勉!???? |
            \********************************************/


            Linux靜態(tài)、共享和動(dòng)態(tài)庫之編程

            作者: Jerry Cat
            時(shí)間: 2006/04/21
            鏈接: http://www.shnenglu.com/jerysun0818/archive/2006/04/22/6065.html

            一.庫的分類
            ??? 有兩種說法, 如果熟悉WIN平臺(tái)下的DLL, 相信不難理解:

            ??? 庫可以有三種使用的形式:靜態(tài)、共享和動(dòng)態(tài).靜態(tài)庫的代碼在編譯時(shí)就已連接到開發(fā)人員開發(fā)的應(yīng)用程序中, 而共享庫只是在程序開始運(yùn)行時(shí)才載入, 在編譯時(shí), 只是簡(jiǎn)單地指定需要使用的庫函數(shù).動(dòng)態(tài)庫則是共享庫的另一種變化形式.動(dòng)態(tài)庫也是在程序運(yùn)行時(shí)載入, 但與共享庫不同的是, 使用的庫函數(shù)不是在程序運(yùn)行開始, 而是在程序中的語句需要使用該函數(shù)時(shí)才載入.動(dòng)態(tài)庫可以在程序運(yùn)行期間釋放動(dòng)態(tài)庫所占用的內(nèi)存, 騰出空間供其它程序使用.由于共享庫和動(dòng)態(tài)庫并沒有在程序中包括庫函數(shù)的內(nèi)容, 只是包含了對(duì)庫函數(shù)的引用, 因此代碼的規(guī)模比較小.

            ??? Linux下的庫文件分為共享庫和靜態(tài)庫兩大類, 它們兩者的差別僅在程序執(zhí)行時(shí)所需的代碼是在運(yùn)行時(shí)動(dòng)態(tài)加載的, 還是在編譯時(shí)靜態(tài)加載的.區(qū)分庫類型最好的方法是看它們的文件后綴, 通常共享庫以.so(Shared Object的縮寫)結(jié)尾, 靜態(tài)鏈接庫通常以.a結(jié)尾(Archive的縮寫).在終端缺省情況下, 共享庫通常為綠色, 而靜態(tài)庫為黑色.

            ???? 已經(jīng)開發(fā)的大多數(shù)庫都采取共享庫的方式.ELF格式的可執(zhí)行文件使得共享庫能夠比較容易地實(shí)現(xiàn), 當(dāng)然使用舊的a.out模式也可以實(shí)現(xiàn)庫的共享.Linux系統(tǒng)中目前可執(zhí)行文件的標(biāo)準(zhǔn)格式為ELF格式.

              .a的是為了支持較老的a.out格式的可執(zhí)行文件的
              .so的是支持elf格式的可執(zhí)行文件的庫.

             ? .a是靜態(tài)庫文件, 可以用ar 命令生成.
              .so是動(dòng)態(tài)庫文件, 編譯時(shí)加上指定的選項(xiàng)即可生成, 具體選項(xiàng)看相應(yīng)的系統(tǒng)文檔了.

            二.庫的命名規(guī)則
            ??? GNU庫的使用必須遵守Library GNU Public License(LGPL許可協(xié)議).該協(xié)議與GNU許可協(xié)議略有不同, 開發(fā)人員可以免費(fèi)使用GNU庫進(jìn)行軟件開發(fā), 但必須保證向用戶提供所用的庫函數(shù)的源代碼.

              系統(tǒng)中可用的庫都存放在/usr/lib和/lib目錄中.庫文件名由前綴lib和庫名以及后綴組成.根據(jù)庫的類型不同, 后綴名也不一樣.共享庫的后綴名由.so和版本號(hào)組成, 靜態(tài)庫的后綴名為.a.采用舊的a.out格式的共享庫的后綴名為.sa.
              libname.so.major.minor
              libname.a

              這里的name可以是任何字符串, 用來唯一標(biāo)識(shí)某個(gè)庫.該字符串可以是一個(gè)單字、幾個(gè)字符、甚至一個(gè)字母.數(shù)學(xué)共享庫的庫名為libm.so.5, 這里的標(biāo)識(shí)字符為m, 版本號(hào)為5.libm.a則是靜態(tài)數(shù)學(xué)庫.X-Windows庫名為libX11.so.6, 這里使用X11作為庫的標(biāo)識(shí), 版本號(hào)為6.

            三.庫操作命令

            ?? Linux庫操作可以使用命令完成, 目前常用的命令是ldd和ldconfig.

            ?? 1.ldd
            ?ldd是Library Dependency Display縮寫, 它的作用是顯示一個(gè)可執(zhí)行程序必須使用的共享庫.

            ?$ ldd /usr/bin/mesg
            ?libc.so.6 => /lib/tls/i686/cmov/libc.so.6 (0xb7eaf000)
            ?/lib/ld-linux.so.2 => /lib/ld-linux.so.2 (0xb7feb000)

            ?? 2.ldconfig
            ?庫安裝到系統(tǒng)以后, 為了讓動(dòng)態(tài)鏈接庫為系統(tǒng)所認(rèn)識(shí)及共享, 就需要運(yùn)行l(wèi)dconfig.ldconfig命令的用途, 主要是在默認(rèn)搜尋目錄(/lib和/usr/lib)以及動(dòng)態(tài)庫配置文件/etc/ld.so.conf內(nèi)所列的目錄下, 搜索出可共享的動(dòng)態(tài)鏈接庫(格式如lib*.so*), 進(jìn)而創(chuàng)建出動(dòng)態(tài)裝入程序(ld.so)所需的連接和緩存文件.緩存文件默認(rèn)為/etc/ld.so.cache, 此文件保存已排好序的動(dòng)態(tài)鏈接庫名字列表, ldconfig通常在系統(tǒng)啟動(dòng)時(shí)運(yùn)行, 而當(dāng)用戶安裝了一個(gè)新的動(dòng)態(tài)鏈接庫時(shí),就需要手工運(yùn)行這個(gè)命令.

            ???? (1)命令格式
            ?ldconfig [選項(xiàng)] [libs]

            ???? (2)主要選項(xiàng)
            ?-v或--verbose ldconfig將顯示正在掃描的目錄、搜索到的動(dòng)態(tài)鏈接庫, 以及它所創(chuàng)建的連接的名字.

            ?-f CONF 指定動(dòng)態(tài)鏈接庫的配置文件為CONF, 系統(tǒng)默認(rèn)為/etc/ld.so.conf.

            ?-C CACHE 指定生成的緩存文件為CACHE, 系統(tǒng)默認(rèn)的是/etc/ld.so.cache,文件存放已排好序的可共享的動(dòng)態(tài)鏈接庫的列表.

            ?-p或--print-cache 讓ldconfig打印出當(dāng)前緩存文件所保存的所有共享庫的名字.

            ?-r ROOT 改變應(yīng)用程序的根目錄為ROOT.

            ?-n ldconfig僅掃描命令行指定的目錄, 不掃描默認(rèn)目錄(/lib、/usr/lib),也不掃描配置文件/etc/ld.so.conf所列的目錄.

            ?運(yùn)行沒有選項(xiàng)的ldconfig命令時(shí), 用于更新高速緩沖文件.這個(gè)命令主要用于高速緩沖DNS服務(wù)器(Caching DNS Server).高速緩沖DNS服務(wù)器的原理是提供查詢的歷史記錄, 并且利用這些記錄來提高查詢的效率.

            ?當(dāng)某個(gè)查詢是第一次被發(fā)送到高速緩沖DNS服務(wù)器時(shí), 高速緩沖DNS服務(wù)器就將此查詢的整個(gè)過程記錄下來, 在一定的時(shí)期內(nèi)用它來回答所有相同的查詢, 從而減少整個(gè)DNS系統(tǒng)的負(fù)擔(dān)并且提高查詢速度.

            四.庫的升級(jí)

            ?Linux系統(tǒng)軟件更新很快, 新的核心幾乎每幾個(gè)星期就公布一次, 其它軟件的更新也是非常頻繁.多數(shù)情況下, 盲目跟隨潮流的升級(jí)并不必要, 如果確實(shí)需要新版本的特性時(shí)再升級(jí).換句話說, 不要為了升級(jí)而升級(jí).Linux系統(tǒng)中多數(shù)軟件都是用共享庫來編譯的, 其中包含了在不同程序之間共享的公用子例程.

            在運(yùn)行某個(gè)程序時(shí), 如果看到如下信息:“Incompatible library version.”則表明需要將該庫升級(jí)到程序所需要的版本.庫是向下兼容的, 也就是說, 用老版本庫編譯的程序可以在新安裝的版本庫上運(yùn)行, 反之則不行.

            Linux庫函數(shù)的升級(jí)是一項(xiàng)重要的工作, 往往與其它軟件包的升級(jí)有一定關(guān)聯(lián)作用, 所以操作前一定要備份文件.下面看一下如何把Glibc 2.2.4.13升級(jí)至2.3.2版本, 其過程如下:

            ? 1.下載.gz壓縮文件并解壓

            在GUN C網(wǎng)站下載的四個(gè).gz壓縮文件, 解壓至一臨時(shí)目錄中:
            cd /usr/caolinux
            tar xzvf glibc-2.3.2.tar.gz
            cd glibc-2.3.2
            tar xzvf ../glibc-linuxthreads-2.3.2.tar.gz
            tar xzvf ../glibc-crypt-2.3.2.tar.gz
            tar xzvf ../glibc-localedata-2.3.2.tar.gz

            ? 2.建立庫函數(shù)的安裝目錄
            mkdir /usr/higlibc
            cd /usr/higlibc

            ?? 3.建立編譯目錄
            mkdir cao
            cd cao
            ./configure --enable-add-ons=linuxthreads,crypt,localedata -prefix=/usr/higlibc

            ? 4.編譯與安裝
            make
            make check
            make install

            ? 5.改變數(shù)據(jù)庫的鏈接
            ln -s /usr/higlibc/lib/ld-linux.so.2 /lib/ld-linux.so.2

            然后, 修改/etc/ld.so.conf, 加入一行/usr/higlibc/lib, 執(zhí)行下面代碼:
            ldconfig -v

            更新/etc/ld.so.cache的內(nèi)容, 列出每個(gè)庫的版本號(hào), 掃描目錄和所要?jiǎng)?chuàng)建及更新的鏈接.

            ?6.更改GCC設(shè)置

            cd /usr/lib/gcc-lib
            cp -r i386-redhat-linux higlibc

            ?7.更新符號(hào)鏈接
            cd /usr/higlibc/include
            ln -s /usr/src/linux/include/linux
            ln -s /usr/src/linux/include/asm
            ln -s /usr/X11R6/include/X11

            8.測(cè)試并完成

            五.高級(jí)共享庫特性
            ?1. soname

            共享庫的一個(gè)非常重要的, 也是非常難的概念是 soname——簡(jiǎn)寫共享目標(biāo)名(short for shared object name).這是一個(gè)為共享庫(.so)文件而內(nèi)嵌在控制數(shù)據(jù)中的名字.如前面提到的, 每一個(gè)程序都有一個(gè)需要使用的庫的清單.這個(gè)清單的內(nèi)容是一系列庫的 soname, 如同 ldd 顯示的那樣, 共享庫裝載器必須找到這個(gè)清單.

            soname 的關(guān)鍵功能是它提供了兼容性的標(biāo)準(zhǔn).當(dāng)要升級(jí)系統(tǒng)中的一個(gè)庫時(shí), 并且新庫的 soname 和老的庫的 soname 一樣, 用舊庫連接生成的程序, 使用新的庫依然能正常運(yùn)行.這個(gè)特性使得在 Linux 下, 升級(jí)使用共享庫的程序和定位錯(cuò)誤變得十分容易.

            在 Linux 中, 應(yīng)用程序通過使用 soname, 來指定所希望庫的版本.庫作者也可以通過保留或者改變 soname 來聲明, 哪些版本是相互兼容的, 這使得程序員擺脫了共享庫版本沖突問題的困擾.

            查看/usr/local/lib 目錄, 分析 MiniGUI 的共享庫文件之間的關(guān)系

            2. 共享庫裝載器

            當(dāng)程序被調(diào)用的時(shí)候, Linux 共享庫裝載器(也被稱為動(dòng)態(tài)連接器)也自動(dòng)被調(diào)用.它的作用是保證程序所需要的所有適當(dāng)版本的庫都被調(diào)入內(nèi)存.共享庫裝載器名字是 ld.so 或者是 ld-linux.so, 這取決于 Linux libc 的版本, 它必須使用一點(diǎn)外部交互, 才能完成自己的工作.然而它接受在環(huán)境變量和配置文件中的配置信息.

            文件 /etc/ld.so.conf 定義了標(biāo)準(zhǔn)系統(tǒng)庫的路徑.共享庫裝載器把它作為搜索路徑.為了改變這個(gè)設(shè)置, 必須以 root 身份運(yùn)行 ldconfig 工具.這將更新 /etc/ls.so.cache 文件, 這個(gè)文件其實(shí)是裝載器內(nèi)部使用的文件之一.

            3. 使用 dlopen

            另外一個(gè)強(qiáng)大的庫函數(shù)是 dlopen().該函數(shù)將打開一個(gè)新庫, 并把它裝入內(nèi)存.該函數(shù)主要用來加載庫中的符號(hào), 這些符號(hào)在編譯的時(shí)候是不知道的.比如 Apache Web 服務(wù)器利用這個(gè)函數(shù)在運(yùn)行過程中加載模塊, 這為它提供了額外的能力.一個(gè)配置文件控制了加載模塊的過程.這種機(jī)制使得在系統(tǒng)中添加或者刪除一個(gè)模塊時(shí), 都不需要重新編譯了.

            可以在自己的程序中使用 dlopen().dlopen() 在 dlfcn.h 中定義, 并在 dl 庫中實(shí)現(xiàn).它需要兩個(gè)參數(shù):一個(gè)文件名和一個(gè)標(biāo)志.文件名可以是我們學(xué)習(xí)過的庫中的 soname.標(biāo)志指明是否立刻計(jì)算庫的依賴性.如果設(shè)置為 RTLD_NOW 的話, 則立刻計(jì)算;如果設(shè)置的是 RTLD_LAZY, 則在需要的時(shí)候才計(jì)算.另外, 可以指定 RTLD_GLOBAL, 它使得那些在以后才加載的庫可以獲得其中的符號(hào).

            當(dāng)庫被裝入后, 可以把 dlopen() 返回的句柄作為給 dlsym() 的第一個(gè)參數(shù), 以獲得符號(hào)在庫中的地址.使用這個(gè)地址, 就可以獲得庫中特定函數(shù)的指針, 并且調(diào)用裝載庫中的相應(yīng)函數(shù).

            六、LINUX下動(dòng)態(tài)鏈接庫的使用
            重要的dlfcn.h頭文件
            LINUX下使用動(dòng)態(tài)鏈接庫, 源程序需要包含dlfcn.h頭文件, 此文件定義了調(diào)用動(dòng)態(tài)鏈接庫的函數(shù)的原型.下面詳細(xì)說明一下這些函數(shù).
            1. dlerror
            原型為: const char *dlerror(void);
            當(dāng)動(dòng)態(tài)鏈接庫操作函數(shù)執(zhí)行失敗時(shí), dlerror可以返回出錯(cuò)信息, 返回值為NULL時(shí)表示操作函數(shù)執(zhí)行成功.
            2. dlopen
            原型為: void *dlopen (const char *filename, int flag);
            dlopen用于打開指定名字(filename)的動(dòng)態(tài)鏈接庫, 并返回操作句柄.
            filename: 如果名字不以/開頭, 則非絕對(duì)路徑名, 將按下列先后順序查找該文件.
            (1) 用戶環(huán)境變量中的LD_LIBRARY值;
            (2) 動(dòng)態(tài)鏈接緩沖文件/etc/ld.so.cache
            (3) 目錄/lib, /usr/lib
            flag表示在什么時(shí)候解決未定義的符號(hào)(調(diào)用).取值有兩個(gè):
            1) RTLD_LAZY : 表明在動(dòng)態(tài)鏈接庫的函數(shù)代碼執(zhí)行時(shí)解決.
            2) RTLD_NOW : 表明在dlopen返回前就解決所有未定義的符號(hào), 一旦未解決, dlopen將返回錯(cuò)誤.
            dlopen調(diào)用失敗時(shí), 將返回NULL值, 否則返回的是操作句柄.
            3. dlsym : 取函數(shù)執(zhí)行地址
            原型為: void *dlsym(void *handle, char *symbol);
            dlsym根據(jù)動(dòng)態(tài)鏈接庫操作句柄(handle)與符號(hào)(symbol), 返回符號(hào)對(duì)應(yīng)的函數(shù)的執(zhí)行代碼地址.由此地址, 可以帶參數(shù)執(zhí)行相應(yīng)的函數(shù).
            如程序代碼: void (*add)(int x,int y); /* 說明一下要調(diào)用的動(dòng)態(tài)函數(shù)add */
            add=dlsym("xxx.so","add"); /* 打開xxx.so共享庫,取add函數(shù)地址 */
            add(89,369); /* 帶兩個(gè)參數(shù)89和369調(diào)用add函數(shù) */
            4. dlclose : 關(guān)閉動(dòng)態(tài)鏈接庫
            原型為: int dlclose (void *handle);
            dlclose用于關(guān)閉指定句柄的動(dòng)態(tài)鏈接庫, 只有當(dāng)此動(dòng)態(tài)鏈接庫的使用計(jì)數(shù)為0時(shí),才會(huì)真正被系統(tǒng)卸載.

            posted @ 2006-04-22 01:32 Jerry Cat 閱讀(3431) | 評(píng)論 (1)編輯 收藏

            /********************************************\
            |????歡迎轉(zhuǎn)載, 但請(qǐng)保留作者姓名和原文鏈接, 祝您進(jìn)步并共勉!???? |
            \********************************************/


            1.2 A Keyword Distinction

            作者: Jerry Cat
            時(shí)間: 2006/04/20
            鏈接: http://www.shnenglu.com/jerysun0818/archive/2006/04/22/6064.html

            -------------------------
            unequivocal: 毫不含糊的
            pedestrian:? 步行者; 步行的, 呆板的, 通俗的
            infamous:??? 聲名狼藉的
            strike aside:閃躲開
            brandish:??? 揮舞(n. & v.)
            fledgling:?? n.羽毛初長(zhǎng)的雛鳥, 羽翼未豐無經(jīng)驗(yàn)的人, 初出茅廬的人
            underpinning:基礎(chǔ), 支柱, 支撐
            discourse:?? 談話, 演說, 演講, 論文(n. & v.)

            C++的struct 與 class有惱人的曖昧關(guān)系, 表面上struct里沒顯式說明存儲(chǔ)權(quán)限的全是public而class則全是private, 事實(shí)卻并非如此簡(jiǎn)單當(dāng)考慮到與C的兼容時(shí), 尤其是對(duì)待C中的tricks時(shí), 更是traps多多, 地雷密布!

            A C program's trick is sometimes a C++ program's trap. One example of this is the use of a one-element array at the end of a struct to allow individual struct objects to address variable-sized arrays:

            struct mumble {
            ?? /* stuff */
            ?? char pc[ 1 ];
            };

            // grab a string from file or standard input
            // allocate memory both for struct & string

            struct mumble *pmumb1 = ( struct mumble* )
            ?? malloc(sizeof(struct mumble)+strlen(string)+1);//在C中內(nèi)存連續(xù)分布的, 但若考慮到
            ?? //這是在C++中, struct基本上就是類, 這類的數(shù)據(jù)成員與外來(參)變量的"tricky 捆綁式"
            ?? //內(nèi)存布局將導(dǎo)致派生類的數(shù)據(jù)成員"插不進(jìn)去"從而導(dǎo)致類的數(shù)據(jù)成員內(nèi)存布局不連續(xù)!
            ?? //所以C的trick是非標(biāo)準(zhǔn)的不能濫用!

            strcpy( &mumble.pc, string );
            This may or may not translate well when placed within a class declaration that

            1). specifies multiple access sections containing data,
            2). derives from another class or is itself the object of derivation, or
            3). defines one or more virtual functions.

            The data members within a single access section are guaranteed within C++ to be laid out in the order of their declaration. The layout of data contained in multiple access sections, however, is left undefined. In the following declaration, for example, the C trick may or may not work, depending on whether the protected data members are placed before or after those declared private:

            class stumble {
            public:
            ?? // operations ...
            protected:
            ?? // protected stuff
            private:
            ?? /* private stuff */
            ?? char pc[ 1 ];
            };
            ?
            Similarly, the layout of data members of the base and derived classes is left undefined, thereby also negating any guarantee that the trick might work. The presence of a virtual function also places the trick's viability in question. The best advice is not to do it. (Chapter 3 discusses these layout issues in greater detail.)

            //接上
            If a programmer absolutely needs a data portion of an arbitrarily complex C++ class to have the look and feel of an equivalent C declaration, that portion is best factored out into an independent struct declaration. The original idiom for combining this C portion with its C++ part (see [KOENIG93]) was to derive the C++ part from the C struct:

            struct C_point { ... };
            class Point : public C_point { ... };
            thus supporting both the C and C++ usage:

            extern void draw_line( Point, Point );
            extern "C" void draw_rect ( C_point, C_Point );

            draw_line( Point( 0, 0 ), Point( 100, 100 ));
            draw_rect( Point( 0, 0 ), Point( 100, 100 ));
            This idiom is no longer recommended, however, because of changes to the class inheritance layout in some compilers (for example, the Microsoft C++ compiler) in support of the virtual function mechanism (see Section 3.4 for a discussion). Composition, rather than inheritance, is the only portable method of combining C and C++ portions of a class (the conversion operator provides a handy extraction method):

            struct C_point { ... };

            class Point {
            public:
            ?? operator C_point() { return _c_point; }
            ?? // ...
            private:
            ?? C_point _c_point;
            ?? // ...
            };

            強(qiáng)烈不推薦這種種"淫巧",? 不過在C/C++混合編程時(shí)你還不得不用它:)
            One reasonable use of the C struct in C++, then, is when you want to pass all or part of a complex class object to a C function. This struct declaration serves to encapsulate that data and guarantees a compatible C storage layout. This guarantee, however, is maintained only under composition. Under inheritance, the compiler decides whether additional data members are inserted within the base struct subobject (again, see Section 3.4 for a discussion, as well as Figures 3.2(a) and 3.2(b)).

            posted @ 2006-04-22 01:23 Jerry Cat 閱讀(610) | 評(píng)論 (0)編輯 收藏

            胡錦濤主席說"我也每天使用微軟公司的操作系統(tǒng)"

            胡主席訪問微軟時(shí)說:“比爾·蓋茨先生是中國(guó)的朋友,我則是微軟的朋友。”他告訴蓋茨:“我也每天使用微軟公司的操作系統(tǒng)。”蓋茨則說:“無論何時(shí)您需要關(guān)于windows的建議,我將很高興提供幫助。”如果不考慮中美貿(mào)易摩擦的大背景,這番對(duì)話簡(jiǎn)直就是一對(duì)老朋友之間的對(duì)話,而不是國(guó)家首腦和一位企業(yè)領(lǐng)導(dǎo)者之間的對(duì)話。

            ---------------------------------------------------------

            胡錦濤主席訪問微軟重申保護(hù)知識(shí)產(chǎn)權(quán)決心
            2006.04.21? 來自:國(guó)際金融報(bào) ??

              表示加強(qiáng)知識(shí)產(chǎn)權(quán)保護(hù)不僅對(duì)中國(guó)擴(kuò)大對(duì)外開放和改善投資環(huán)境十分必要,而且對(duì)于加強(qiáng)中國(guó)自主創(chuàng)新能力也是不可或缺的。

              美國(guó)西雅圖消息當(dāng)?shù)貢r(shí)間4月18日下午,正在美國(guó)華盛頓州西雅圖訪問的中國(guó)國(guó)家主席胡錦濤,會(huì)見了華盛頓州州長(zhǎng)葛瑞格爾。

              隨后,胡錦濤主席前往設(shè)在萊德蒙德的微軟公司總部參觀,并出席了在比爾·蓋茨家舉行的歡迎宴會(huì)。

              參觀微軟是胡錦濤此次訪美行程中極其重要的一個(gè)環(huán)節(jié)。在參觀了微軟公司的主要技術(shù)后,胡錦濤重申了中國(guó)加強(qiáng)知識(shí)產(chǎn)權(quán)保護(hù)的決心。他表示,此舉“不僅對(duì)中國(guó)擴(kuò)大對(duì)外開放和改善投資環(huán)境”十分必要,而且“對(duì)于加強(qiáng)中國(guó)自主創(chuàng)新能力”也是不可或缺的。

              胡錦濤稱贊了比爾·蓋茨在微軟取得的成就,并說:“因?yàn)槟悖葼枴どw茨先生是中國(guó)的朋友,我則是微軟的朋友。”他表示希望看到微軟和中國(guó)的合作,并歡迎微軟將來增加在中國(guó)的投資。

              就在胡錦濤開始訪美的當(dāng)天,聯(lián)想與微軟簽訂12億美元的軟件購買協(xié)議,此前方正、同方及TCL等公司也簽訂了價(jià)值17億美元的軟件購買協(xié)議,為其生產(chǎn)的計(jì)算機(jī)預(yù)裝微軟Windows操作系統(tǒng),以此抵制盜版軟件。

              微軟公司的高管們認(rèn)為,胡錦濤的這次訪問象征著中國(guó)政府對(duì)知識(shí)產(chǎn)權(quán)的態(tài)度出現(xiàn)根本轉(zhuǎn)變。中國(guó)已開始強(qiáng)化在知識(shí)產(chǎn)權(quán)問題上的立場(chǎng),因?yàn)榧訌?qiáng)對(duì)知識(shí)產(chǎn)權(quán)的保護(hù)符合中國(guó)自身的經(jīng)濟(jì)發(fā)展利益。

              微軟首席技術(shù)官克瑞格·蒙迪表示,“我認(rèn)為,一年多來,中國(guó)領(lǐng)導(dǎo)人已越過了一道坎,意識(shí)到知識(shí)產(chǎn)權(quán)對(duì)中國(guó)本身的未來要求也至關(guān)重要。”盡管問題不會(huì)在一夜之間改變,但他認(rèn)為最近的幾則通告是一種“重大飛躍”。

              蒙迪說,中國(guó)仍是微軟優(yōu)先考慮的重點(diǎn),無論是作為一個(gè)市場(chǎng)還是未來市場(chǎng)的技術(shù)來源,盡管在知識(shí)產(chǎn)權(quán)方面存在一些困難。

              當(dāng)天上午10時(shí)50分左右,胡錦濤乘坐的專機(jī)抵達(dá)西雅圖佩因機(jī)場(chǎng)。在機(jī)場(chǎng)發(fā)表書面講話時(shí),胡錦濤指出,中美都是偉大的國(guó)家,擁有廣泛的共同利益和堅(jiān)實(shí)的合作基礎(chǔ),肩負(fù)著促進(jìn)世界和平與發(fā)展的共同責(zé)任。一個(gè)健康穩(wěn)定、不斷發(fā)展的中美關(guān)系不僅造福兩國(guó)人民,而且有利于亞太地區(qū)及世界的和平、穩(wěn)定、繁榮。

              當(dāng)晚在比爾·蓋茨豪宅為胡主席一行舉行的歡迎宴會(huì)上,美中關(guān)系全國(guó)委員會(huì)主席歐倫斯對(duì)胡錦濤此行給予了高度評(píng)價(jià)。他稱,“胡錦濤把訪美的第一站放在西雅圖,其實(shí)是用行動(dòng)對(duì)解決中美貿(mào)易爭(zhēng)端作出承諾——中國(guó)愿意開放經(jīng)濟(jì)、同美國(guó)加強(qiáng)合作。這就是一個(gè)‘負(fù)責(zé)任的利益相關(guān)者’所代表的含義。”

              據(jù)悉,胡錦濤將于當(dāng)?shù)貢r(shí)間19日參觀波音公司,然后飛往華盛頓與布什總統(tǒng)在白宮舉行會(huì)談,鑒于近期國(guó)際市場(chǎng)原油價(jià)格飆升,各界人士紛紛預(yù)計(jì)能源問題將成為此次會(huì)談的重要議題之一。

              胡錦濤對(duì)比爾·蓋茨家訪有深意

              胡錦濤主席于4月18日前往美國(guó)進(jìn)行為期4天的國(guó)事訪問,其中一項(xiàng)安排是到全球首富、微軟公司董事會(huì)主席比爾·蓋茨的私人住宅探訪,并與100多名其他賓客出席晚宴。

              比爾·蓋茨作為全球首富,同時(shí)也是先進(jìn)科學(xué)技術(shù)的領(lǐng)導(dǎo)者之一,其創(chuàng)辦的微軟公司對(duì)全球科技和經(jīng)濟(jì)發(fā)展已經(jīng)發(fā)揮了并且還將繼續(xù)發(fā)揮引領(lǐng)作用。從胡主席對(duì)比爾·蓋茨的家訪,至少可以看出三點(diǎn)含義:

              一是表達(dá)中國(guó)政府維護(hù)公平貿(mào)易、打擊盜版的決心。中國(guó)作為全世界第二大PC市場(chǎng),是國(guó)際投資者爭(zhēng)奪的對(duì)象。對(duì)于我國(guó)現(xiàn)實(shí)存在的軟件盜版問題,我國(guó)政府高度重視,外界也十分關(guān)注。加大反盜版行動(dòng)的力度,既是促進(jìn)國(guó)內(nèi)經(jīng)濟(jì)秩序健康發(fā)展的需要,也是對(duì)外國(guó)投資者的善意回應(yīng)。

              在胡主席出訪前,信產(chǎn)部、國(guó)家版權(quán)局、商務(wù)部、財(cái)政部等于4月10日聯(lián)合下發(fā)《關(guān)于計(jì)算機(jī)預(yù)裝正版操作系統(tǒng)軟件有關(guān)問題的通知》,要求在我國(guó)境內(nèi)生產(chǎn)的計(jì)算機(jī),出廠時(shí)應(yīng)當(dāng)預(yù)裝正版操作系統(tǒng)軟件。而進(jìn)口計(jì)算機(jī)在國(guó)內(nèi)銷售,銷售前應(yīng)當(dāng)預(yù)裝正版操作系統(tǒng)軟件。同時(shí)規(guī)定計(jì)算機(jī)生產(chǎn)者和操作系統(tǒng)軟件提供者須按照規(guī)定報(bào)送計(jì)算機(jī)銷售數(shù)量、操作系統(tǒng)軟件的預(yù)裝數(shù)量。

              胡主席向蓋茨表示,希望看到微軟和中國(guó)的合作,歡迎微軟將來增加在中國(guó)的投資,并表示中國(guó)會(huì)在保護(hù)知識(shí)產(chǎn)權(quán)的問題上履行諾言。

              事實(shí)上,我國(guó)的反盜版行動(dòng)直接促進(jìn)了中國(guó)廠商與微軟公司的貿(mào)易。3家中國(guó)電腦制造商將宣布未來3年購買總價(jià)值4億美元的微軟Windows操作系統(tǒng)的計(jì)劃。

              二是體現(xiàn)中國(guó)領(lǐng)導(dǎo)人對(duì)科學(xué)技術(shù)、對(duì)知識(shí)分子的尊重。按照中國(guó)的傳統(tǒng),家訪是一種很高的禮遇。中國(guó)政府歷來強(qiáng)調(diào)尊重知識(shí)、尊重人才,而比爾·蓋茨既是一位資本家,也是一位成功的創(chuàng)業(yè)者,是自主創(chuàng)新的典型代表。他的創(chuàng)業(yè)之路早已為中國(guó)人所津津樂道,在年輕人心目中,蓋茨堪稱一位英雄。

              胡主席訪問微軟時(shí)說:“比爾·蓋茨先生是中國(guó)的朋友,我則是微軟的朋友。”他告訴蓋茨:“我也每天使用微軟公司的操作系統(tǒng)。”蓋茨則說:“無論何時(shí)您需要關(guān)于windows的建議,我將很高興提供幫助。”如果不考慮中美貿(mào)易摩擦的大背景,這番對(duì)話簡(jiǎn)直就是一對(duì)老朋友之間的對(duì)話,而不是國(guó)家首腦和一位企業(yè)領(lǐng)導(dǎo)者之間的對(duì)話。

              蓋茨的家庭宴會(huì)上,其實(shí)只有三道大菜:煙熏珍珠雞沙拉、黃洋蔥配制的牛排或大比目魚配大蝦(任選其一)、牛油杏仁大蛋糕。說白了就是雞肉、牛肉或者蝦魚和蛋糕。當(dāng)然,美國(guó)人待客歷來只如此,但如果按照中國(guó)人的眼光,把蓋茨看作是“知識(shí)分子企業(yè)家”,這個(gè)場(chǎng)面和中國(guó)傳統(tǒng)知識(shí)分子的待客模式也還有些相像。

              三是表達(dá)中國(guó)努力建設(shè)創(chuàng)新型國(guó)家的雄心。

              今年1月9日,胡主席在全國(guó)科技大會(huì)上宣布中國(guó)將用15年時(shí)間建設(shè)創(chuàng)新型國(guó)家;科技大會(huì)召開3個(gè)月后,他借訪美之機(jī),親自造訪微軟總部,考察微軟先進(jìn)技術(shù),顯然具有深意。

              毫無疑問,建設(shè)創(chuàng)新型國(guó)家需要體制和資金上的支持,但同時(shí),在全社會(huì)營(yíng)造“創(chuàng)新文化”更加重要。承認(rèn)、尊重他人的科技成果,努力學(xué)習(xí)借鑒他人的先進(jìn)經(jīng)驗(yàn),應(yīng)當(dāng)是創(chuàng)新文化的基本要素。

              當(dāng)中國(guó)國(guó)家主席與微軟領(lǐng)導(dǎo)人聚首之時(shí),傳遞出的正是對(duì)中華文化優(yōu)良傳統(tǒng)的繼承和弘揚(yáng),對(duì)外國(guó)文化有益成果的積極吸收和借鑒之意。

            posted @ 2006-04-21 16:12 Jerry Cat 閱讀(574) | 評(píng)論 (0)編輯 收藏

            /********************************************\
            |????歡迎轉(zhuǎn)載, 但請(qǐng)保留作者姓名和原文鏈接, 祝您進(jìn)步并共勉!???? |
            \********************************************/


            C++對(duì)象模型(1)


            作者: Jerry Cat
            時(shí)間: 2006/04/20
            鏈接: http://www.shnenglu.com/jerysun0818/archive/2006/04/20/5969.html

            Chapter 0 : Preface
            =-=-=-=-=-=-=-=-=-=
            I must also say that the general pattern of virtual function implementation across all current compilation systems is to use a class-specific virtual table of a fixed size that is constructed prior to program execution.

            Chapter 1: Object Lessons
            =-=-=-=-=-=-=-=-=-=-=-=-=
            1.1 The C++ Object Model
            -------------------------
            (1). class Point
            {
            public:
            ?? Point( float xval );
            ?? virtual ~Point();
            ?? float x() const;
            ?? static int PointCount();

            protected:
            ?? virtual ostream& print( ostream &os ) const;
            ?? float _x;
            ?? static int _point_count;
            };

            Stroustrup's original (and still prevailing) C++ Object Model is derived from the simple object model by optimizing for space and access time. Nonstatic data members are allocated directly within each class object. Static data members are stored outside the individual class object. Static and nonstatic function members are also hoisted outside the class object. Virtual functions are supported in two steps:

            ? 1). A table of pointers to virtual functions is generated for each class (this is called the virtual table).

            ? 2). A single pointer to the associated virtual table is inserted within each class object (traditionally, this has been called the vptr). The setting, resetting, and not setting of the vptr is handled automatically through code generated within each class constructor, destructor, and copy assignment operator (this is discussed in Chapter 5). The type_info object associated with each class in support of runtime type identification (RTTI) is also addressed within the virtual table, usually within the table's first slot.

            (2). 加入繼承后
            C++ supports both single inheritance:

            class Library_materials { ... };
            class Book : public Library_materials { ... };
            class Rental_book : public Book { ... };
            and multiple inheritance:

            // original pre-Standard iostream implementation
            class iostream:
            ?? public istream,
            ?? public ostream { ... };
            Moreover, the inheritance may be specified as virtual (that is, shared):

            class istream : virtual public ios { ... };
            class ostream : virtual public ios { ... };

            In the case of virtual inheritance, only a single occurrence of the base class is maintained (called a subobject) regardless of how many times the class is derived from within the inheritance chain. iostream, for example, contains only a single instance of the virtual ios base class.

            How might a derived class internally model its base class instance? In a simple base class object model, each base class might be assigned a slot within the derived class object. Each slot holds the address of the base class subobject. The primary drawback to this scheme is the space and access-time overhead of the indirection. A benefit is that the size of the class object is unaffected by changes in the size of its associated base classes.

            Alternatively, one can imagine a base table model. Here, a base class table is generated for which each slot contains the address of an associated base class, much as the virtual table holds the address of each virtual function. Each class object contains a bptr initialized to address its base class table. The primary drawback to this strategy, of course, is both the space and access-time overhead of the indirection. One benefit is a uniform representation of inheritance within each class object. Each class object would contain a base table pointer at some fixed location regardless of the size or number of its base classes. A second benefit would be the ability to grow, shrink, or otherwise modify the base class table without changing the size of the class objects themselves.

            The original inheritance model supported by C++ forgoes all indirection; the data members of the base class subobject are directly stored within the derived class object. This offers the most compact and most efficient access of the base class members. The drawback, of course, is that any change to the base class members, such as adding, removing, or changing a member's type, requires that all code using objects of the base class or any class derived from it be recompiled.

            posted @ 2006-04-20 18:13 Jerry Cat 閱讀(549) | 評(píng)論 (0)編輯 收藏

            /********************************************\
            |????歡迎轉(zhuǎn)載, 但請(qǐng)保留作者姓名和原文鏈接, 祝您進(jìn)步并共勉!???? |
            \********************************************/

            VC++的鏈接錯(cuò)誤LNK2005


            作者: Jerry Cat
            時(shí)間: 2006/04/19
            鏈接: http://www.shnenglu.com/jerysun0818/archive/2006/04/19/5913.html

            編程中經(jīng)常能遇到LNK2005錯(cuò)誤——重復(fù)定義錯(cuò)誤,其實(shí)LNK2005錯(cuò)誤并不是一個(gè)很難解決的錯(cuò)誤。弄清楚它形成的原因,就可以輕松解決它了。

            造成LNK2005錯(cuò)誤主要有以下幾種情況:
            1.重復(fù)定義全局變量。可能存在兩種情況:
            A、對(duì)于一些初學(xué)編程的程序員,有時(shí)候會(huì)以為需要使用全局變量的地方就可以使用定義申明一下。其實(shí)這是錯(cuò)誤的,全局變量是針對(duì)整個(gè)工程的。正確的應(yīng)該是在一個(gè)CPP文件中定義如下:int g_Test;那么在使用的CPP文件中就應(yīng)該使用:extern int g_Test即可,如果還是使用int g_Test,那么就會(huì)產(chǎn)生LNK2005錯(cuò)誤,一般錯(cuò)誤錯(cuò)誤信息類似:AAA.obj error LNK2005 int book c?
            book@@3HA already defined in BBB.obj。切記的就是不能給變量賦值否則還是會(huì)有LNK2005錯(cuò)誤。
            ?????? 這里需要的是“聲明”,不是“定義”!根據(jù)C++標(biāo)準(zhǔn)的規(guī)定,一個(gè)變量是聲明,必須同時(shí)滿足兩個(gè)條件,否則就是定義:
            (1)聲明必須使用extern關(guān)鍵字;(2)不能給變量賦初值
            所以,下面的是聲明:
            extern int a;
            下面的是定義
            int a; int a = 0; extern int a =0;
            B、對(duì)于那么編程不是那么嚴(yán)謹(jǐn)?shù)某绦騿T,總是在需要使用變量的文件中隨意定義一個(gè)全局變量,并且對(duì)于變量名也不予考慮,這也往往容易造成變量名重復(fù),而造成LNK2005錯(cuò)誤。

            2.頭文件的包含重復(fù)。往往需要包含的頭文件中含有變量、函數(shù)、類的定義,在其它使用的地方又不得不多次包含之,如果頭文件中沒有相關(guān)的宏等防止重復(fù)鏈接的措施,那么就會(huì)產(chǎn)生LNK2005錯(cuò)誤。解決辦法是在需要包含的頭文件中做類似的處理:#ifndef MY_H_FILE?? //如果沒有定義這個(gè)宏
            #define MY_H_FILE?? //定義這個(gè)宏
            …….?? //頭文件主體內(nèi)容
            …….
            #endif
            上面是使用宏來做的,也可以使用預(yù)編譯來做,在頭文件中加入:
            #pragma once
            //頭文件主體
            3.使用第三方的庫造成的。這種情況主要是C運(yùn)行期函數(shù)庫和MFC的庫沖突造成的。具體的辦法就是將那個(gè)提示出錯(cuò)的庫放到另外一個(gè)庫的前面。另外選擇不同的C函數(shù)庫,可能會(huì)引起這個(gè)錯(cuò)誤。微軟和C有兩種C運(yùn)行期函數(shù)庫,一種是普通的函數(shù)庫:LIBC.LIB,不支持多線程。另外一種是支持多線程的:msvcrt.lib。如果一個(gè)工程里,這兩種函數(shù)庫混合使用,可能會(huì)引起這個(gè)錯(cuò)誤,一般情況下它需要MFC的庫先于C運(yùn)行期函數(shù)庫被鏈接,因此建議使用支持多線程的msvcrt.lib。所以在使用第三方的庫之前首先要知道它鏈接的是什么庫,否則就可能造成LNK2005錯(cuò)誤。如果不得不使用第三方的庫,可以嘗試按下面所說的方法修改,但不能保證一定能解決問題,前兩種方法是微軟提供的:
            A、選擇VC菜單Project->Settings->Link->Catagory選擇Input,再在Ignore libraries 的Edit欄中填入你需要忽略的庫,如:Nafxcwd.lib;Libcmtd.lib。然后在Object/library Modules的Edit欄中填入正確的庫的順序,這里需要你能確定什么是正確的順序,呵呵,God bless you!
            B、選擇VC菜單Project->Settings->Link頁,然后在Project Options的Edit欄中輸入/verbose:lib,這樣就可以在編譯鏈接程序過程中在輸出窗口看到鏈接的順序了。
            C、選擇VC菜單Project->Settings->C/C++頁,Catagory選擇Code Generation后再在User Runtime libraray中選擇MultiThread DLL等其他庫,逐一嘗試。

            這就是我所遇到過的LNK2005錯(cuò)誤的幾種情況,肯定還有其他的情況也可能造成這種錯(cuò)誤,所以我不希望你在看完這篇文章以后,再遇到LNK2005錯(cuò)誤時(shí)候,不動(dòng)腦筋的想對(duì)號(hào)入座的排除錯(cuò)誤。編程的過程就是一個(gè)思考的過程,所以還是多多開動(dòng)你的頭腦,那樣收獲會(huì)更多!
            =======================================
            支持,我在社區(qū)里也看到了許多LINK 2005錯(cuò)
            補(bǔ)充一點(diǎn),就是一次在用第三方庫時(shí),由于errno被重定義,用多種方法都不能解決,后查找MSDN,發(fā)現(xiàn)link有個(gè)選項(xiàng)/FORCE可以解決,在IDE下
            Project->Settings->Link頁,選categroy為custom,將force file output前打勾
            但會(huì)有警告
            warning LNK4088: image being generated due to /FORCE option; image may not run
            但的確解決了問題,這是由于VC對(duì)重定義比較嚴(yán)格,像BCB或GCC在庫中的重定義不會(huì)有任何警告或錯(cuò)誤
            ========================================
            我發(fā)現(xiàn)的另外一個(gè)出現(xiàn)LINK2005的現(xiàn)象,好像是由于名稱空間而引起的。我在dos下寫的程序沒有問題,但是放在mfc中就出現(xiàn)了這個(gè)鏈接錯(cuò)誤。因?yàn)槠鸪鯃D省事,我在一個(gè)頭文件中寫了using namespace std,并且這個(gè)頭文件我多處使用,另外,我還使用了boost庫。后來,問題解決的方法非常奇怪,在一個(gè)頭文件中引用其他頭文件,這些頭文件的順序換一下就通過了,那個(gè)出現(xiàn)問題的頭文件中我使用了std::map,當(dāng)我把這種容器使用模板代替后,鏈接就有沒事了。(例如:template<class coll>),后來感到模板技術(shù)還有這種效果,賺了!哈哈
            ========================================
            What are the C and C++ libraries my program would link with?

            ????????????????????? Summary Table

            ?Compile?? Old???????????? New IOStream?? ?Libraries

            ?Option???? IOStream?? ?or STL???????? ?????? Linked With

            ?

            ?/ML??????? No??????????????? No???????????????????LIBC.LIB

            ?/MLd????? No??????????????? No???????????????????LIBCD.LIB

            ?/MT??????? No??????????????? No???????????????????LIBCMT.LIB

            ?/MTd????? No??????????????? No???????????????????LIBCMTD.LIB

            ?/MD?????? No???????????????? No???????????????????MSVCRT.LIB

            ?/MDd?????No???????????????? No???????????????????MSVCRTD.LIB

            ?/ML??????? No??????????????? Yes???????????????????LIBC.LIB,??? ?LIBCP.LIB

            ?/MLd????? No??????????????? Yes???????????????????LIBCD.LIB,?? LIBCPD.LIB

            ?/MT??????? No??????????????? Yes???????????????????LIBCMT.LIB,? LIBCPMT.LIB

            ?/MTd????? No??????????????? Yes???????????????????LIBCMTD.LIB, LIBCPMTD.LIB

            ?/MD??????? No??????????????? Yes???????????????????MSVCRT.LIB,? MSVCPRT.LIB

            ?/MDd????? No??????????????? Yes???????????????????MSVCRTD.LIB, MSVCPRTD.LIB

            ?/ML??????? Yes??????????????? No???????????????????LIBC.LIB,??? ??LIBCI.LIB

            ?/MLd????? Yes??????????????? No???????????????????LIBCD.LIB,?? ?LIBCID.LIB

            ?/MT??????? Yes??????????????? No???????????????????LIBCMT.LIB,? ?LIBCIMT.LIB

            ?/MTd????? Yes??????????????? No???????????????????LIBCMTD.LIB, ?LIBCIMTD.LIB

            ?/MD??????? Yes??????? ?????? No???????????????????MSVCRT.LIB,? MSVCIRT.LIB

            ?/MDd????? Yes??????? ?????? No???????????????????MSVCRTD.LIB, MSVCIRTD.LIB


            你的程序使用了/ML編譯選項(xiàng),而程序依賴的.lib可能使用/MDd選項(xiàng)編譯,造成鏈接沖突.

            統(tǒng)一編譯選項(xiàng)可回避此錯(cuò)誤
            Project Settings->C/C++ Tab->Category:CodeGeneration
            Use run-time library組合框中選擇Multithread Dll(或Debug Multithread Dll )

            Summary Table for CRT DLLs Used
            Import Library Linked With DLLs Used (Visual C++ 5.0|6.0) DLLs Used (Visual C++ 4.2) DLLs Used (Visual C++ .NET 2002| Visual C++ .NET 2003)
            MSVCRT.LIB MSVCRT.DLL MSVCRT.DLL MSVCRT.DLL
            MSVCRTD.LIB MSVCRTD.DLL MSVCRTD.DLL MSVCRTD.DLL
            MSVCPRT.LIB MSVCP(5|6)0.DLL MSVCP7(0|1).DLL
            MSVCPRTD.LIB MSVCP(5|6)0D.DLL MSVCP7(0|1)D.DLL
            MSVCIRT.LIB MSVCIRT.DLL MSVCIRT.DLL
            MSVCIRTD.LIB MSVCIRTD.DLL MSVCIRTD.DLL


            注意:所有相關(guān)工程都應(yīng)該選擇相同編譯選項(xiàng)
            ========================================
            微軟的MSDN中查到信息的

            可能的原因

            不慎同時(shí)與單線程庫和多線程庫鏈接。確保應(yīng)用程序項(xiàng)目文件只包括適當(dāng)?shù)膸欤⑶胰魏蔚谌綆煲堰m當(dāng)創(chuàng)建了單線程或多線程版本。
            該符號(hào)為封裝函數(shù)(通過用 /Gy 編譯創(chuàng)建),包含在多個(gè)文件中,但在各編譯間已改變。重新編譯所有包含 symbol 的文件。
            以不同的形式在不同庫中的兩個(gè)成員對(duì)象中定義了該符號(hào),并且使用了這兩個(gè)成員對(duì)象。
            某個(gè)絕對(duì)符號(hào)被定義兩次,而每次定義的值不同。
            頭文件聲明并定義了變量。可能的解決方案有:
            在 .h 中聲明變量:extern BOOL MyBool;,然后在 .c 或 .cpp 文件中向它分配:BOOL MyBool = FALSE;。
            將變量聲明為 Static。
            將變量聲明為 selectany。
            當(dāng)將 uuid.lib 與定義 GUID 的其他 .lib 文件(例如 oledb.lib 和 adsiid.lib)一起使用時(shí)。例如:
            oledb.lib(oledb_i.obj) : error LNK2005: _IID_ITransactionObject
            already defined in uuid.lib(go7.obj)
            若要修復(fù),請(qǐng)將 /FORCE:MULTIPLE 添加到鏈接器命令行選項(xiàng),并確保 uuid.lib 是引用的第一個(gè)庫。

            有關(guān)更多信息,請(qǐng)參閱知識(shí)庫文章:

            Q148652,PRB: LNK2005 Errors When Link C Run-Time Libraries Are Linked Before MFC Libraries。
            Q140440,F(xiàn)IX: Global Overloaded Delete Operator Causes LNK2005。
            Q184235,PRB: LNK2005 Errors on New and Delete When Defining _ATL_MIN_CRT。
            該錯(cuò)誤之后為致命錯(cuò)誤 LNK1169。
            =======================================
            有時(shí)候因?yàn)楣こ淌褂昧祟A(yù)編譯頭文件并且是增量編譯,所以當(dāng)你改動(dòng)以后可能也會(huì)出現(xiàn)LNK2005錯(cuò)誤,提示“XXXX已經(jīng)在XXXX.obj文件中定義”的消息,這時(shí)候只要Rebuild All一般都能解決問題。這是因?yàn)轭^文件的順序被改動(dòng)等等操作造成的。
            最后要說明的:事物是在不斷變化中的,C++的標(biāo)準(zhǔn)在變化,編譯器也在變化,所以并不是所有的LNK2005錯(cuò)誤都可以在這里找到答案,但是至少它能給你以提示。學(xué)習(xí)并思考才是正確的!

            posted @ 2006-04-19 23:45 Jerry Cat 閱讀(3926) | 評(píng)論 (0)編輯 收藏
            僅列出標(biāo)題
            共14頁: First 6 7 8 9 10 11 12 13 14 

            <2025年6月>
            25262728293031
            1234567
            891011121314
            15161718192021
            22232425262728
            293012345

            常用鏈接

            留言簿(7)

            隨筆檔案

            最新隨筆

            搜索

            •  

            最新評(píng)論

            閱讀排行榜

            評(píng)論排行榜

            久久99国产精品尤物| 久久九九久精品国产免费直播| | 亚洲国产视频久久| 久久天天躁狠狠躁夜夜网站| 久久久九九有精品国产| 99久久人人爽亚洲精品美女| 中文成人无码精品久久久不卡 | 亚洲精品乱码久久久久久自慰| 欧美亚洲色综久久精品国产| 精品一久久香蕉国产线看播放| 国产成人精品综合久久久久 | 亚洲国产精品久久久久| 欧美黑人激情性久久| 国产成人久久久精品二区三区| 久久精品国产亚洲AV久| 久久se精品一区二区影院| 国产麻豆精品久久一二三| 狠狠色丁香久久婷婷综合图片| 精品国产婷婷久久久| 国产精品一久久香蕉国产线看观看| 亚洲综合久久久| 久久精品国产只有精品66| 伊人色综合久久| 欧美精品一区二区精品久久 | 国产2021久久精品| 国产日产久久高清欧美一区| 青青草原综合久久大伊人| 久久亚洲中文字幕精品一区| 久久久久四虎国产精品| 韩国无遮挡三级久久| 97久久超碰国产精品旧版| 久久水蜜桃亚洲av无码精品麻豆| 国产激情久久久久久熟女老人| 亚洲欧洲精品成人久久奇米网| 久久久久久久久久免免费精品 | 久久亚洲国产最新网站| 婷婷久久五月天| 亚洲va国产va天堂va久久| 亚洲狠狠婷婷综合久久久久| 婷婷五月深深久久精品|