QQ登录

只需一步,快速开始

 找回密码
 注册

QQ登录

只需一步,快速开始

查看: 5593|回复: 24

C获取字符数组偏移地址疑问

[复制链接]
发表于 2009-12-21 16:39:35 | 显示全部楼层 |阅读模式
在grubinst里面有这样一个define,为了获取一个数组的偏移地址,其中有一点疑惑,请大家指点。

他是这样写的,这样调用的。

#define valueat(buf, ofs, type)        *( (type*) (((char*)&buf)+ofs) )
//ofs是偏移地址,type是要赋值的类型(即数据长度)
unsigned char grub_mbr[512];
valueat(grub_mbr,4,unsigned short)=0x3920;

他这里(char*)&buf         有点疑问,buf是一个指针了,他这样再取地址(&buf)理论上说是指针的指针(char **),但是前面的强制转换却是一个(char*)。为什么要这么写呢?

要我的话,我就这样写了
#define valueat(buf, ofs, type) *((type*) (((char*)buf)+ofs))

我这个可以正常运行,但是奇怪的是他那个也可以正常运行。(结果相同)

[ 本帖最后由 zy_sunshine 于 2009-12-21 16:44 编辑 ]
 楼主| 发表于 2009-12-21 17:05:14 | 显示全部楼层
  1. #include <stdio.h>

  2. #define valueat(buf, ofs, type)        *( (type*) ( ((char*)buf)+ofs ) )
  3. main()
  4. {
  5.         unsigned char grub_mbr[512] = {  
  6. 235, 6, 128, 5, 32, 57, 255, 255, 232, 0,
  7.   0, 91, 193, 235, 4, 140, 200, 1, 195, 142, 219,
  8.   83, 106, 25, 203, 246, 6, 2, 0, 4, 116, 15,
  9.   49, 192, 142, 192, 191, 252, 5, 102, 184, 68, 85,
  10.   67, 69, 102, 171, 104, 0, 32, 23, 188, 0, 144,
  11.   49, 201, 81, 186, 128, 0, 82, 180, 8, 249, 205,
  12.   19, 90, 88, 22, 7, 114, 23, 128, 225, 63, 249,
  13.   116, 17, 145, 180, 2, 137, 197, 49, 219, 65, 82,
  14.   249, 205, 19, 90, 114, 2, 246, 220, 14, 31, 156,
  15.   49, 246, 49, 255, 185, 223, 0, 252, 243, 165, 187,
  16.   252, 25, 102, 184, 71, 82, 85, 170, 234, 122, 0,
  17.   0, 32, 22, 31, 102, 57, 7, 117, 84, 157, 114,
  18.   60, 14, 31, 173, 136, 230, 173, 137, 193, 36, 63,
  19.   116, 31, 41, 232, 72, 246, 216, 191, 3, 0, 180,
  20.   2, 104, 0, 13, 7, 49, 219, 96, 205, 19, 97,
  21.   115, 10, 96, 49, 192, 205, 19, 97, 79, 117, 233,
  22.   249, 232, 197, 9, 119, 40, 131, 198, 12, 129, 254,
  23.   254, 1, 114, 198, 119, 21, 190, 178, 49, 180, 8,
  24.   153, 82, 205, 19, 88, 114, 9, 153, 145, 36, 63,
  25.   116, 3, 65, 235, 192, 190, 81, 1, 232, 111, 0,
  26.   235, 254, 30, 6, 102, 96, 140, 195, 250, 15, 1,
  27.   22, 96, 10, 15, 32, 192, 12, 1, 15, 34, 192,
  28.   190, 8, 0, 142, 198, 102, 49, 246, 102, 49, 255,
  29.   102, 185, 0, 36, 0, 0, 252, 243, 102, 165, 190,
  30.   16, 0, 142, 198, 36, 254, 15, 34, 192, 142, 195,
  31.   185, 0, 2, 49, 246, 86, 191, 0, 124, 87, 6,
  32.   31, 86, 7, 252, 243, 165, 191, 16, 126, 190, 0,
  33.   10, 185, 30, 0, 252, 243, 102, 46, 165, 6, 31,
  34.   251, 203, 250, 184, 0, 32, 142, 208, 188, 220, 143,
  35.   251, 102, 97, 7, 31, 233, 111, 255, 180, 14, 205,
  36.   16, 46, 172, 60, 0, 117, 246, 195, 13, 10, 77,
  37.   105, 115, 115, 105, 110, 103, 32, 77, 66, 82, 45,
  38.   104, 101, 108, 112, 101, 114, 46, 0, 0, 0, 0,
  39.   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  40.   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  41.   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  42.   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  43.   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  44.   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  45.   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  46.   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  47.   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  48.   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  49.   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  50.   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  51.   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  52.   0, 0, 0, 0, 0, 85, 170};
  53.         printf("%d\n", valueat(grub_mbr, 0, unsigned char));
  54.         //printf("%d\n", *((unsigned char*)((unsigned char *)(&grub_mbr)+1)));
  55.         //printf("%d\t%d\t%d", sizeof(char),sizeof(unsigned char),sizeof(int));
  56. }
复制代码
回复

使用道具 举报

发表于 2009-12-21 17:11:10 | 显示全部楼层
C 很久没看了,不过我印象里。C 的某些时候变量的 *X 和 X 还有 &Y 和 Y 这种引用有的时候他们等价。
另外,你看看你编译时有没有 waring 输出。貌似 GCC 会帮你更正一些语法。
回复

使用道具 举报

 楼主| 发表于 2009-12-21 17:19:25 | 显示全部楼层
我用的vc编译器没有warning
刚才又换gnu编译器,也没有warning
两个都没有,,,,
回复

使用道具 举报

发表于 2009-12-21 17:58:48 | 显示全部楼层
貌似需要另外加参数 -Wall 才显示这种问题的 waring 。
回复

使用道具 举报

whistler_wmz 该用户已被删除
发表于 2009-12-21 18:12:13 | 显示全部楼层
提示: 作者被禁止或删除 内容自动屏蔽
回复

使用道具 举报

whistler_wmz 该用户已被删除
发表于 2009-12-21 18:13:03 | 显示全部楼层
提示: 作者被禁止或删除 内容自动屏蔽
回复

使用道具 举报

whistler_wmz 该用户已被删除
发表于 2009-12-21 18:14:54 | 显示全部楼层
提示: 作者被禁止或删除 内容自动屏蔽
回复

使用道具 举报

 楼主| 发表于 2009-12-21 18:22:26 | 显示全部楼层
楼上正解,明白了
在char buf[]时候是一样的
char *buf  就不一样了
回复

使用道具 举报

发表于 2009-12-21 18:43:06 | 显示全部楼层
C 的指针是满清10大酷刑之一。
回复

使用道具 举报

发表于 2009-12-21 19:47:09 | 显示全部楼层
好像字符数组是特殊的。
回复

使用道具 举报

 楼主| 发表于 2009-12-21 20:31:30 | 显示全部楼层
测试字符串数组

  1. #include <stdio.h>
  2. main()
  3. {
  4.   //int buf[] = {1,2,3,4,5,6,7,8,9,0};
  5.   char buf[] = {'a','b','c','d','e','f','g','h','i','j'};
  6.   printf("%d\n", buf);
  7.   printf("%d\n", &buf);
  8.   printf("----------------\n");
  9.   printf("%d\n", buf+1);
  10.   printf("%d\n", &buf+1);
  11.   printf("----------------\n");
  12.   printf("%d\n", ((char*)&buf)+1);
  13. }
  14. 结果
  15. 2293600
  16. 2293600
  17. ----------------
  18. 2293601
  19. 2293610
  20. ----------------
  21. 2293601
复制代码
测试int数组

  1. #include <stdio.h>
  2. main()
  3. {
  4.   int buf[] = {1,2,3,4,5,6,7,8,9,0};
  5.   //char buf[] = {'a','b','c','d','e','f','g','h','i','j'};
  6.   printf("%d\n", buf);
  7.   printf("%d\n", &buf);
  8.   printf("----------------\n");
  9.   printf("%d\n", buf+1);
  10.   printf("%d\n", &buf+1);
  11.   printf("----------------\n");
  12.   printf("%d\n", ((int*)&buf)+1);//sorry,一开始我用的char* 那当然是加1了,这样就是加4了
  13. }
  14. 结果
  15. 1245016
  16. 1245016
  17. ----------------
  18. 1245020
  19. 1245056
  20. ----------------
  21. 1245020
复制代码
最后说明:
buf[]
buf是指向第一个元素的指针
&buf是指向整个数组的指针

(char*)&buf他这个做法,纯属xx放屁找麻烦型,将&buf变成指向整个数组的指针后,又用强制转换转成了指向单个元素的指针。(应该跟踪指针看看指针在内存中的数据结构)

最后一组也正确了,,我开始用错了强制转换了(int*) 用成(char*)了

[ 本帖最后由 zy_sunshine 于 2009-12-25 12:46 编辑 ]
回复

使用道具 举报

发表于 2009-12-22 09:37:49 | 显示全部楼层
有的数组是连续存放的。
典型的就是 char 组。这个时候,第一个元素和整个数组的指针是相等的。
整个字串的指针 +1 ,就会指向第二个元素。很适合用来进行遍历操作。

指针操作有很多不合规但是非常便捷的操作可以用的。所以编译器编译某些不适当的指针操作会出问题,因为他要考虑某些例外的应用。

指针游戏是一门艺术……
印象里还专门有指针操作而实现程序性能提升的实例程序可以看的。

PS:int 好像不能 +1 ,应该去 +4(int 如果是 32 bit 的),而且你也不能这么获取数组里面的变量。反正 char 指针操作是个很有用处的东西。
回复

使用道具 举报

 楼主| 发表于 2009-12-22 12:08:34 | 显示全部楼层
看样做嵌入式也太难了些,和这些指针,位,内存,什么的斤斤计较。
满清十大酷刑倒还挺好看,这个指针就不好看了......
回复

使用道具 举报

发表于 2009-12-22 17:04:11 | 显示全部楼层
你只要好好看看 C 的指针操作教程就行了。
反正我曾经刚刚看一点,我就晕菜了。
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 注册

本版积分规则

GMT+8, 2024-3-29 02:59 , Processed in 0.114989 second(s), 15 queries .

© 2021 Powered by Discuz! X3.5.

快速回复 返回顶部 返回列表