zy_sunshine 发表于 2009-12-21 16:39:35

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

在grubinst里面有这样一个define,为了获取一个数组的偏移地址,其中有一点疑惑,请大家指点。

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

#define valueat(buf, ofs, type)        *( (type*) (((char*)&buf)+ofs) )
//ofs是偏移地址,type是要赋值的类型(即数据长度)
unsigned char grub_mbr;
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 编辑 ]

zy_sunshine 发表于 2009-12-21 17:05:14

#include <stdio.h>

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

jiangtao9999 发表于 2009-12-21 17:11:10

C 很久没看了,不过我印象里。C 的某些时候变量的 *X 和 X 还有 &Y 和 Y 这种引用有的时候他们等价。
另外,你看看你编译时有没有 waring 输出。貌似 GCC 会帮你更正一些语法。

zy_sunshine 发表于 2009-12-21 17:19:25

我用的vc编译器没有warning
刚才又换gnu编译器,也没有warning
两个都没有,,,,

jiangtao9999 发表于 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

zy_sunshine 发表于 2009-12-21 18:22:26

楼上正解,明白了
在char buf[]时候是一样的
char *buf就不一样了

jiangtao9999 发表于 2009-12-21 18:43:06

C 的指针是满清10大酷刑之一。

sejishikong 发表于 2009-12-21 19:47:09

好像字符数组是特殊的。

zy_sunshine 发表于 2009-12-21 20:31:30

测试字符串数组
#include <stdio.h>
main()
{
//int buf[] = {1,2,3,4,5,6,7,8,9,0};
char buf[] = {'a','b','c','d','e','f','g','h','i','j'};
printf("%d\n", buf);
printf("%d\n", &buf);
printf("----------------\n");
printf("%d\n", buf+1);
printf("%d\n", &buf+1);
printf("----------------\n");
printf("%d\n", ((char*)&buf)+1);
}
结果
2293600
2293600
----------------
2293601
2293610
----------------
2293601
测试int数组
#include <stdio.h>
main()
{
int buf[] = {1,2,3,4,5,6,7,8,9,0};
//char buf[] = {'a','b','c','d','e','f','g','h','i','j'};
printf("%d\n", buf);
printf("%d\n", &buf);
printf("----------------\n");
printf("%d\n", buf+1);
printf("%d\n", &buf+1);
printf("----------------\n");
printf("%d\n", ((int*)&buf)+1);//sorry,一开始我用的char* 那当然是加1了,这样就是加4了
}
结果
1245016
1245016
----------------
1245020
1245056
----------------
1245020
最后说明:
buf[]
buf是指向第一个元素的指针
&buf是指向整个数组的指针

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

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

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

jiangtao9999 发表于 2009-12-22 09:37:49

有的数组是连续存放的。
典型的就是 char 组。这个时候,第一个元素和整个数组的指针是相等的。
整个字串的指针 +1 ,就会指向第二个元素。很适合用来进行遍历操作。

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

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

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

zy_sunshine 发表于 2009-12-22 12:08:34

看样做嵌入式也太难了些,和这些指针,位,内存,什么的斤斤计较。
满清十大酷刑倒还挺好看,这个指针就不好看了......

jiangtao9999 发表于 2009-12-22 17:04:11

你只要好好看看 C 的指针操作教程就行了。
反正我曾经刚刚看一点,我就晕菜了。
页: [1] 2
查看完整版本: C获取字符数组偏移地址疑问