由一个每日一练引发的问题:
Windows:
Linux:
Mac:
请回答产生上述现象的原因
Tips:
那我再给你点思路,既然是操作系统不一样,有哪些不一样的点呢?
(1)生成的可执行文件貌似不一样,Mac和Ubuntu都是a.out,Windows是exe
(2)那变量究竟是个什么玩意?它有几层含义?
(3)地址是什么?获得的地址究竟是哪里的地址?
解答
在上述代码中
*p=arr1;
该语句是将arr1数组的地址(即一个指针变量,占8个字节)赋给了long型指针指向的内存,也即arr数组元素存放的内存,该操作会改变该内存的值。
1、Windows
对于windows系统来说,在执行该赋值(即将大数据放入指针指向的小变量的内存)时会进行强制类型转换,将arr1的值(即指针变量值)转化为int型的数据,并存放在p指向的内存的开始4字节中(为什么会转换成int类型,因为该内存(即arr数组的内存)存放的是int变量),也即改变了arr[0]的值。p是int型指针的话,情况一样(已经测试验证过了)。
采用如下代码:
int arr[10]={1,2000,3};
int arr1[10]={4,5,6};
printf("&arr=%p\tarr=%p\tarr1=%p\n",&arr,arr,arr1);
long *p=&arr;
*p=arr1;
printf("arr=%p\tarr[0]=%p\tarr[1]=%p\tarr[2]=%p\n",arr,arr[0],arr[1],arr[2]);
printf("%p %p %p\n",arr,arr1,*p);
进行测试时,输出结果如下图所示:
图中,arr1的地址是22FD90;
arr[0]的值以%p格式输出也是22FD90;arr[0]的值以%d格式输出是2293136,对应十六进制的22FD90;
*p的值以%p格式输出也是22FD90;
- Linux系统和MAC系统
而在Linux和Mac系统中,将大数据放入指针指向的小变量的内存时,直接存放,在填满小变量内存后继续占用其后续内存。则上述代码将arr1的值(占8字节)存在arr数组内存的8字节内存中,这一操作将改变arr[0]和arr[1]的值。(安装好Linux系统后测试验证)还要验证p是int型指针时,是什么情况?
注意1:上述代码中p=arr1;//改变p指针指向内存的值
与p=arr1;//改变p指针的指向,并不会改变arr数组的值
进行区分,
P=arr1;时,输出结果为:*
如图所示,arr数组的值并未改变。
注意2:
arr本身是一个数组名,
数组名代表三个含义:
1) 数组第一个元素的地址
2) 整个数组的地址
3) 数组的名字
对于1)和2),虽然arr的值和&arr是一样的,但arr+1指向下一个元素,&arr+1指向下一个数组。
输出结果如下图:
由图可见,arr和&arr的值一样;
arr+1的值是在arr值的基础上增加了4个字节(arr存储int变量),即指向数组arr中首元素后的下一个元素;
而&arr+1的值在arr值的基础上增加了40个字节(arr是存储了10个int变量的数组),即指向整个数组后面的内存。
类似的机制,在函数指针中也存在。