C_and_CPP 板


LINE

※ 引述《anoymouse (没有昵称)》之铭言: : 关於"阵列名称的位址"跟"阵列第一个元素的位址"相同但值不同的问题 : &name=0x0000 &name[0]=0x0000 : name =0x0000 name[0]=1 : 在板上只看到LPH66大的回文,其实看不太懂 : 上网看大部分的解释大概是说: : 如果有一个阵列int name[3]={1,2,3}, : &name[0]=0x0000 : &name[1]=0x0004 : &name[2]=0x0008 : 其阵列名称name是一个指向阵列第一个元素的位址的指标,也就是指标常数 : name=0x0000 : name+1=0x0004 : name+2=0x0008 : 如果阵列名称name碰到两个operator:sizeof() or & : 变成&name就会是指到整个阵列的位址,所以&name+1就会变成0x000C : 意思是说阵列名称(指标常数)其实并没有自身的位址的概念? : 如果只是取阵列元素如name[0]那就会自动decay(网路上都用这个词)成指标 *(name+0) : 如果是使用&name那只是纯粹得到整个阵列的位址? &name并不是指标常数的位址? : 不知道这样问大家是否看的懂? 谢谢! 嗨嗨,先打个程式测测看就知道罗 #include <stdio.h> int main() { int array[3] = {6, 8, 9}; printf("sizeof(int): %d (0x%X)\n", sizeof(int), sizeof(int)); printf("sizeof(array): %d (0x%X)\n", sizeof(array), sizeof(array)); printf("array: %p\n", array); printf("&array: %p\n", array); printf("&array[0]: %p\n", &array[0]); printf("&array[1]: %p\n", &array[1]); printf("&array[2]: %p\n", &array[2]); printf("array + 0: %p\n", array + 0); printf("array + 1: %p\n", array + 1); printf("array + 2: %p\n", array + 2); printf("&array + 0: %p\n", &array + 0); printf("&array + 1: %p\n", &array + 1); printf("&array + 2: %p\n", &array + 2); printf("*(array + 1): %d\n", *(array + 1)); printf("*array + 1 : %d\n", *array + 1); return 0; } 以gcc-x86在Windows编译执行结果如下: sizeof(int): 4 (0x4) sizeof(array): 12 (0xC) array: 0061FF24 &array: 0061FF24 &array[0]: 0061FF24 &array[1]: 0061FF28 &array[2]: 0061FF2C array + 0: 0061FF24 array + 1: 0061FF28 array + 2: 0061FF2C &array + 0: 0061FF24 &array + 1: 0061FF30 &array + 2: 0061FF3C *(array + 1): 8 *array + 1 : 7 首先关於对阵列中每个元素取址这部分应该不会有太大困难, 取得的指标就是该元素的记忆体位址, 再来对阵列名称取址以及单纯阵列名称都表示阵列开头的位址, 而阵列的开头也就是第一个元素, 因此这三个位址是一样的没问题: array: 0061FF24 &array: 0061FF24 &array[0]: 0061FF24 接着阵列名称 + 常数,这个就比较不好理解了, 你可以直觉把他从 array + n 转换成 &array[n] 不过要注意的是当有上下文的时候要注意优先序, 因为你想要做的是对指标做dereference,而不是先提领再运算, 所以要小心 int result = *(array + 1); 和 int result = *array + 1; 的差别,你也许会疑惑为什麽可以直接dereference阵列名称, 还记得他们都是阵列第一个元素的位址吗? 因此 *array 提领的结果就是 array[0] 的值了。 最後我想你最大的困难是在 &array + 1 上面我们发现某个指标加上常数偏移就会等於以该指标作为阵列的第常数个元素的位址, 听起来很饶口,但是我要你观察的是 array + n 的偏移量, 或是更一般性的说我们要观察 ptr + n 的偏移量意义, 藉由观察 array + 1 以及 array + 2 执行的结果: array + 1: 0061FF28 array + 2: 0061FF2C 我们发现两个位址相减 0061FF2C - 0061FF28 = 4 由此可知每对这个阵列名称 + 1,就会得到往後4个bytes的位址, 这4个bytes是哪里来的? 上面程式一开始我就写了 sizeof(int), 而 int 正是这个阵列携带元素的型态,而每个元素的大小是4个bytes, 同理如果把 array + 1 和 array + 2 套回刚刚的公式 array + 1 = &array[1] array + 2 = &array[2] 以元素在阵列中的位址来思考的话, 不难发现第三个元素的位址 &array[2] 比第二个元素的位址 &array[1] 多了4个bytes,也就是元素的大小。 到这边整理一下, 阵列名称 + 常数偏移 array + n 的位址 // 以下都把指标当作整数运算 = 阵列开头的位址 + n * (阵列元素的大小) = &array[0] + n * sizeof(int) // 阵列的开头就是第一个元素 = &array + n * sizeof(array[0]) // 第一个元素型态是int = array + n * sizeof(*array) // *array就是第一个元素 = ptr + n * sizeof(*ptr) 这样归纳,可以直接导出我要讲的结论: &array + 1 的位址是多少呢?套用上面公式的话 其位址 = &array + 1 * sizeof(*&array) // 指标当作整数,此处非C语言 这边我们知道 &array 是指标对吧, 这个指标是一个指向「带有3个int的阵列」的指标, 我们把该指标命名为 ptr,其定义写成 int (*ptr)[3]; declare ptr as pointer to array 3 of int 因为这个指标指向的元素是一个「带有3个int的阵列」, 而又3个int的阵列的大小是3 * 4 = 12 (0xC), 故 ptr + 1 的位址就会是 ptr的位址 + 1 * 12, 再验证程式的结果: &array + 0: 0061FF24 &array + 1: 0061FF30 &array + 2: 0061FF3C 该指标每多 + 1,位址就会 + 12 (0xC),没错。 到这边如果都能懂的话, 想一想,&array + 1 位址是不是就是 &array[3] 呢? 希望以上的说明能让大家多一种思考方式,也希望能帮助到各位。 提供一点小公式 // 此处都是C语言没问题 &array[0] = array + 0 = array = &array elements of array: sizeof(array)/sizeof(*array) --



