1.C++ CODE(P29)
int i = 1;
void main(int argc, char ** argv){
int i = i;
}
/*main中的i未定义*/
2.计算X中1个个数(P31)
int onenumber(int x){
int count = 0;
while(x){
count++;
x = x&(x-1);
}
return count;
}
onenumber(9999)-----8
9999-----10011100001111
判断一个数是否为2^N
2, 4, 8-- 10, 100, 1000这样的数X按位与X-1对于0
//返回1---为2^N
//返回0--否
int fun(int x){
return !(x&(x-1))
}
3.printf计算参数时是从右到左压栈的。。
void main(int argc, char ** argv){
int b =3;
int arr[] = {6, 7, 8, 9, 10};
int *ptr = arr;
*(ptr++)+=123;
printf("%d, %d\n", *ptr, *(++ptr));
}
输出 8,8
4. 编程风格
if('A' == a){
a++;
}
if(a == 'A'){
a++;
}
第一种,当==写错成=时,因不能给常数复制程序会报错,可以检测错误。
S=Y+J*7;
for(int i=0; i<8; i++){
X = i+Y+J*7;
printf("%d", X);
}
S=Y+J*7;
for(int i=0; i<8; i++){
printf("%d", i+S);
}
第二种,把加法移除循环外,加速程序运行。
5.类型转换(P34)
void main(int argc, char ** argv){
float a = 1.0f;
cout << (int)a << endl; //浮点转成整形
cout << &a << endl; //变量地址
cout << (int &)a<< endl; //将指向a的指针变换成int型指针。因将float地址开始出 //sizeof(int)当成int开看待。(浮点数与整 //形在内存中不同的存储方式)
cout <<boolalpha << ( (int)a == (int &)a )<< endl;
a = 0.0f;
cout << (int)a << endl; //浮点转成整形
cout << &a << endl; //变量地址
cout << (int &)a<< endl; //将指向a的指针变换成int型指针。因将float地址开始出 //sizeof(int)当成int开看待。(浮点数与整形在内存 //中不同的存储方式)
cout <<boolalpha << ( (int)a == (int &)a )<< endl;
}
输出:false---true
(P34)
void main(int argc, char ** argv){
unsigned int a = 0xfffffff7;
unsigned char i = (unsigned char)a;//uint->uchar发生字节阶段(截断高位)
char *b = (char *)&a; //指针类型转变
printf("%08x, %08x", i, *b);
}
输出:000000f7,fffffff7
6.运算符优先级(P39)
void main(int argc, char ** argv){
unsigned char a = 0xA5;
unsigned char b = ~a>>4+1; //(~a)>>(4+1); 优先级从低到高>>,+,~
printf("%d", b);
}
输出:250
a=0xA5 ------16位寄存器 0x00 A5
取反 0xFF 5A
右移5位 0x07 fA = 250
7. 平均值(P40)
int f(int x, int y){
return (x&y)+((x^y)>>1)//x&y相同一半, 想(x^y)>>1 不同的一半
int max(int x, int y){
return (x+y+abs(x-y))/2;
}
abs函数--#include "math.h"
10.交换x,y--不用中间变量
*************
x = x - y;
y = x + y;
x = y - x;
x+y可能越界
**************
a^a = 0
a^0 = a
x=x^y;
y=x^y;
x=x^y;
10. c++调用被C编译器编译后的函数,加extern “C”(P40)
C++支持函数重载,C不支持函数重载。同一函数在C++和C中编译后的名字不同。(foo函数 C++编译后函数名_foo_int_int C编译后的函数名_foo).C++使用extern “C”连接C,解决名字匹配问题。
11 宏(P46)
结构体某个变量相对结构体的偏移量
#define FIND(struc, e) (size_t)&(((struc *)0)->e)
一年中的秒数(忽略闰年)
#define SENCONDS_PER_YEAR (60*60*24*365)UL
最小值
#define MIN(x, y) ( (x) >= (y) ? (y) : (x) )
12 const用途(P47) *********
1 定义常量
2, 修饰函数的参数。参数只能读,不能修改。(可防止意外改动,提高程序的健壮性)
13 const和#define区别******
都可以定义常量。const常量有类型,define无类型。编译器可以对const常量类型进行检查,而define只是简单的字符替换,可能会出现意想不到的结果。
C编译器不把const看成编译期间的常量
const size = 100;
char buf[size]; //编译错误。。。
C++中带有const函数的只能修改带有mutable成员变量。
class C{
public:
int incr() const{
m++; //right
d++; //wrong
}
private:
mutable int m;
int d;
}
14 sizeof strlen
1. char * str = "123";
sizeof(str) = 4;//编译器在后面加了\0
strlen(str) = 3;
2. char str[] = "123";
sizeof(str) = 4;//编译器在后面加了\0
strlen(str) = 3;
2. char str[100] = "123";
sizeof(str) = 100;
strlen(str) = 3;
当str[10]=“0123456789”,编译器报错arry bounds overflow。
15.
结构体长度
一、结构体变量中成员的偏移量必须是成员大小的整数倍(0被认为是任何数的整数倍)
二、结构体大小必须是所有成员大小的整数倍。
struct{
short a; //偏移量0
short b; //偏移量2
short c; //偏移量4
}
总长度4+2 = 6;满足第二条件
struct{
long a; //偏移量0
short b; //偏移量4
}
总长度4+2 = 6;不满足第二条件,长度有6变为8;
*****************
计算对象的大小,只看其中的成员变量。内存对齐情况,参考结构体大小计算。
sizeof只计算栈中分配的大小。static变量不计算在内。
class A1{
public:
int a;
static int b;
A1();
~A!();
}
sizeof(A1)=4;
class A2{
public:
int a;
char b;
}
sizeof(A2) =8;
sizeof运算符 strlen函数
int *b[10]; sizeof(b)=10*4=40
int **a[3][4]; sizeof(a)=3*4*4=48
16.内联函数和宏定义(P60)
区别:
1.内联函数嵌入到目标文件中,不用中断调用,加快程序运行速度。宏定义编译时的代码替换
2.内联函数检测参数类型,宏定义则没有。内联更安全,但是是以牺牲存储空间为代价。
内联函数用处:
1.代码被重复调用
2.函数只有简单的几行
17 指针 引用区别(P62)
1.非空区别。指针可以为空。引用初始化必须赋初值
2.修改区别。指针可以修改。引用不可以更改
3.合法性区别。指针测试是否为空(strlen)。引用必须测试其合法性
18 指针合法性(P66)
char *strA(){
char str[] = "abcd"; //堆栈空间。函数推出,堆栈空间无效。
return str;
}
修改为
char *strA(){
static char str[] = "abcd"; //静态存储空间
return str;
}
char *str="avdd"; //全局空间,只读。str[0]='1'出错。
char str[] = "abcd"; //局部空间。str[0] = '1'有效。
19 指针的减法(指针类型的差值)(P68)
int a[3]={0, 1, 2};
int *p, *q;
p = a;
q = &a[2];
cout<<a[q-p]<<endl;
输出为:a[p-q]=a[8/sizof(int)]=a[2]=2;
20.代码输出 1
class A{
public:
A() {m_a =1; m_b=2;}
~A(){};
void fun(){printf("%d%d", m_a, m_b);}
private:
int m_a;
int m_b;
};
class B{
public:
B() {m_a =3;}
~A(){};
void fun(){printf("%d", m_a);}
private:
int m_a;
};
void main(){
A a;
P* pb = (B*)(&a);
pb->fun();
}
21.
A.函数的形参在函数未调用之前分配存储空间 // 调用时分配内存
B.若函数的定义出现在主函数之前,则可以不必再说明 //函数需在调用之前什么,与主函数没有什么关系
C.若一个函数没有返回值,则什么值都不返回 //main 默认返回0
D.一般来说,函数的形参和实参的类型一致
22 s.p[i]====*(s.p+i)
struct S{
int i;
int *p;
}
main(){
S s;
int *p = &s.i;
p[0] = 4;
p[1] = 3;
s.p =p;
s.p[1] = 1;
s.p[0] = 2; //程序崩溃。 *((int *)1) = 2;
23函数指针
函数指针 void (*f)();
返回指针函数 void *f();
const指针 const char *;
指向const变量的指针 char * const;
指向const变量的const指针 const char *const;
24 一位数组取指针,变为指向二维数组的指针
int a[] = {1, 2, 3, 4, 5};
int *ptr = (int *)(&a +1) //等价于a+6
printf(" %d %d" , *(a+1), *(ptr -1));
输出为2,5
25. 迷途指针 空指针
迷途指针 -- delete一个指针,释放内存,但是指针还存在。不安全,通过赋值为0变为空指针。
指针指向内存位置0;
26 malloc/free new/delete区别
1.malloc/free函数 new/delete运算符
2. new/delete为对象分配内存。对象初始化时调用构造函数,消亡前调用析构函数,malloc/free做不到。
int i = 1;
void main(int argc, char ** argv){
int i = i;
}
/*main中的i未定义*/
2.计算X中1个个数(P31)
int onenumber(int x){
int count = 0;
while(x){
count++;
x = x&(x-1);
}
return count;
}
onenumber(9999)-----8
9999-----10011100001111
判断一个数是否为2^N
2, 4, 8-- 10, 100, 1000这样的数X按位与X-1对于0
//返回1---为2^N
//返回0--否
int fun(int x){
return !(x&(x-1))
}
3.printf计算参数时是从右到左压栈的。。
void main(int argc, char ** argv){
int b =3;
int arr[] = {6, 7, 8, 9, 10};
int *ptr = arr;
*(ptr++)+=123;
printf("%d, %d\n", *ptr, *(++ptr));
}
输出 8,8
4. 编程风格
if('A' == a){
a++;
}
if(a == 'A'){
a++;
}
第一种,当==写错成=时,因不能给常数复制程序会报错,可以检测错误。
S=Y+J*7;
for(int i=0; i<8; i++){
X = i+Y+J*7;
printf("%d", X);
}
S=Y+J*7;
for(int i=0; i<8; i++){
printf("%d", i+S);
}
第二种,把加法移除循环外,加速程序运行。
5.类型转换(P34)
void main(int argc, char ** argv){
float a = 1.0f;
cout << (int)a << endl; //浮点转成整形
cout << &a << endl; //变量地址
cout << (int &)a<< endl; //将指向a的指针变换成int型指针。因将float地址开始出 //sizeof(int)当成int开看待。(浮点数与整 //形在内存中不同的存储方式)
cout <<boolalpha << ( (int)a == (int &)a )<< endl;
a = 0.0f;
cout << (int)a << endl; //浮点转成整形
cout << &a << endl; //变量地址
cout << (int &)a<< endl; //将指向a的指针变换成int型指针。因将float地址开始出 //sizeof(int)当成int开看待。(浮点数与整形在内存 //中不同的存储方式)
cout <<boolalpha << ( (int)a == (int &)a )<< endl;
}
输出:false---true
(P34)
void main(int argc, char ** argv){
unsigned int a = 0xfffffff7;
unsigned char i = (unsigned char)a;//uint->uchar发生字节阶段(截断高位)
char *b = (char *)&a; //指针类型转变
printf("%08x, %08x", i, *b);
}
输出:000000f7,fffffff7
6.运算符优先级(P39)
void main(int argc, char ** argv){
unsigned char a = 0xA5;
unsigned char b = ~a>>4+1; //(~a)>>(4+1); 优先级从低到高>>,+,~
printf("%d", b);
}
输出:250
a=0xA5 ------16位寄存器 0x00 A5
取反 0xFF 5A
右移5位 0x07 fA = 250
7. 平均值(P40)
int f(int x, int y){
return (x&y)+((x^y)>>1)//x&y相同一半, 想(x^y)>>1 不同的一半
}
int max(int x, int y){
return (x+y+abs(x-y))/2;
}
abs函数--#include "math.h"
10.交换x,y--不用中间变量
*************
x = x - y;
y = x + y;
x = y - x;
x+y可能越界
**************
a^a = 0
a^0 = a
x=x^y;
y=x^y;
x=x^y;
10. c++调用被C编译器编译后的函数,加extern “C”(P40)
C++支持函数重载,C不支持函数重载。同一函数在C++和C中编译后的名字不同。(foo函数 C++编译后函数名_foo_int_int C编译后的函数名_foo).C++使用extern “C”连接C,解决名字匹配问题。
11 宏(P46)
结构体某个变量相对结构体的偏移量
#define FIND(struc, e) (size_t)&(((struc *)0)->e)
一年中的秒数(忽略闰年)
#define SENCONDS_PER_YEAR (60*60*24*365)UL
最小值
#define MIN(x, y) ( (x) >= (y) ? (y) : (x) )
12 const用途(P47) *********
1 定义常量
2, 修饰函数的参数。参数只能读,不能修改。(可防止意外改动,提高程序的健壮性)
13 const和#define区别******
都可以定义常量。const常量有类型,define无类型。编译器可以对const常量类型进行检查,而define只是简单的字符替换,可能会出现意想不到的结果。
C编译器不把const看成编译期间的常量
const size = 100;
char buf[size]; //编译错误。。。
C++中带有const函数的只能修改带有mutable成员变量。
class C{
public:
int incr() const{
m++; //right
d++; //wrong
}
private:
mutable int m;
int d;
}
14 sizeof strlen
1. char * str = "123";
sizeof(str) = 4;//编译器在后面加了\0
strlen(str) = 3;
2. char str[] = "123";
sizeof(str) = 4;//编译器在后面加了\0
strlen(str) = 3;
2. char str[100] = "123";
sizeof(str) = 100;
strlen(str) = 3;
当str[10]=“0123456789”,编译器报错arry bounds overflow。
15.
结构体长度
一、结构体变量中成员的偏移量必须是成员大小的整数倍(0被认为是任何数的整数倍)
二、结构体大小必须是所有成员大小的整数倍。
struct{
short a; //偏移量0
short b; //偏移量2
short c; //偏移量4
}
总长度4+2 = 6;满足第二条件
struct{
long a; //偏移量0
short b; //偏移量4
}
总长度4+2 = 6;不满足第二条件,长度有6变为8;
*****************
计算对象的大小,只看其中的成员变量。内存对齐情况,参考结构体大小计算。
sizeof只计算栈中分配的大小。static变量不计算在内。
class A1{
public:
int a;
static int b;
A1();
~A!();
}
sizeof(A1)=4;
class A2{
public:
int a;
char b;
}
sizeof(A2) =8;
sizeof运算符 strlen函数
int *b[10]; sizeof(b)=10*4=40
int **a[3][4]; sizeof(a)=3*4*4=48
16.内联函数和宏定义(P60)
区别:
1.内联函数嵌入到目标文件中,不用中断调用,加快程序运行速度。宏定义编译时的代码替换
2.内联函数检测参数类型,宏定义则没有。内联更安全,但是是以牺牲存储空间为代价。
内联函数用处:
1.代码被重复调用
2.函数只有简单的几行
17 指针 引用区别(P62)
1.非空区别。指针可以为空。引用初始化必须赋初值
2.修改区别。指针可以修改。引用不可以更改
3.合法性区别。指针测试是否为空(strlen)。引用必须测试其合法性
18 指针合法性(P66)
char *strA(){
char str[] = "abcd"; //堆栈空间。函数推出,堆栈空间无效。
return str;
}
修改为
char *strA(){
static char str[] = "abcd"; //静态存储空间
return str;
}
char *str="avdd"; //全局空间,只读。str[0]='1'出错。
char str[] = "abcd"; //局部空间。str[0] = '1'有效。
19 指针的减法(指针类型的差值)(P68)
int a[3]={0, 1, 2};
int *p, *q;
p = a;
q = &a[2];
cout<<a[q-p]<<endl;
输出为:a[p-q]=a[8/sizof(int)]=a[2]=2;
20.代码输出 1
class A{
public:
A() {m_a =1; m_b=2;}
~A(){};
void fun(){printf("%d%d", m_a, m_b);}
private:
int m_a;
int m_b;
};
class B{
public:
B() {m_a =3;}
~A(){};
void fun(){printf("%d", m_a);}
private:
int m_a;
};
void main(){
A a;
P* pb = (B*)(&a);
pb->fun();
}
21.
A.函数的形参在函数未调用之前分配存储空间 // 调用时分配内存
B.若函数的定义出现在主函数之前,则可以不必再说明 //函数需在调用之前什么,与主函数没有什么关系
C.若一个函数没有返回值,则什么值都不返回 //main 默认返回0
D.一般来说,函数的形参和实参的类型一致
22 s.p[i]====*(s.p+i)
struct S{
int i;
int *p;
}
main(){
S s;
int *p = &s.i;
p[0] = 4;
p[1] = 3;
s.p =p;
s.p[1] = 1;
s.p[0] = 2; //程序崩溃。 *((int *)1) = 2;
23函数指针
函数指针 void (*f)();
返回指针函数 void *f();
const指针 const char *;
指向const变量的指针 char * const;
指向const变量的const指针 const char *const;
24 一位数组取指针,变为指向二维数组的指针
int a[] = {1, 2, 3, 4, 5};
int *ptr = (int *)(&a +1) //等价于a+6
printf(" %d %d" , *(a+1), *(ptr -1));
输出为2,5
25. 迷途指针 空指针
迷途指针 -- delete一个指针,释放内存,但是指针还存在。不安全,通过赋值为0变为空指针。
指针指向内存位置0;
26 malloc/free new/delete区别
1.malloc/free函数 new/delete运算符
2. new/delete为对象分配内存。对象初始化时调用构造函数,消亡前调用析构函数,malloc/free做不到。