《Thinking in C++》读书笔记——Chapter 3: The C in C++ (2)

Chapter3: The C in C++ (2)

Bitwise operators

(1)The bitwise exclusive or, or xor (^) produces a one in the output bit if one or the other input bit is a one, but not both.

 

(2)Bitwise operators can be combined with the = sign to unite the operation and assignment: &=, |=, and ^= are all legitimate operations (since ~ is a unary operator it cannot be combined with the = sign).

 

Casting Operators

In some situations it forces the compiler to treat data as if it were (for instance) larger than it really is, so it will occupy more space in memory; this can trample over other data. This usually occurs when casting pointers.

(1)static_cast

static_cast用法示例:

 1 //: C03:static_cast.cpp
 2 void func(int) {}
 3     int main() {
 4     int i = 0x7fff; // Max pos value = 32767
 5     long l;
 6     float f;
 7 // (1) Typical castless conversions:( to highlight these promotions.)
 8     l = i;
 9     f = i;
10 // Also works:
11     l = static_cast<long>(i);
12     f = static_cast<float>(i);
13 // (2) Narrowing conversions:( will often give you a warning)
14     i = l; // May lose digits
15     i = f; // May lose info
16 // Says "I know," eliminates warnings:
17     i = static_cast<int>(l);
18     i = static_cast<int>(f);
19     char c = static_cast<char>(i);
20 // (3) Forcing a conversion from void* :( Assigning from a void* is not allowed without a cast in C++)
21 void* vp = &i;
22 // Old way produces a dangerous conversion:
23     float* fp = (float*)vp;
24 // The new way is equally dangerous:
25     fp = static_cast<float*>(vp);
26 // (4) Implicit type conversions, normally
27 // performed by the compiler:( highlights the action)
28     double d = 0.0;
29     int x = d; // Automatic type conversion
30     x = static_cast<int>(d); // More explicit
31     func(d); // Automatic type conversion
32     func(static_cast<int>(d)); // More explicit
33 } ///:~
(2)const_cast

If you want to convert from a const to a nonconst or from a volatile to a nonvolatile, you use const_cast.

 

(3)reinterpret_cast

This is the least safe of the casting mechanisms, and the one most likely to produce bugs. A reinterpret_cast pretends that an object is just a bit pattern that can be treated (for some dark purpose) as if it were an entirely different type of object.

reinterpret_cast用法以及结果示例:

//: C03:reinterpret_cast.cpp
#include <iostream>
using namespace std;
const int sz = 100;
struct X { int a[sz]; };
void print(X* x) {
    for(int i = 0; i < sz; i++)
        cout << x->a[i] << ' ';
    cout << endl << "--------------------" << endl;
}
int main() {
    X x;
    print(&x);
    int* xp = reinterpret_cast<int*>(&x);
    for(int* i = xp; i < xp + sz; i++)
        *i = 0;
// Can't use xp as an X* at this point
// unless you cast it back:
    print(reinterpret_cast<X*>(xp));
// In this example, you can also just use
// the original identifier:
    print(&x);
} ///:~
        

结果如下:

(4)dynamic_cast

For type-safe downcasting. (以后介绍)

 

sizeof – an operator by itself

Note that sizeof is an operator, not a function. If you apply it to a type, it must be used with the parenthesized form shown above, but if you apply it to a variable you can use it without parentheses

 

Composite type creation

(1)Aliasing names with typedef
(2)Combining variables with struct
(3)Clarifying programs with enum

An enumerated data type is useful when you want to keep track of some sort of feature:

 1 //: C03:Enum.cpp
 2 // Keeping track of shapes
 3 enum ShapeType {
 4 circle,
 5 square,
 6 rectangle
 7 }; // Must end with a semicolon like a struct
 8 int main() {
 9     ShapeType shape = circle;
10 // Activities here....
11 // Now do something based on what the shape is:
12     switch(shape) {//shape is really just an int in C
13         case circle: /* circle stuff */ break;
14         case square: /* square stuff */ break;
15         case rectangle: /* rectangle stuff */ break;
16     }
17 } ///:~
18         

If you don’t like the way the compiler assigns values, you can do it yourself, like this:

 1 enum ShapeType { 2 circle = 10, square = 20, rectangle = 50 3 }; 

If you give values to some names and not to others, the compiler will use the next integral value. For example,

 1 enum snap { crackle = 25, pop }; 

