Note1:指针有两个值:P 和*P
void fun(int *p)//形参 不分配空间
{
*p += 100;
int a = 10;
p = &a;
}
int main()
{
int x = 10;
int *s = &x;
fun(s);
cout << *s <<endl<< x;
return 0;
}
分析:在fun()结束后,s仍然指向x。对p本身的改变,对s不变。
p=&a;后 p指向a的地址。 s仍是x的地址,并未改变。
###################################################################
Note2:
void Swap_a(int a,int b)//传值操作:形参改变,但是实参不变
{
int c = a;
a = b;
b = c;
}
void Swap_b(int &a,int &b)//传入引用:可以改变实参
{
int c = a;
a = b;
b = c;
}
void Swap_c(int *p1,int *p2)
{
int c = *p1;
*p1 = *p2;
*p2 = c;
}
int main()
{
int x = 10, y = 20;
Swap_a(x, y);
cout << x << " " << y << endl; //NO
Swap_b(x, y);
cout << x << " " << y << endl; //YES
Swap_c(&x, &y);
cout << x << " " << y << endl; //YES
return 0;
}
###################################################################
Note3:数组名的第二个例外:取地址
int main()
{
int a = 10;
int ar[] = { 12, 23, 34, 45, 56, 67, 78, 89, 90, 100 };
cout << sizeof(ar) << endl;//数组名的第一个例外:40
//1 从右到左。2 遇见(),先内后外
int *p[10];//[10]数组,放的是整型指针 p是数组名,数组开辟10个大小空间
int *r = &a;
int(*s)[10] = &ar;//(*s)指针(开辟4个字节,存放数组地址),指向的数组:开辟10个大小,里面放的是整型类型 这个10 不可以少,和ar保持一致
return 0;
}
1 p和ar的区别:p数组放的是 整型指针(四个字节)。
2 cout << sizeof§ <<" "<<sizeof(s)<< endl; 40 4
3 int(*s)[10] = &p;
这是错误的,不可以 大小相同,类型不同
4 int * (*s)[10] = &p;
就可以了
5
6 能指向的三个条件:大小 类型 连续空间。
###################################################################
Note4:数组名的第三个例外:初始化引用,让这个引用代表整个数组
int main()
{
int ar[] = { 12, 23, 34, 45, 56, 67, 78, 89, 90, 100 };
cout << sizeof(ar) << endl;//数组名的第一个例外:40
int &br1 = ar[0];//12的别名
int(&br2)[10] = ar;//数组ar的引用
int *p[10];//[10]数组,放的是整型指针 p是数组名,数组开辟10个大小空间
int(*s)[10] = &ar;//(*s)指针(开辟4个字节,存放数组地址),指向的数组:开辟10个大小,里面放的是整型类型
int* (&br3)[10] = p;//数组p的引用
return 0;
}
这三种情况:编译器关心:数组大小 类型。
其他情况下:都是首元素的地址
int &cr[10]; 不能编译通过,产生二义性。
###################################################################
Note5:二级指针:
二级指针存储一级指针地址,一级指针存储变量地址。上低下高,地址连续。
int main()
{
int a3 = 0, a2 = 0, a1 = 0, a0 = 0;
int *p3 = &a3, *p2 = &a2, *p1 = &a1, *p0 = &a0;
int **s = &p0;
return 0;
}
一级指针:
type *p=0;
p+=1;//p+=sizeof(type)*1;
二级指针:
type *s;//二级指针
s+=1;//s+=sizeof(type)*1; 4
*s+=1;//*s+=sizeof(type)1; //此时s 是一级指针 类型可能会变
###################################################################
Note6:
int main()
{
int ar0[3][4] = { 0 };
int(*s)[4] =ar0;// s是二级指针 s+1是加一个数组 s指向数组的地址
cout << "ar0[2][2]:" << ar0[2][2] << endl;
*(*(s + 2) + 2) = 1;
cout << "ar0[2][2]:" << ar0[2][2] << endl;
return 0;
}
ar0 数组首元素地址 ar0+1加到下一个元素
&ar0 数组的地址 &ar0+1加到下一个数组
*&ar0 数组首元素地址
###################################################################
Note7:
void fun(int &a)
{
int *p = &a;
a += 10;
*p += 10;
}
int main()
{
int x = 10;
int &r = x;
fun(x);
fun(r);
cout << x << endl;//50
return 0;
}
运行结果:
###################################################################
Note8:
分析:第一个 第三个有错:能力扩大,通过解引用 进而改变*p的值。
###################################################################
Note9:
分析:都对。因为p的值是 a的地址,s1 s2 s3的值都可以改变,而且其指向的值也可以变,p的值不受影响。
###################################################################
Note10:对应于 Note7。引用被编译器处理为 自身不可改变的 指针
void fun(int * const a)//用指针模拟逻辑上的引用
{
int *p = a;
*a += 10;
*p += 10;
}
int main()
{
int x = 10;
int * const r = &x;
fun(&x);
fun(r);
cout << x << endl;//50
return 0;
}
这个不可改变的指针 在使用时(使用引用),常常解引用操作。
###################################################################
Note11:
int c = 10;
int &b = c;
int *p = &c;
b = 100;
*p = 100;
反汇编:
int c = 10;
00E646B2 mov dword ptr [c],0Ah
int &b = c;
00E646B9 lea eax,[c]
00E646BC mov dword ptr [b],eax
** int *p = &c; **
00E646BF lea eax,[c]
00E646C2 mov dword ptr [p],eax
b = 100;
00E646C5 mov eax,dword ptr [b]
00E646C8 mov dword ptr [eax],64h
*p = 100;
00E646CE mov eax,dword ptr [p]
00E646D1 mov dword ptr [eax],64h
引用也开辟4个字节的空间。用于存放它引用变量的地址。
###################################################################
Note11:数组名和指针的区别:
int main()
{
int ar[10] = { 1, 2, 3, 4 };
int *p = ar;
p[1] = 6;// *(p+1)
ar[1] = 6;// *(ar+1)
return 0;
}
分析:
p[1] = 6;
00F24BDE mov eax,4
00F24BE3 shl eax,0
00F24BE6 mov ecx,dword ptr [p] //先从内存中访问p
00F24BE9 mov dword ptr [ecx+eax],6
ar[1] = 6;
00F24BF0 mov eax,4
00F24BF5 shl eax,0
00F24BF8 mov dword ptr ar[eax],6
###################################################################
Note12:
int main()
{
int ar[5][2] = { 1,2,3,4,5,6,7,8,9,10 };
int(*p)[2] =&ar[1];// p是指向数组的指针
cout << p[1][3] << endl;
int *s = ar[1];// *(ar+1)
cout << s[3] << endl;
return 0;
}
###################################################################
Note13:
int main()
{
int ar[3][4];
sizeof(ar);//12*4
int(*p)[3][4] = &ar;//p是指向二维数组的地址 p+1是48
int(&br)[3][4] = ar;
int(*s)[4] = ar;//s指向一位数组的地址 ar的首元素是个一位数组
return 0;
}
###################################################################
Note14: