取地址和指针
double pi = 3.1416;
取地址
π
指针
char ch = #(char * ) π
cout << ch << end1
则应该打印出如下内容
short转double
short s = 45;
double d = * (double * )&s;
在把short类型赋给double的类型的值的时候会自动补充内存,因为short类型的变量只占两个字节,而double变量要占8个字节,所以,会自动向后补充六个字节大小的空内存来填补上
定义的数据结构
定义一个结构
student fraction{
int num;
int denum;
}
现在声明一个
fraction pi;
pi.num = 22;
pi.denum = 7;
于是内存变成了这样:
下面将进行一系列的内存变换:
① ((fraction *)&(pi.denum))->num=12;
"&(pi.denum) : 取pi.denum的地址
(fraction *)&(pi.denum) : 取pi.denum的地址,然后把它重新构造一个fraction的结构
((fraction *)&(pi.denum))->num=12 : 取pi.denum的地址,然后把它重新构造一个fraction的结构,然后再对这个新的结构进行赋值操作。
在重新构造一个新的fraction时,这时候把pi.denum进行覆盖,给了((fraction *)&(pi.denum))的num,所以此时会重新拿到一块新的内存来进行填补构成一个新的fraction,也就是下图上面空的一块。
② ((fraction *)&(pi.denum))->denum=33;
为((fraction *)&(pi.denum))的denum进行赋值
③ ((fraction *)&(pi.denum))[0].denum;
这里将((fraction *)&(pi.denum))改为了一个数组形式,取第0个,然后取他的denum的值,这样写是没有问题的,但是就是非常的怪异,这句话能取出33这个值。
数组
int array[10];
array[0] = 44; array[9] = 100; array[45] = 45;
array[10] = 1;
数组的长度只有10,当给数组array[10]进行赋值时,则会额外取一块内存进行赋值,而不是出错。
array[25] = 25;
同理,会向后延长内存来进行赋值。
array[-4] = 77;
我当时看到这里还是挺惊讶的,数组的所引值竟然可以有负数,因为在java中从来没有接触过有负数的索引值,所以看到这个还是有点惊奇。不过原理也和上面一样,按序向前找即可。
*(array - 4)
这个式子的意思就是,取到array[-4]这个值。
几个恒等于
array ≡ &array[0] // array就相当于array数组第一个成员的地址
array + k ≡ &array[k] // array+k,偏移k个单位的地址,也就是array[k]的地址
*array ≡ array[0] // 这和上面的有些区别,这个的意思是指针直接指向的就是array[0]的值,而不是地址
*(array + k) ≡ array[k] // 同理,这是指向偏移k个地址的之后的值
类型变换
C语言中一个int类型时占两个字节的,short类型只占一个字节,所以下面就有了类型的变换。
int arr[5];
arr[3]=128;
因为一个int时两个字节构成,128用2进制表示是 1000 0000,于是array[3]里面实际的存储就是0000 0000 1000 0000,也就是前一个字节是0,后一个字节是128
((short *)arr)[6]=2;
这个数组被改成了short类型的数组,那么此时int类型的数组名义上便被转换为了short类型的数组,所以这时候((short *)arr)就好比把现在的int类型的数组每个位置切了一刀,形成了一个新的二倍的short类型数组,然后把2装在这个数组里面。
这个时候arr[3]里面的值就发生了变化,后一个字节也就是后8位依旧是128,但是前八位是2,换成二进制,现在arr[3]里面变成了这样:0000 0010 1000 000,所以现在arr[3]里面的值是128*2+128。
( ( short * ) ( ( ( char * ) ( &arr[1] ) ) + 8 ) ) [3] = 100;
这个式子就比较麻烦了,这个式子需要拆分再看,按顺序。
- &arr[1] : 取到arr的索引为1的地址
- ( char * ) ( &arr[1] ) : 以此数组为char类型来进行操作。
- ( ( ( char * ) ( &arr[1] ) ) + 8 ):向右偏移8个单位
- ( ( short * ) ( ( ( char * ) ( &arr[1] ) ) + 8 ) ) :以此数组为short类型来操作。
- ( ( short * ) ( ( ( char * ) ( &arr[1] ) ) + 8 ) ) [3] = 100:取第三个,赋值为100.
总的来说就是进行了如此的操作,如下图。
操作自定义结构的数组
定义数据结构
struct Student{
char * name;
char suid[8];
int numUtnits;
};
Student pupils[4];
此时会在内存中开辟4个Student大小的内存提供来使用
pupils[0].numUnits = 21;
pupils[2].name = strdup(“Adam”);
pupils[3].name = pupils[0].suid + 6;
这句话的意思就是将 pupils[3]的name 的 地址 在 pupils[0]的suid 的第六位处。
strcpy(pupils[1].suid, “40415xx”);
这句话的意思不是赋值,其实是复制的意思
strcpy(pupils[3].name, “123456”);
此时我们设定的 pupils[3] ,那么,但是我们前面把它的地址取得是 pupils[0]的suid+6 ,所以此时设置的就是 pupils[0]的suid+6 处的值,然而这里只有7 8 两个位置显然不够,所以,后面的3456会毫不客气地覆盖 pupils[0]的numUints 的值,就发生了下面这样的情况
pupils[7].suid[11] = ‘A’ ;
我们定义第7个,显然已经超出了范围,所以就一上面说过的数组来说,它会自动向后延申。然而suid一共有8位,盛不下11个,所以还会向后延,他就占用了numUints的第四位。