catalog
指针强转, 指针里存储的信息 ->
&
符号的取地址, 变量的地址
int a = 0x12 34 56 78;
___由于有(大, 小)端的问题, 先不讨论0x12
这个字节的地址问题, 即先不涉及到 (值)的问题
___一个变量, 他一定占据(连续的地址) [a, a + 1, a + 2, ..., a + k]
; 每一个地址, 即指向一个字节 且从[a]开始递增, 即[a]是 低地址
____其中, (a
称为: 该变量的起始地址), (k + 1
为: 该变量的 大小)
&
取地址符号 的作用是: 返回该变量的 (起始地址) 即, &
号 返回的, 一定是该变量的 低地址;
请注意, 到目前为止, 都与 (大小端) 无关!!!
即, &
返回的地址, 一定是[a]
地址 (低地址);
但是, 有歧义的点是: [a]
地址这个字节, 所存储的(值), 可能是(0x12
), 可能是(0x78
小端)
判断系统是 大 ? 小端 的 一个经典算法是:
int a = 7;
if( *( (char *)&a) == '\x7'){
DE<< "little-Endian";
}
else{
DE<< "big-Endian";
}
这里面有一个 (char *)&a
, 这是最核心的; 从int *
转换到 char *
, 发生了什么呢??
任何一个指针里所存储的信息, 有两个: (指向地址) (偏移量)
指针强转, 只改变(偏移量), 不改变(指向地址)
比如, 变量a
的地址是: [a0, a1, a2, a3]
(a0是低地址), 值是0x 12 34 56 78
则, &a
是 (int的指针), 他的信息是: (指向地址: a0
) (偏移量: 4
)
当发生强转时, (char *)&a
, 这个指针 是(char的指针), 他的信息是: (指向地址: a0
) (偏移量: 1
)
可以发现, 这两个指针, (指向地址)是一样的, 只有偏移量不同;
偏移量, 影响的是 *
取值
* (&a)
, 得到[a0, a1, a2, a3]
这4个字节的值;
而*( (char *)&a)
, 得到[a0]
这1个字节的值; 因为[a0]
是低地址, 如果他的值 是0x78
, 说明是 小端
指针的强转
任何类型的指针 可以强转为: 整型
T a; // &a = 0x76fdb4
size_t val = reinterpret_cast< ::std::size_t>( &a);
, 此时, val
的值为: 7798196
(即为上面地址的10进制)
size_t val = &a;
这样强转是错误的
整数可以强转为: 任意类型的指针
int a;
(T *)a;
是可以的, 输出会得到a
的十六进制
指针也是变量
T* ptr = addr_1; '需求: 让ptr指向addr_2地址'
/ 这当然很简单,直接ptr = addr_2即可。
/ 但,我们要把这个操作,放到'函数'里面去做
你肯定会直接想到:
func(T* ptr){
ptr = addr_2;
}
func(ptr);
那么,我们就需要回顾,指针!
int* ptr = addr_1;
DE(ptr); / == addr_1
' 输出这个ptr变量的(值),就像(int a=123; DE(a)就是123,即a的值) '
' 这个ptr的值,便是一个地址(int变量的值是个数字123,T*指针的值是个地址) '
DE(&ptr); / == ptr_var_addr
' ptr是个变量(指针,不要以为他就直接是个地址值,不是的!!) '
' 他也是个变量,==只不过,这个变量里 存放的值,是个地址== '
' 所以, &ptr的值,是这个ptr变量 所在的地址,和addr_1没有关系 '
' 就像是: (int a = 123; &a和123,肯定没有关系) '
DE(*ptr); / 这很简单,(即addr_1地址里的数据)
func(T* ptr_param){
DE(ptr_param); / == addr_1
' 即,这个ptr_param变量,里面的值 是什么 '
' 这确实容易让人混乱,你可以这样想: '
' int a = 123; func(int t){
此时DE(t) == 123; } '
' a和t 不是同个变量,但里面的值是相同的。 即(值拷贝)!! '
' 很重要的概念: 我们往往说,值拷贝、地址/指针拷贝。 '
' 但其实,不存在所谓的地址拷贝。 地址拷贝(从指针变量的角度看,也是值拷贝!!) '
/ 即,此时 ptr_param 和 ptr,里面的值是相同的 都是addr_1
/ 但是,这两个 是完全不同的变量!!!
DE(&ptr_param); / != ptr_var_addr
/ 上面已经解释过了, ptr_param是个局部变量,是新创建的变量
/ 和ptr没有关系, 只不过 他俩 里面的值 是相同的
'需求: 如何让 ptr_param == ptr呢?? '
1, 引用(把指针这个变量,引用过来)
2, 指针(把ptr的地址ptr_var_addr,给传递过来)
template<typename Type>
void func1(Type & ptr){
ptr = addr_2;
}
template<typename Type>
void func2(Type * ptr){
*ptr = addr_2; ' *ptr == ptr[0],只是不同的写法 '
}
// 上面的Type是: 你的指针ptr的类型 '
// 如果你的ptr是指向int的,即Type = int* , 即( T * )类型
T* ptr = addr_1;
func1< T * >( ptr );
func2< T * >( & ptr );
// 此时, ptr == addr_2; 修改了指针指向 '
数组的传参
数组在传参时, 会变成指针!!! 而且, C/C++函数不允许按值传递
Foo arr [ 5];
sizeof( arr); // : sizeof( Foo) * 5
void func0( Foo _arr [ 5] ){
sizeof( _arr); // : sizeof( void *)
}
void func1( Foo _arr [ ] ){
sizeof( _arr); // : sizeof( void *)
}
void func2( Foo * _arr ){
sizeof( _arr); // : sizeof( void *)
}
func 0 1 2
这3个函数, 其实是一样的;
并不是说 (数组名, 就是数组头元素指针 毕竟, sizeof( 数组名) != sizeof( 指针)
),