免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
12下一页
最近访问板块 发新帖
查看: 4331 | 回复: 11

[C] 指针用法的困惑 [复制链接]

论坛徽章:
0
发表于 2013-06-04 22:22 |显示全部楼层
最近在看C语言接口与实现这本书,被里面的指针用法搞得快崩溃了。现在刚看到序列(seq)这章,其中的一个调用不太理解,望大侠解惑。

  1. struct Array_T {
  2.         int length;
  3.         int size;
  4.         char *array;
  5. };

  6. struct Seq_T {
  7.         struct Array_T array;
  8.         int length;
  9.         int head;
  10. };
  11. typedef struct Seq_T *Seq_T;

  12. void *Seq_get(Seq_T seq, int i) {
  13.         assert(seq);
  14.         assert(i >= 0 && i < seq->length);
  15.         return ((void **)seq->array.array)[(seq->head + i)%seq->array.length];
  16. }
复制代码
这其中的 ((void **)seq->array.array)[.....]如何理解?

如果按照我自己的做法,会采取这种方式返回: (void *)&(seq->array.array)[......];

论坛徽章:
0
发表于 2013-06-05 09:37 |显示全部楼层
a[i]即*(a+i)的语法糖,这句返回的是(void **)seq->array.array从开始位置向后移动(seq->head + i)%seq->array.length个sizeof(void *)长度之后所在位置的值。返回值类型是void *,那便是把从当前位置向后sizeof(void *)长度的内容转化为void指针格式(地址)。
以上纯属个人理解。。。

论坛徽章:
0
发表于 2013-06-05 09:56 |显示全部楼层
本帖最后由 rollin7 于 2013-06-05 10:15 编辑
circleratio 发表于 2013-06-05 09:37
a即*(a+i)的语法糖,这句返回的是(void **)seq->array.array从开始位置向后移动(seq->head + i)%seq->array ...


你说得没错,早上仔细研究了下,把各地址打印出来分析,基本算是搞清了。不过还是感谢你

(void **)seq->array.array把其转化为一个二级指针,采用[(seq->head + i)%seq->array ...]是把其作为指针数组取第(seq->head + i)%seq->array ...个元素(其也是指针)来使用,最后转化出的地址即为
seq->array->array +  sizeof(void *) * ((seq->head + i)%seq->array.length]);

另外,(void *)&(seq->array.array)[......]用法是错的

论坛徽章:
4
水瓶座
日期:2013-09-06 12:27:30摩羯座
日期:2013-09-28 14:07:46处女座
日期:2013-10-24 14:25:01酉鸡
日期:2014-04-07 11:54:15
发表于 2013-06-05 10:42 |显示全部楼层
一旦你有了二级指针这种国产教材概念, 你就很难理解指针到底是什么了.

论坛徽章:
0
发表于 2013-06-05 15:11 |显示全部楼层
我觉得size应该是用来指示每个元素的大小,所以答案应该是这样:(void *)&seq->array.array[((seq->head + i) % seq->array.length) * seq->array.size]

论坛徽章:
0
发表于 2013-06-05 15:49 |显示全部楼层
本帖最后由 rollin7 于 2013-06-05 16:09 编辑
zhouqi5063 发表于 2013-06-05 15:11
我觉得size应该是用来指示每个元素的大小,所以答案应该是这样:(void *)&seq->array.array[((seq->head +  ...


size确实是用来指示元素大小的,但在此处是用不到size的,因为(void **)已经强制转换了,实际上转换后的array可以理解成为 void *array[n], 即array是含有n个指针的数组,

由于指针在32位机器上需要4个字节,因此
((void **)seq->array.array)[(seq->head + i)%seq->array.length] 它表示返回一个指向
(char)array[(seq->head + i)%seq->array.length *sizeof (void *) ],
(char)array[(seq->head + i)%seq->array.length *sizeof (void *) +1],
(char)array[(seq->head + i)%seq->array.length *sizeof (void *) +2],
(char)array[(seq->head + i)%seq->array.length *sizeof (void *) +3]
这四个字节组合成的地址的指针

(void *)&seq->array.array[((seq->head +  ... 是不正确的,它表示返回一个指向seq->array.array[((seq->head +  ... ]地址的指针

论坛徽章:
0
发表于 2013-06-05 17:57 |显示全部楼层
回复 6# rollin7


    就是因为是元素大小才不能直接强转为void *的元素,强转是有问题的,要不然这段代码就不通用了

论坛徽章:
0
发表于 2013-06-05 18:09 |显示全部楼层
(void *)&seq->array.array[((seq->head + i) % seq->array.length) * seq->array.size]    是没有错的,他返回的就是指向所需要元素的地址

论坛徽章:
0
发表于 2013-06-05 18:11 |显示全部楼层
数据结构里的两个lenth是冗余的,让人用的时候不知所措,一个就够了

论坛徽章:
0
发表于 2013-06-06 14:45 |显示全部楼层
我理解就是把array[idx]里存的数据强制转化为指针
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP