• <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

            /********************************************\
            |????歡迎轉載, 但請保留作者姓名和原文鏈接, 祝您進步并共勉!???? |
            \********************************************/


            連綿不斷的析取流

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


            /*
            精巧的ostream和<<機制, 不僅具有面向對象的多重繼承和重載, 且性能不輸C的IO庫函數

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

            >>a表示將數據放入a對象中.
            <<a表示將a對象中存儲的數據拿出到流中, 最終匯入流對象ostream.
            */

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

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

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

            /********************************************\
            |????歡迎轉載, 但請保留作者姓名和原文鏈接, 祝您進步并共勉!???? |
            \********************************************/

            C++對象模型(3) - An Object Distinction
            ?
            作者: Jerry Cat
            時間: 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間進行調解
            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就是個只保留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, 因為基類和派生類的布局是"基部重合在一起的", 派生類還是超集哩!
            // 基類在"上"(低址處), 派生類多出的部分緊接著"連"在下面; 引用(本質上是指針)和指針對這兩種數據類型
            // 有類似匯編中word ptr 和 dword ptr的關系, 它倆的首址是相同的. 編譯器會自動鑒別基類和子類從而調整
            // 類似word ptr 和 dword ptr的這種類的"類型尋址"操作
            // 而且Scott Meyer說過它們是一種"is a"的關系:"The derived is a base class"
            // 向上(基類方向)轉換沒問題的, 向下轉換一般不可 - 簡直"無中生有"嘛! 但MFC中對動態類對象CDerived(用
            // DECLARE_DYNCREATE宏 和 IMPLEMENT_DYNCREATE宏在程序運行時而非編譯動態生成)倒可用DYNAMIC_DOWNCAST
            // 宏來完成將指向CBase的指針Downcast成指向它:
            // CDerived * pDerived = DYNAMIC_DOWNCAST(CDerived, pBase); //CBase *pBase;
            // 原型為DYNAMIC_DOWNCAST( class, pointer )

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

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

            只有指針和引用才能"救多態"!
            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;
            多態只存在于
            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.
            多態是面向對象OO的實質
            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抽象數據類型是基于對象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 閱讀(693) | 評論 (0)編輯 收藏

            [轉]AT&T x86 asm 語法

            創建時間:2001-04-09
            文章屬性:翻譯

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

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

            儲器操作數的大小取決于操作碼的最后一個字符。 它們是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分辨代表源和目的操作數后綴。
            ??? 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應該是兩個相互獨立的指令, 存儲器的情況也有一點不同。通常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 指令通常是個短跳轉。 可是, 下面這些指令都是只能在一個字節的范圍內跳轉: jcxz, jecxz, loop, loopz, loope, loopnz 和loopne

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

            單操作數來獲得擴展結果。


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

            Inline Asm
            我將首先開始inline asm, 因為似乎關于這方面的疑問非常多。這是最基本的語法了, 就象在線幫助信息中描述的:
            __asm__(asm statements : outputs : inputs : registers-modified);

            這四個字段的含義是:

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

            ??? 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"就讓編譯器決定該在哪里加載i的值。一般來說,你的大部分輸入變量都可以被賦予 "g", 讓編

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

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

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

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

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

            子。

            讓我們看看兩個輸入變量且引入了"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, 現在我們已經有了兩個輸入變量了。沒問題了, 我們只需要記住%0對應第一個輸入變量(在這個例子中是i), %1對應在i后面的列出的j


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

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

            讓我們來看看輸出字段:

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

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

            如何同時處理輸入輸出字段的。
            ??? 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, 唯一個不清楚的地方就是匯編代碼中的變量的個數。我馬上來解釋一下。
            當同時使用輸入字段和輸出字段的時候:

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

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

            在我們的例子中, %0 對應k, %1 對應i, %2對應j。很簡單,是吧?

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

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

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

            ??? int i=0, j=1, k=0;
            ??? __asm__ __volatile__("
            ??????? pushl %%eax\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, 如果必要的話。一個16-bit寄存器名代表了32-, 16-或8-bit寄存器。 如果我們要改寫內存 (寫入一個變量等。

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

            來, 是為了更簡單易懂。

            在你的內聯匯編里面定位標號應該使用b或f來作為終止符, 尤其是向后向前的跳轉。(譯者注:b代表向后跳轉,f代表向前跳轉)

            For example,

            ??? __asm__ __volatile__("
            ??????? 0:\n
            ??????????? ...
            ??????????? jmp 0b\n
            ??????????? ...
            ??????????? jmp 1f\n
            ??????????? ...
            ??????? 1:\n
            ??????????? ...
            ??? );
            這里有個用c代碼和內聯匯編代碼混合寫的跳轉程序的例子(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文件。基本結構如下:
            ??? .file "myasm.S"

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

            ??? .text
            ??? .globl __myasmfunc
            ??? __myasmfunc:
            ??? ...
            ??? ret
            Macros, macros! 頭文件libc/asmdefs.h便于你寫asm。 在你的匯編代碼最前面包含此頭文件然后就可以使用宏了。一個例子: 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
            這是一個好的純粹的匯編代碼框架

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

            /********************************************\
            |????歡迎轉載, 但請保留作者姓名和原文鏈接, 祝您進步并共勉!???? |
            \********************************************/


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

            作者: Jerry Cat
            時間: 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++編程一頭一尾最重要, 無數英雄折腰, 多少豪杰翻船!
            ??? free(tmpstr);
            ??? return str - nCnt;
            }

            上面方法不好, 繁雜且易出錯, 經沐楓兄指點, 下面倆是改進版^_^
            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)
            {?? //省去一變量, 時間換空間法
            ??? 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 閱讀(1122) | 評論 (7)編輯 收藏

            /********************************************\
            |????歡迎轉載, 但請保留作者姓名和原文鏈接, 祝您進步并共勉!???? |
            \********************************************/


            Linux靜態、共享和動態庫之編程

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

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

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

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

            ???? 已經開發的大多數庫都采取共享庫的方式.ELF格式的可執行文件使得共享庫能夠比較容易地實現, 當然使用舊的a.out模式也可以實現庫的共享.Linux系統中目前可執行文件的標準格式為ELF格式.

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

             ? .a是靜態庫文件, 可以用ar 命令生成.
              .so是動態庫文件, 編譯時加上指定的選項即可生成, 具體選項看相應的系統文檔了.

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

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

              這里的name可以是任何字符串, 用來唯一標識某個庫.該字符串可以是一個單字、幾個字符、甚至一個字母.數學共享庫的庫名為libm.so.5, 這里的標識字符為m, 版本號為5.libm.a則是靜態數學庫.X-Windows庫名為libX11.so.6, 這里使用X11作為庫的標識, 版本號為6.

            三.庫操作命令

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

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

            ?$ 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
            ?庫安裝到系統以后, 為了讓動態鏈接庫為系統所認識及共享, 就需要運行ldconfig.ldconfig命令的用途, 主要是在默認搜尋目錄(/lib和/usr/lib)以及動態庫配置文件/etc/ld.so.conf內所列的目錄下, 搜索出可共享的動態鏈接庫(格式如lib*.so*), 進而創建出動態裝入程序(ld.so)所需的連接和緩存文件.緩存文件默認為/etc/ld.so.cache, 此文件保存已排好序的動態鏈接庫名字列表, ldconfig通常在系統啟動時運行, 而當用戶安裝了一個新的動態鏈接庫時,就需要手工運行這個命令.

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

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

            ?-f CONF 指定動態鏈接庫的配置文件為CONF, 系統默認為/etc/ld.so.conf.

            ?-C CACHE 指定生成的緩存文件為CACHE, 系統默認的是/etc/ld.so.cache,文件存放已排好序的可共享的動態鏈接庫的列表.

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

            ?-r ROOT 改變應用程序的根目錄為ROOT.

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

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

            ?當某個查詢是第一次被發送到高速緩沖DNS服務器時, 高速緩沖DNS服務器就將此查詢的整個過程記錄下來, 在一定的時期內用它來回答所有相同的查詢, 從而減少整個DNS系統的負擔并且提高查詢速度.

            四.庫的升級

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

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

            Linux庫函數的升級是一項重要的工作, 往往與其它軟件包的升級有一定關聯作用, 所以操作前一定要備份文件.下面看一下如何把Glibc 2.2.4.13升級至2.3.2版本, 其過程如下:

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

            在GUN C網站下載的四個.gz壓縮文件, 解壓至一臨時目錄中:
            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.建立庫函數的安裝目錄
            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.改變數據庫的鏈接
            ln -s /usr/higlibc/lib/ld-linux.so.2 /lib/ld-linux.so.2

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

            更新/etc/ld.so.cache的內容, 列出每個庫的版本號, 掃描目錄和所要創建及更新的鏈接.

            ?6.更改GCC設置

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

            ?7.更新符號鏈接
            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.測試并完成

            五.高級共享庫特性
            ?1. soname

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

            soname 的關鍵功能是它提供了兼容性的標準.當要升級系統中的一個庫時, 并且新庫的 soname 和老的庫的 soname 一樣, 用舊庫連接生成的程序, 使用新的庫依然能正常運行.這個特性使得在 Linux 下, 升級使用共享庫的程序和定位錯誤變得十分容易.

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

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

            2. 共享庫裝載器

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

            文件 /etc/ld.so.conf 定義了標準系統庫的路徑.共享庫裝載器把它作為搜索路徑.為了改變這個設置, 必須以 root 身份運行 ldconfig 工具.這將更新 /etc/ls.so.cache 文件, 這個文件其實是裝載器內部使用的文件之一.

            3. 使用 dlopen

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

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

            當庫被裝入后, 可以把 dlopen() 返回的句柄作為給 dlsym() 的第一個參數, 以獲得符號在庫中的地址.使用這個地址, 就可以獲得庫中特定函數的指針, 并且調用裝載庫中的相應函數.

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

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

            /********************************************\
            |????歡迎轉載, 但請保留作者姓名和原文鏈接, 祝您進步并共勉!???? |
            \********************************************/


            1.2 A Keyword Distinction

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

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

            C++的struct 與 class有惱人的曖昧關系, 表面上struct里沒顯式說明存儲權限的全是public而class則全是private, 事實卻并非如此簡單當考慮到與C的兼容時, 尤其是對待C中的tricks時, 更是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中內存連續分布的, 但若考慮到
            ?? //這是在C++中, struct基本上就是類, 這類的數據成員與外來(參)變量的"tricky 捆綁式"
            ?? //內存布局將導致派生類的數據成員"插不進去"從而導致類的數據成員內存布局不連續!
            ?? //所以C的trick是非標準的不能濫用!

            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;
            ?? // ...
            };

            強烈不推薦這種種"淫巧",? 不過在C/C++混合編程時你還不得不用它:)
            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 閱讀(589) | 評論 (0)編輯 收藏

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

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

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

            胡錦濤主席訪問微軟重申保護知識產權決心
            2006.04.21? 來自:國際金融報 ??

              表示加強知識產權保護不僅對中國擴大對外開放和改善投資環境十分必要,而且對于加強中國自主創新能力也是不可或缺的。

              美國西雅圖消息當地時間4月18日下午,正在美國華盛頓州西雅圖訪問的中國國家主席胡錦濤,會見了華盛頓州州長葛瑞格爾。

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

              參觀微軟是胡錦濤此次訪美行程中極其重要的一個環節。在參觀了微軟公司的主要技術后,胡錦濤重申了中國加強知識產權保護的決心。他表示,此舉“不僅對中國擴大對外開放和改善投資環境”十分必要,而且“對于加強中國自主創新能力”也是不可或缺的。

              胡錦濤稱贊了比爾·蓋茨在微軟取得的成就,并說:“因為你,比爾·蓋茨先生是中國的朋友,我則是微軟的朋友。”他表示希望看到微軟和中國的合作,并歡迎微軟將來增加在中國的投資。

              就在胡錦濤開始訪美的當天,聯想與微軟簽訂12億美元的軟件購買協議,此前方正、同方及TCL等公司也簽訂了價值17億美元的軟件購買協議,為其生產的計算機預裝微軟Windows操作系統,以此抵制盜版軟件。

              微軟公司的高管們認為,胡錦濤的這次訪問象征著中國政府對知識產權的態度出現根本轉變。中國已開始強化在知識產權問題上的立場,因為加強對知識產權的保護符合中國自身的經濟發展利益。

              微軟首席技術官克瑞格·蒙迪表示,“我認為,一年多來,中國領導人已越過了一道坎,意識到知識產權對中國本身的未來要求也至關重要。”盡管問題不會在一夜之間改變,但他認為最近的幾則通告是一種“重大飛躍”。

              蒙迪說,中國仍是微軟優先考慮的重點,無論是作為一個市場還是未來市場的技術來源,盡管在知識產權方面存在一些困難。

              當天上午10時50分左右,胡錦濤乘坐的專機抵達西雅圖佩因機場。在機場發表書面講話時,胡錦濤指出,中美都是偉大的國家,擁有廣泛的共同利益和堅實的合作基礎,肩負著促進世界和平與發展的共同責任。一個健康穩定、不斷發展的中美關系不僅造福兩國人民,而且有利于亞太地區及世界的和平、穩定、繁榮。

              當晚在比爾·蓋茨豪宅為胡主席一行舉行的歡迎宴會上,美中關系全國委員會主席歐倫斯對胡錦濤此行給予了高度評價。他稱,“胡錦濤把訪美的第一站放在西雅圖,其實是用行動對解決中美貿易爭端作出承諾——中國愿意開放經濟、同美國加強合作。這就是一個‘負責任的利益相關者’所代表的含義。”

              據悉,胡錦濤將于當地時間19日參觀波音公司,然后飛往華盛頓與布什總統在白宮舉行會談,鑒于近期國際市場原油價格飆升,各界人士紛紛預計能源問題將成為此次會談的重要議題之一。

              胡錦濤對比爾·蓋茨家訪有深意

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

              比爾·蓋茨作為全球首富,同時也是先進科學技術的領導者之一,其創辦的微軟公司對全球科技和經濟發展已經發揮了并且還將繼續發揮引領作用。從胡主席對比爾·蓋茨的家訪,至少可以看出三點含義:

              一是表達中國政府維護公平貿易、打擊盜版的決心。中國作為全世界第二大PC市場,是國際投資者爭奪的對象。對于我國現實存在的軟件盜版問題,我國政府高度重視,外界也十分關注。加大反盜版行動的力度,既是促進國內經濟秩序健康發展的需要,也是對外國投資者的善意回應。

              在胡主席出訪前,信產部、國家版權局、商務部、財政部等于4月10日聯合下發《關于計算機預裝正版操作系統軟件有關問題的通知》,要求在我國境內生產的計算機,出廠時應當預裝正版操作系統軟件。而進口計算機在國內銷售,銷售前應當預裝正版操作系統軟件。同時規定計算機生產者和操作系統軟件提供者須按照規定報送計算機銷售數量、操作系統軟件的預裝數量。

              胡主席向蓋茨表示,希望看到微軟和中國的合作,歡迎微軟將來增加在中國的投資,并表示中國會在保護知識產權的問題上履行諾言。

              事實上,我國的反盜版行動直接促進了中國廠商與微軟公司的貿易。3家中國電腦制造商將宣布未來3年購買總價值4億美元的微軟Windows操作系統的計劃。

              二是體現中國領導人對科學技術、對知識分子的尊重。按照中國的傳統,家訪是一種很高的禮遇。中國政府歷來強調尊重知識、尊重人才,而比爾·蓋茨既是一位資本家,也是一位成功的創業者,是自主創新的典型代表。他的創業之路早已為中國人所津津樂道,在年輕人心目中,蓋茨堪稱一位英雄。

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

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

              三是表達中國努力建設創新型國家的雄心。

              今年1月9日,胡主席在全國科技大會上宣布中國將用15年時間建設創新型國家;科技大會召開3個月后,他借訪美之機,親自造訪微軟總部,考察微軟先進技術,顯然具有深意。

              毫無疑問,建設創新型國家需要體制和資金上的支持,但同時,在全社會營造“創新文化”更加重要。承認、尊重他人的科技成果,努力學習借鑒他人的先進經驗,應當是創新文化的基本要素。

              當中國國家主席與微軟領導人聚首之時,傳遞出的正是對中華文化優良傳統的繼承和弘揚,對外國文化有益成果的積極吸收和借鑒之意。

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

            /********************************************\
            |????歡迎轉載, 但請保留作者姓名和原文鏈接, 祝您進步并共勉!???? |
            \********************************************/


            C++對象模型(1)


            作者: Jerry Cat
            時間: 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 閱讀(533) | 評論 (0)編輯 收藏

            /********************************************\
            |????歡迎轉載, 但請保留作者姓名和原文鏈接, 祝您進步并共勉!???? |
            \********************************************/

            VC++的鏈接錯誤LNK2005


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

            編程中經常能遇到LNK2005錯誤——重復定義錯誤,其實LNK2005錯誤并不是一個很難解決的錯誤。弄清楚它形成的原因,就可以輕松解決它了。

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

            2.頭文件的包含重復。往往需要包含的頭文件中含有變量、函數、類的定義,在其它使用的地方又不得不多次包含之,如果頭文件中沒有相關的宏等防止重復鏈接的措施,那么就會產生LNK2005錯誤。解決辦法是在需要包含的頭文件中做類似的處理:#ifndef MY_H_FILE?? //如果沒有定義這個宏
            #define MY_H_FILE?? //定義這個宏
            …….?? //頭文件主體內容
            …….
            #endif
            上面是使用宏來做的,也可以使用預編譯來做,在頭文件中加入:
            #pragma once
            //頭文件主體
            3.使用第三方的庫造成的。這種情況主要是C運行期函數庫和MFC的庫沖突造成的。具體的辦法就是將那個提示出錯的庫放到另外一個庫的前面。另外選擇不同的C函數庫,可能會引起這個錯誤。微軟和C有兩種C運行期函數庫,一種是普通的函數庫:LIBC.LIB,不支持多線程。另外一種是支持多線程的:msvcrt.lib。如果一個工程里,這兩種函數庫混合使用,可能會引起這個錯誤,一般情況下它需要MFC的庫先于C運行期函數庫被鏈接,因此建議使用支持多線程的msvcrt.lib。所以在使用第三方的庫之前首先要知道它鏈接的是什么庫,否則就可能造成LNK2005錯誤。如果不得不使用第三方的庫,可以嘗試按下面所說的方法修改,但不能保證一定能解決問題,前兩種方法是微軟提供的:
            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錯誤的幾種情況,肯定還有其他的情況也可能造成這種錯誤,所以我不希望你在看完這篇文章以后,再遇到LNK2005錯誤時候,不動腦筋的想對號入座的排除錯誤。編程的過程就是一個思考的過程,所以還是多多開動你的頭腦,那樣收獲會更多!
            =======================================
            支持,我在社區里也看到了許多LINK 2005錯
            補充一點,就是一次在用第三方庫時,由于errno被重定義,用多種方法都不能解決,后查找MSDN,發現link有個選項/FORCE可以解決,在IDE下
            Project->Settings->Link頁,選categroy為custom,將force file output前打勾
            但會有警告
            warning LNK4088: image being generated due to /FORCE option; image may not run
            但的確解決了問題,這是由于VC對重定義比較嚴格,像BCB或GCC在庫中的重定義不會有任何警告或錯誤
            ========================================
            我發現的另外一個出現LINK2005的現象,好像是由于名稱空間而引起的。我在dos下寫的程序沒有問題,但是放在mfc中就出現了這個鏈接錯誤。因為起初圖省事,我在一個頭文件中寫了using namespace std,并且這個頭文件我多處使用,另外,我還使用了boost庫。后來,問題解決的方法非常奇怪,在一個頭文件中引用其他頭文件,這些頭文件的順序換一下就通過了,那個出現問題的頭文件中我使用了std::map,當我把這種容器使用模板代替后,鏈接就有沒事了。(例如:template<class coll>),后來感到模板技術還有這種效果,賺了!哈哈
            ========================================
            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編譯選項,而程序依賴的.lib可能使用/MDd選項編譯,造成鏈接沖突.

            統一編譯選項可回避此錯誤
            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


            注意:所有相關工程都應該選擇相同編譯選項
            ========================================
            微軟的MSDN中查到信息的

            可能的原因

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

            有關更多信息,請參閱知識庫文章:

            Q148652,PRB: LNK2005 Errors When Link C Run-Time Libraries Are Linked Before MFC Libraries。
            Q140440,FIX: Global Overloaded Delete Operator Causes LNK2005。
            Q184235,PRB: LNK2005 Errors on New and Delete When Defining _ATL_MIN_CRT。
            該錯誤之后為致命錯誤 LNK1169。
            =======================================
            有時候因為工程使用了預編譯頭文件并且是增量編譯,所以當你改動以后可能也會出現LNK2005錯誤,提示“XXXX已經在XXXX.obj文件中定義”的消息,這時候只要Rebuild All一般都能解決問題。這是因為頭文件的順序被改動等等操作造成的。
            最后要說明的:事物是在不斷變化中的,C++的標準在變化,編譯器也在變化,所以并不是所有的LNK2005錯誤都可以在這里找到答案,但是至少它能給你以提示。學習并思考才是正確的!

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

            <2007年7月>
            24252627282930
            1234567
            891011121314
            15161718192021
            22232425262728
            2930311234

            常用鏈接

            留言簿(7)

            隨筆檔案

            最新隨筆

            搜索

            •  

            最新評論

            閱讀排行榜

            評論排行榜

            久久国产精品成人免费| 久久国产成人午夜AV影院| 99久久精品国产一区二区蜜芽| 久久综合亚洲鲁鲁五月天| 久久久久无码专区亚洲av| 日本精品久久久久中文字幕| 2021精品国产综合久久| 精品久久人妻av中文字幕| 久久久精品2019免费观看| 欧美黑人又粗又大久久久| 香蕉久久av一区二区三区| 亚洲αv久久久噜噜噜噜噜| 亚洲人成伊人成综合网久久久| 精品熟女少妇AV免费久久| 精品无码久久久久国产动漫3d| 亚洲精品美女久久久久99| 国产精品无码久久综合| 久久国产精品-久久精品| 国产精品久久久久一区二区三区 | 亚洲AV日韩精品久久久久久久| 精品久久久中文字幕人妻| 2021久久精品国产99国产精品| 久久久精品免费国产四虎| 久久久精品国产Sm最大网站| 亚洲Av无码国产情品久久| 欧美噜噜久久久XXX| 成人a毛片久久免费播放| 久久天天婷婷五月俺也去| 久久久久亚洲av无码专区| 国产69精品久久久久9999| 久久精品人妻中文系列| 国产精品久久久天天影视| 日本欧美国产精品第一页久久| 色综合久久无码五十路人妻| 狠狠色伊人久久精品综合网 | 狠狠综合久久AV一区二区三区| 亚洲AV日韩AV永久无码久久| 国产精品日韩欧美久久综合| 伊人久久大香线蕉AV色婷婷色| 久久久中文字幕| 人妻无码αv中文字幕久久琪琪布|