The compiler gives pop the value 26.

 

If you have an instance of an enumeration color called a. In C you can say a++, but in C++ you can’t.

 

(4)Saving memory with union

>>A union piles all the data into a single space; it figures out the amount of space necessary for the largest item you’ve put in the union, and makes that the size of the union.

 

>>All the addresses of the union variables are the same (in a class or struct, the addresses are different).

 

(5)Arrays

>>Arrays cannot be passed by value.

 

>>Just passing the address of an array isn’t enough information; you must always be able to know how big the array is inside your function, so you don’t run off the end of that array.

 

>>argv[0] is the path and name of the program itself.

 

>>All you get from the command-line is character arrays; if you want to treat an argument as some other type, you are responsible for converting it inside your program.

 

>>The bits inside of floats and doubles are divided into three regions: the exponent, the mantissa, and the sign bit

 

>>You cannot add two pointers, and if you subtract pointers the result is the number of elements between the two pointers. However, you can add or subtract an integral value and a pointer.

 

The C assert( ) macro

When you use assert( ), you give it an argument that is an expression you are “asserting to be true.” The preprocessor generates code that will test the assertion. If the assertion isn’t true, the program will stop after issuing an error message telling you what the assertion was and that it failed.

 

1 //: C03:Assert.cpp
2 // Use of the assert() debugging macro
3 #include <cassert> // Contains the macro
4 using namespace std;
5 int main() {
6     int i = 100;
7     assert(i != 100); // Fails
8 } ///:~

结果如下:

 

When you are finished debugging, you can remove the code generated by the macro by placing the line:

 #define NDEBUG 

in the program before the inclusion of <cassert>, or by defining NDEBUG on the compiler command line. NDEBUG is a flag used in <cassert>to change the way code is generated by the macros.

 

Function addresses(函数指针,考点)

(1)To define a pointer to a function that has no arguments and no return value, you say: void (*funcPtr)(); funcPtr is a pointer to a function that takes no arguments and returns void. But void *funcPtr()declaring a function (that returns a void*) rather than defining a variable.

 

(2)void * (*(*fp1)(int))[10]: fp1 is a pointer to a function that takes an integer argument and returns a pointer to an array of 10 void pointers.

(3)float (*(*fp2)(int,int,float))(int): fp2 is a pointer to a function that takes three arguments (int, int, and float) and returns a pointer to a function that takes an integer argument and returns a float.

(4)typedef double (*(*(*fp3)())[10])();fp3 a;: An fp3 is a pointer to a function that takes no arguments and returns a pointer to an array of 10 pointers to functions that take no arguments and return doubles.” Then it says “a is one of these fp3 types.”

(5)int (*(*f4())[10])(): f4 is a function that returns a pointer to an array of 10 pointers to functions that return integers.

 

(6)Using a function pointer:

 1 //: C03:PointerToFunction.cpp
 2 // Defining and using a pointer to a function
 3 #include <iostream>
 4 using namespace std;
 5 void func() {
 6     cout << "func() called..." << endl;
 7 }
 8 int main() {
 9     void (*fp)(); // Define a function pointer
10     fp = func; // Initialize it
11     (*fp)(); // Dereferencing calls the function
12     void (*fp2)() = func; // Define and initialize
13     (*fp2)();
14 } ///:~

 

(7)Arrays of pointers to functions:

This supports the concept of table-driven code; instead of using conditionals or case statements, you select functions to execute based on a state variable.

一个示例:

 1 //: C03:FunctionTable.cpp
 2 // Using an array of pointers to functions
 3 #include <iostream>
 4 using namespace std;
 5 // A macro to define dummy functions:
 6 #define DF(N) void N() { \
 7 cout << "function " #N " called..." << endl; }
 8 DF(a); DF(b); DF(c); DF(d); DF(e); DF(f); DF(g);
 9 void (*func_table[])() = { a, b, c, d, e, f, g };
10 int main() {
11     while(1) {
12         cout << "press a key from 'a' to 'g' "
13             "or q to quit" << endl;
14         char c, cr;
15         cin.get(c); cin.get(cr); // second one for CR
16         if ( c == 'q' )
17             break; // ... out of while(1)
18         if ( c < 'a' || c > 'g' )
19             continue;
20         (*func_table[c - 'a'])();
21     }
22 } ///:~
23     

 

转载于:https://www.cnblogs.com/solare/p/3700102.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值