和大家分享一段C代码

newfinder 2010-10-28 12:18:55

int a[5] = {1,2,3,4,5};
int *ptr1 = (int *)(&a+1);
int *ptr2 = (int *)((int)a + 1);
printf("%x,%x\n",ptr1[-1],*ptr2);

平时真的很难想到这些.
...全文
200 19 打赏 收藏 转发到动态 举报
写回复
用AI写文章
19 条回复
切换为时间正序
请发表友善的回复…
发表回复
AI应用技术 2010-10-28
  • 打赏
  • 举报
回复
[Quote=引用楼主 newfinder 的回复:]
C/C++ code

int a[5] = {1,2,3,4,5};
int *ptr1 = (int *)(&a+1);
int *ptr2 = (int *)((int)a + 1);
printf("%x,%x\n",ptr1[-1],*ptr2);


平时真的很难想到这些.
[/Quote]
除了帮助理解,一点意义都没有
bo_00 2010-10-28
  • 打赏
  • 举报
回复
最主要的就是 那个 +1 ,到底是怎么个+1,,明白这个,指针就好办了。
王大军9527 2010-10-28
  • 打赏
  • 举报
回复

int a[5] = {1,2,3,4,5};
int *ptr1 = (int *)(&a+1);
int *ptr2 = (int *)((int)a + 1);
printf("%x,%x\n",ptr1[-1],*ptr2);


在平时的确少写这样的代码为好!
但这段代码却是考察基本功比较不错的题目:

&a 是对数组 a 取地址, 即得到的应该是数组指针

int a[5] = {1, 2, 3, 4, 5};
int (*p)[5] = &a; /* 数组指针,指向数组a,指针p的步长是 sizeof(int [5]) */
++p; (&a + 1) /* p + 1 即指针p偏移了sizeof(int [5]) p指向数组a[4]后面的一个数组 */
int *ptr1 = (int *)p;/* 强制转换p 成 int* 型指针赋给ptr1, int *型指针步长是sizeof(int) */

printf("%x\n", ptr1[-1]);
/* ptr1[-1]编译器会解释为 *(ptr1 - 1),ptr1的步长是sizeof(int), 所以其值是5*/



int *ptr2 = (int *)((int)a + 1);
/*
* a本身的步长是sizeof(int), 但强制转换成int, 后 + 1, 即普通的加法,不涉及指针偏移
* 假设是在x86小端字节序主机上:
* a-------------> 01 //地址低端
* (int)a + 1----> 00 //即现在 ptr2指向的地址
* 00
* 00 ===> a[0](int型是4bytes)
* a+1-----------> 02
* 00
* 00
* 00 ===> a[1]
* a+2-----------> 03
* 00
* ……
* 从上面可以看到 ptr2 指向的地址, 所以 *ptr2 的值是 0x20000000
* 上面的是在上小端字节序主机的结果,在大端字节序主机上的值是不一样的,值是 0x0100.理论都是一样的
*/
bo_00 2010-10-28
  • 打赏
  • 举报
回复
这种代码还是别收藏了。

int32 *ptr1 = (int *)(&a+1);
&a取的是数组地址,&a+1相当与sizeof(a),就是把ptr指到了数组元素5的屁股上。
打印ptr[-1],向前挪了32bit,所以结果是5。

int32 *ptr2 = (int *)((int)a + 1);
将数组a的地址转换成10进制后+1的话,就是把ptr2从数组首向后挪了8bit。
打印*ptr2时,取int32数据进行打印。
另外考虑,内存中存放的形式
01 00 00 00 02 00 00 00 03 00 00 00 04 00 00 00 05 00 00 00 ?? ?? ?? ??
所以挪了8bit的话,打印结果是200000


这种代码,不仅考了别人,同时也折磨自己。
newfinder 2010-10-28
  • 打赏
  • 举报
回复
是啊 指针是C的精华,也是最难理解和运用的,确实离不了它
现在面试题确实出的很经典,虽然有些不是常用的,但可以给咋们一点指点,多了解程序设计中的奥妙.呵呵
king_fiske 2010-10-28
  • 打赏
  • 举报
回复
1 2000
monkey_1263 2010-10-28
  • 打赏
  • 举报
回复
看不太懂!!!
helloangel8002 2010-10-28
  • 打赏
  • 举报
回复
第一个好像有点懂
第二个就不懂了
shexinwei 2010-10-28
  • 打赏
  • 举报
回复
帮忙顶吧,确实不大好用的写法。
一根烂笔头 2010-10-28
  • 打赏
  • 举报
回复
能理解,但是不好用,我看贝尔实验室的砖头书给的建议是,尽量减少对指针的运算的使用!可读性差!容易出差错,有时候会导致无意义的运算!
job82824 2010-10-28
  • 打赏
  • 举报
回复
现在的笔试不都朝着不实用怪异用法发展 ...
無_1024 2010-10-28
  • 打赏
  • 举报
回复
呵呵 还好
lsupper 2010-10-28
  • 打赏
  • 举报
回复
汗,这些用法最好不用...看着就头疼,别说多用了...
黎翔 2010-10-28
  • 打赏
  • 举报
回复
[Quote=引用 18 楼 zhao4zhong1 的回复:]

VC调试时按Alt+8,TC或BC用TD调试,打开汇编窗口看每句C对应的汇编不就啥都明白了吗。
(Linux或Unix下应该也可以在用GDB调试时,看每句C对应的汇编。)
想要从本质上理解C指针,必须学习汇编以及C和汇编的对应关系。
从汇编的角度理解和学习C语言的指针,原本看似复杂的东西就会变得非常简单!
[/Quote]
第一个知道,第二个不知道!!现在学习拉!!以后会把C和汇编对应起来看的
赵4老师 2010-10-28
  • 打赏
  • 举报
回复
VC调试时按Alt+8,TC或BC用TD调试,打开汇编窗口看每句C对应的汇编不就啥都明白了吗。
(Linux或Unix下应该也可以在用GDB调试时,看每句C对应的汇编。)
想要从本质上理解C指针,必须学习汇编以及C和汇编的对应关系。
从汇编的角度理解和学习C语言的指针,原本看似复杂的东西就会变得非常简单!
ashamwolf 2010-10-28
  • 打赏
  • 举报
回复
没觉得有意义,这样的代码很难维护。
王大军9527 2010-10-28
  • 打赏
  • 举报
回复
上面笔误,*ptr2 在小端字节序的值是 0x02000000

69,371

社区成员

发帖
与我相关
我的任务
社区描述
C语言相关问题讨论
社区管理员
  • C语言
  • 花神庙码农
  • 架构师李肯
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