关于C语言指针ii值为0的疑问:为何不是内存单元地址?
嘿,这个问题问到点子上了!咱们先理清两个核心点:指针ii本身的值根本不是0,你看到的0是因为用错了printf的格式符;另外,咱们可以一步步走代码,把每个变量的变化都捋清楚,你就明白到底发生了什么。
首先,核心错误:用错了printf格式符
你最后写的是printf("%f", ii);,但ii是float*类型的指针,%f是用来打印浮点数(float/double)的格式符,用它打印指针属于未定义行为——简单说就是编译器不知道该怎么处理,结果完全依赖于系统环境。
在你的场景里,指针的二进制值被强行解析成了浮点数,刚好在你的系统上这个解析结果是0.0,但这完全是巧合,换个平台可能输出奇怪的数字,甚至程序崩溃。
如果要打印指针的内存地址,应该用%p格式符,并且要把指针转换成void*类型,正确的写法是:
printf("%p", (void*)ii);
这样就能看到ii实际指向的内存地址了。
咱们一步步走代码,看变量到底怎么变
为了更清楚,我把每一步的变量变化列出来:
初始化阶段
float hh[]={10,4,(float)('b'-'d')};:'b'-'d'等于-2,所以hh初始是[10.0, 4.0, -2.0]static float *ii=dd;:因为dd是NULL,所以ii一开始是空指针
hh[0]+=6/4;- 这里是整数除法,
6/4的结果是1(不是1.5),所以hh[0] = 10.0 + 1 = 11.0,现在hh变成[11.0, 4.0, -2.0]
- 这里是整数除法,
ii=&hh[2]-1;&hh[2]是数组第三个元素的地址,指针减1后指向数组的第二个元素hh[1],所以现在ii = &hh[1](是一个有效的内存地址,不是0)
*ii=ii[0]+3;ii[0]等价于*ii,也就是当前hh[1]的值4.0,加3后是7.0,所以hh[1]被改成7.0,hh变成[11.0, 7.0, -2.0]
ii[-1]=(*(hh+1))+2;ii[-1]等价于*(ii-1),也就是hh[0];*(hh+1)是hh[1]的值7.0,加2得9.0,所以hh[0]被改成9.0,hh变成[9.0, 7.0, -2.0]
hh[2]=*(++ii)*2;++ii让ii的指向往后移一位,变成指向hh[2];*(ii)是当前hh[2]的值-2.0,乘2得-4.0,所以hh[2]被改成-4.0,现在ii = &hh[2],hh变成[9.0, 7.0, -4.0]
*ii=(hh[0]==4);hh[0]是9.0,9.0 == 4的结果是假,C语言里布尔假用0表示,所以把0赋值给*ii(也就是hh[2]),现在hh[2] = 0.0,但**ii本身还是指向hh[2]的地址,没有变**!
最后再明确两个点
- 指针
ii的值从第三步开始就一直是有效的内存地址(最后指向hh[2]),从来不是0; - 你看到的0,是错误用
%f打印指针时,把地址的二进制当成浮点数解析的结果;如果要打印ii指向的内容(也就是hh[2]的值),应该写printf("%f", *ii);,这时候输出的0.0才是正确的结果。
内容的提问来源于stack exchange,提问作者141_MATRIX_141
相关产品推荐
相关产品推荐

