|
1 <?xml version="1.0" encoding="utf-8"?> |
|
2 <!-- Copyright (c) 2007-2010 Nokia Corporation and/or its subsidiary(-ies) All rights reserved. --> |
|
3 <!-- This component and the accompanying materials are made available under the terms of the License |
|
4 "Eclipse Public License v1.0" which accompanies this distribution, |
|
5 and is available at the URL "http://www.eclipse.org/legal/epl-v10.html". --> |
|
6 <!-- Initial Contributors: |
|
7 Nokia Corporation - initial contribution. |
|
8 Contributors: |
|
9 --> |
|
10 <!DOCTYPE concept |
|
11 PUBLIC "-//OASIS//DTD DITA Concept//EN" "concept.dtd"> |
|
12 <concept id="GUID-8675AC01-E2D8-425C-899F-12BE99345AA9" xml:lang="en"><title>C++ |
|
13 and Machine Architecture</title><shortdesc>The C++ language, following its foundation in C, is close to the |
|
14 machine architecture. This allows applications to be implemented efficiently, |
|
15 but, especially for developers new to the language, presents some issues of |
|
16 which you need to be aware. This topic reviews the basic language features |
|
17 from this perspective, and discusses how the resulting issues are handled.</shortdesc><prolog><metadata><keywords/></metadata></prolog><conbody> |
|
18 <section> <title>Arithmetic types</title> <p>An <codeph>int</codeph> is |
|
19 usually implemented as the natural machine word size of the particular implementation. |
|
20 This is 32 bits in most modern machines. It was 16 bits in older machines, |
|
21 and in a few machines it may even be 64 bits. </p><p>Similarly, a pointer |
|
22 (a <codeph>void*</codeph>, for instance) is usually implemented as a machine |
|
23 word but, in some machines with special architectures, a pointer may be more |
|
24 complex. </p><p>It is assumed that Symbian is implemented on a machine |
|
25 with a 32-bit or greater machine word, and 32-bit pointers. The types <codeph>TInt</codeph> and <codeph>TUint</codeph> are<codeph> typedefed</codeph> onto the built-in <codeph>int</codeph> and <codeph>unsigned int</codeph> types, |
|
26 and are guaranteed to be at least 32 bits. </p><p>When you need a specific |
|
27 size, regardless of implementation, use a sized type. Several of these are |
|
28 available: </p><table id="GUID-8E1CEF20-AF41-4980-AA56-5CBF2B7F6A9E"> |
|
29 <tgroup cols="2"><colspec colname="col1"/><colspec colname="col2"/> |
|
30 <tbody> |
|
31 <row> |
|
32 <entry><p><codeph>TInt32</codeph>, <codeph>TUint32</codeph> </p> </entry> |
|
33 <entry><p>32-bit signed and unsigned integer</p> <p> In each case, the |
|
34 representation is a 32-bit machine word which, in the ARM architecture, must |
|
35 be aligned to a four-byte boundary. The compiler ensures that this is always |
|
36 the case.</p> </entry> |
|
37 </row> |
|
38 <row> |
|
39 <entry><p><codeph>TInt8</codeph>, <codeph>TUint8</codeph>, <codeph>TText8</codeph></p> </entry> |
|
40 <entry><p>8-bit signed and unsigned integer, and 8-bit character </p><p>In |
|
41 each case, the representation is an 8-bit byte, which has no specific alignment |
|
42 requirements. </p></entry> |
|
43 </row> |
|
44 <row> |
|
45 <entry><p><codeph>TInt16</codeph>, <codeph>TUint16</codeph>, <codeph>TText16</codeph> </p></entry> |
|
46 <entry><p>16-bit signed and unsigned integer, and 16-bit character </p><p>In |
|
47 each case, the representation is a 16-bit halfword, which should be aligned |
|
48 to a two-byte boundary. </p></entry> |
|
49 </row> |
|
50 <row> |
|
51 <entry><p><codeph>TInt64</codeph>, <codeph>TUint64</codeph> </p></entry> |
|
52 <entry><p>64-bit signed and unsigned integer </p><p>These are typedefed |
|
53 to appropriate built-in types for the compiler being used (long long, and |
|
54 unsigned long long for ARM RVCT). </p></entry> |
|
55 </row> |
|
56 <row> |
|
57 <entry><p><codeph>TReal</codeph>, <codeph>TReal64</codeph> </p></entry> |
|
58 <entry><p>Double-precision floating point, IEEE754 64-bit representation |
|
59 This is the floating-point type recommended for general use. </p><p>You |
|
60 are recommended to perform operations in integer arithmetic if possible (for |
|
61 instance, most GUI calculations), and to use floating-point only when the |
|
62 problem demands it (for instance, a spreadsheet application). </p><p>On |
|
63 processors that have floating point hardware, the compiler generates host |
|
64 instructions which use that hardware directly. On processors which don't have |
|
65 a floating point unit, the compiler implements the calculations in software. |
|
66 </p></entry> |
|
67 </row> |
|
68 <row> |
|
69 <entry><p><codeph>TReal32</codeph> </p></entry> |
|
70 <entry><p>32-bit floating point </p><p>This is smaller and quicker, but |
|
71 should only be used when space and/or time are at a true premium, as its precision |
|
72 is unsatisfactory for many applications. </p></entry> |
|
73 </row> |
|
74 </tbody> |
|
75 </tgroup> |
|
76 </table> </section> |
|
77 <section><title>Compound types</title><p>Apart from classes, C++ inherits |
|
78 from C various other types of compounding. </p><p>A struct maps an area |
|
79 of memory: </p><codeblock xml:space="preserve">struct TEg |
|
80 { |
|
81 TInt iInt; // offset 0, 4 bytes |
|
82 TText8 iText; // offset 4, 1 byte |
|
83 // 3 wasted bytes |
|
84 TReal iReal; // offset 8, 8 bytes |
|
85 } // total length = 16 bytes</codeblock><fig id="GUID-70477651-EC14-4321-ACA5-79CEE4AEC69E"> |
|
86 <image href="GUID-7E801A44-4509-5AC0-88D5-7DEA1AF7969D_d0e2078_href.png" placement="inline"/> |
|
87 </fig><p>Structures are regarded as <codeph>T</codeph> types: that is they |
|
88 may not own heap-allocated resources such as <codeph>C</codeph> type classes. |
|
89 </p><p>An array contains many built-ins or other types </p><codeblock xml:space="preserve">TInt a[32]; // 32 TInts, = 128 bytes |
|
90 S b[3]; // 3 Ss, = 48 bytes </codeblock><p>The main disadvantage of using |
|
91 C++ arrays is that there is no automatic checking of index values. For this |
|
92 reason, and to support more complex containers, C++ has evolved the Standard |
|
93 Template Library (STL). Symbian OS does not use STL, but provides its own |
|
94 range of efficient container classes, for fixed, dynamic, and associative |
|
95 arrays. For details, see <xref href="GUID-2F64B579-73D3-548A-9104-16483AF77BCB.dita">Dynamic |
|
96 Arrays</xref>. </p></section> |
|
97 <section><title>Pointers</title><p>A pointer is a memory address. If you can |
|
98 take the address of an object, then you can refer to it by pointer:</p><codeblock xml:space="preserve">S* ps; // pointer to an S |
|
99 ps=&s // take address of existing S |
|
100 </codeblock><p>A pointer is a 32-bit machine word, and could point to anything.</p><fig id="GUID-D33AB198-0B62-4391-B86D-088595AE6B8B"> |
|
101 <image href="GUID-045F3455-2B5A-5B20-ABCE-ED202DC5078A_d0e2109_href.png" placement="inline"/> |
|
102 </fig><p>The specifier is placed next to the type rather than the name. </p><p>There |
|
103 is often a need to refer to memory as anything: for this, a <codeph>void*</codeph> pointer |
|
104 is used in C++. In Symbian, a <codeph>TAny*</codeph> may be referred to instead. |
|
105 A <codeph>TAny*</codeph> is a pointer to anything. </p></section> |
|
106 <section><title>Strings</title><p>In C++, the basic string is an array of |
|
107 characters:</p><codeblock xml:space="preserve">char* hello="hello";</codeblock><p>This statement |
|
108 does two things: firstly, it sets aside six bytes of memory containing the |
|
109 characters 'h', 'e', 'l', 'l', 'o', '\0'. Secondly, it sets the pointer hello |
|
110 to contain the address of the first of those bytes. </p><fig id="GUID-08C1AF40-8D93-414E-B103-1E57AB17480F"> |
|
111 <image href="GUID-512D0DA7-0BC2-534F-9233-11F46D285CA6_d0e2138_href.png" placement="inline"/> |
|
112 </fig><p>Functions accessing the string rely on this address as its starting |
|
113 point, and the terminating <codeph>\0</codeph> to indicate its end. Functions |
|
114 which manipulate the string must either deliberately not extend it, or must |
|
115 have some cue as to the amount of memory reserved for the string (beyond the |
|
116 trailing<codeph>\0</codeph>) so they know how much it can be extended. This |
|
117 leads to an awkward programming style, and every C++ library provides a way |
|
118 to manipulate strings more elegantly. The Symbian platform solution is <i>descriptors</i>: |
|
119 these are introduced in <xref href="GUID-9C51D27D-BEDB-59D1-8F0E-8426B8FF2230.dita">Descriptors</xref></p></section> |
|
120 <section><title>Functions</title><p>Functions are a piece of code which can |
|
121 be called and executed from anywhere else in a program. The stack is used |
|
122 to pass parameters and to contain local variables. The stack is often augmented |
|
123 by machine registers, especially in a register-rich processor such as the |
|
124 ARM, so that memory is often not used. But, conceptually, there is a stack, |
|
125 and for the purposes of this explanation it is convenient to consider the |
|
126 stack as if it were implemented entirely in memory. </p><p>Parameters are |
|
127 passed by copying or evaluating onto the called functions stack frame. It |
|
128 is bad practice to pass large parameters, such as an entire struct, or, in |
|
129 fact, anything beyond two machine words in size, because this involves excessive |
|
130 copying. Instead, a pointer or a reference should be used to pass the address, |
|
131 instead of the data itself. </p><p>In a multi-tasking system such as Symbian, |
|
132 each thread has its own stack, which is a pre-allocated area of memory. Each |
|
133 function then allocates its own frame from the stack on entry, and de-allocates |
|
134 it on exit. The advantage of the stack mechanism is that allocation and de-allocation |
|
135 are very rapid indeed— just a couple of instructions. Also, the lifetime of |
|
136 any variable on the stack is very well defined: it is the lifetime of its |
|
137 owning function, or, in fact, its owning block, since functions may have blocks |
|
138 within them. </p><p>When a function returns, its stack memory is still there: |
|
139 it is just not allocated. The stack memory will be re-used by the next function |
|
140 that is called. A potential source of error is to allocate an object on a |
|
141 functions stack frame, and then return a pointer to it: </p><codeblock xml:space="preserve">TEg* foo() |
|
142 { |
|
143 TEg s; |
|
144 TEg* ps=&s |
|
145 return ps; // !! error !! |
|
146 } |
|
147 </codeblock><p>This pointer will not be valid for long, because the memory |
|
148 will be re-used when the next function is called. You should never allow this |
|
149 to happen. This error is so obvious that a compiler will trap it. But it can |
|
150 occur in more subtle forms: </p><codeblock xml:space="preserve">foo(CContainer* aContainer) |
|
151 { |
|
152 TEg s; |
|
153 TEg* ps=&s |
|
154 aContainer->iMember=ps; |
|
155 } |
|
156 </codeblock><p>These cannot be trapped so easily. </p></section> |
|
157 <section><title>Heap</title><p>Each thread also has a heap. You can allocate |
|
158 and de-allocate objects on the heap at will, and refer to them by pointer. |
|
159 The benefit of a heap is that the lifetime of an object is entirely within |
|
160 your control. This power comes with responsibility: you must not forget to |
|
161 de-allocate objects once you have finished with them, and you must not use |
|
162 pointers to objects that have been de-allocated. </p></section> |
|
163 </conbody></concept> |