※ 发信站: 批踢踢实业坊(ptt.cc), 来自: 39.9.233.174
※ 文章网址: https://webptt.com/cn.aspx?n=bbs/C_and_CPP/M.1486132977.A.B3A.html
1F:推 prismwu: 写真清楚 02/04 00:13
2F:推 cuteSquirrel: 推荐这篇文章 02/04 13:28
3F:推 s89227: 推一个 02/04 20:18
4F:推 MasTerNBHD: 推,满少看到 &变数+常数的 XD 02/04 22:20
5F:推 joj4211: 666666 02/06 00:37
6F:推 jerryh001: 第二个printf少一个& 02/06 12:14
7F:推 HowLeeHi: &array+1知道怎麽计算,但没有很详细去了解原因... 02/07 03:07
8F:→ HowLeeHi: 好像平常也比较少出现的样子!?? 02/07 03:07
9F:推 anoymouse: 谢谢! 03/08 17:12







like.gif 您可能会有兴趣的文章
icon.png[问题/行为] 猫晚上进房间会不会有憋尿问题
icon.pngRe: [闲聊] 选了错误的女孩成为魔法少女 XDDDDDDDDDD
icon.png[正妹] 瑞典 一张
icon.png[心得] EMS高领长版毛衣.墨小楼MC1002
icon.png[分享] 丹龙隔热纸GE55+33+22
icon.png[问题] 清洗洗衣机
icon.png[寻物] 窗台下的空间
icon.png[闲聊] 双极の女神1 木魔爵
icon.png[售车] 新竹 1997 march 1297cc 白色 四门
icon.png[讨论] 能从照片感受到摄影者心情吗
icon.png[狂贺] 贺贺贺贺 贺!岛村卯月!总选举NO.1
icon.png[难过] 羡慕白皮肤的女生
icon.png阅读文章
icon.png[黑特]
icon.png[问题] SBK S1安装於安全帽位置
icon.png[分享] 旧woo100绝版开箱!!
icon.pngRe: [无言] 关於小包卫生纸
icon.png[开箱] E5-2683V3 RX480Strix 快睿C1 简单测试
icon.png[心得] 苍の海贼龙 地狱 执行者16PT
icon.png[售车] 1999年Virage iO 1.8EXi
icon.png[心得] 挑战33 LV10 狮子座pt solo
icon.png[闲聊] 手把手教你不被桶之新手主购教学
icon.png[分享] Civic Type R 量产版官方照无预警流出
icon.png[售车] Golf 4 2.0 银色 自排
icon.png[出售] Graco提篮汽座(有底座)2000元诚可议
icon.png[问题] 请问补牙材质掉了还能再补吗?(台中半年内
icon.png[问题] 44th 单曲 生写竟然都给重复的啊啊!
icon.png[心得] 华南红卡/icash 核卡
icon.png[问题] 拔牙矫正这样正常吗
icon.png[赠送] 老莫高业 初业 102年版
icon.png[情报] 三大行动支付 本季掀战火
icon.png[宝宝] 博客来Amos水蜡笔5/1特价五折
icon.pngRe: [心得] 新鲜人一些面试分享
icon.png[心得] 苍の海贼龙 地狱 麒麟25PT
icon.pngRe: [闲聊] (君の名は。雷慎入) 君名二创漫画翻译
icon.pngRe: [闲聊] OGN中场影片:失踪人口局 (英文字幕)
icon.png[问题] 台湾大哥大4G讯号差
icon.png[出售] [全国]全新千寻侘草LED灯, 水草

请输入看板名称,例如:BuyTogether站内搜寻

TOP