用位操作虽然可以实现加1,但似乎还得要 循环 来帮助。
最简单的事情莫过于让 [color=Red]编译器[/color] 来帮你实现 加 1 功能。
int _inc(int i) { char (*p)[2] = (char (*)[2])i; return (int)&((*p)[1]); }
int main() { printf("%d\n", _inc(100)); return 0; }
----------------------------
当然可以更简单点,直接定义为宏:
#define _INC(x) (int)&((*((char(*)[2])x))[1])
[ 本帖最后由 mik 于 2006-10-6 16:34 编辑 ]
mik 回复于:2006-10-06 11:44:53
让它来得更通用一点:
#define _INC(x) ( \
{ typeof(x) _t = x; \
(int)&((*((char(*)[2])_t))[1]); })
emacsnw 回复于:2006-10-06 15:03:49
这个有点意思,a[1] 其实就是 *(a+1),不过这样也算不用加法吗?
mik 回复于:2006-10-06 15:07:57
呵呵,这些计算是在编译器层面上,编译代码时,编译器计算的,用户代码没有计算这一步
whyglinux 回复于:2006-10-06 15:48:23
1. 似乎不是实现的加 1 功能,而是加 2,因为 p 指向一个具有两个char元素的数组,所以 p 和 p+1 之间的距离是 2 字节。要实现加 1 应该使用长度为 1 的字符数组。
2. 按照你这个思路,_inc 函数的实现还可以更简单些,即使 p 指向单个字符,而不是一个字符数组:
char* p = (char*)i; return (int)&p[1]; /* 相当于 return (int)(p + 1); */
3. 无论是你程序中的 &(*p[1]),还是上面的 &p[1],都需要 [color=red]计算[/color] p + 1 的值。由于 p 是一个指针变量,不是常量,所以这个计算只能在 [color=red]运行时[/color] 计算,不可能是一个 [color=red]编译时[/color] 概念。
mik 回复于:2006-10-06 16:09:13
引用:原帖由 whyglinux 于 2006-10-6 15:48 发表
1. 似乎不是实现的加 1 功能,而是加 2,因为 p 指向一个具有两个char元素的数组,所以 p 和 p+1 之间的距离是 2 字节。要实现加 1 应该使用长度为 1 的字符数组。
2. 按照你这个思路,_inc 函数的实现还可以更 ...
不要这么快下结论,你试过了吗?
1、
[color=Blue]p 是一个 char (*)[2] 型指针, 那么 *p 类型是: char [2][/color]
char c[2];
p = & c;
*p 就是 c,是一个 char[2];
(*p)[1] 相当于 c[1]
那么,c[1] 相对于 c[0],你说是不是 偏移了 1 byte 呀?
2、数组之间的偏移,不是编译时确定,难道是运行时确定 ??
[ 本帖最后由 mik 于 2006-10-7 22:28 编辑 ]
whyglinux 回复于:2006-10-06 16:19:59
>> (*p)[1] 相当于 c[1]
那你应该这样使用:(int)&((*p)[1]),而不是上面程序中的 (int)&(*p[1])。
mik 回复于:2006-10-06 16:34:19
引用:原帖由 whyglinux 于 2006-10-6 16:19 发表
>> (*p)[1] 相当于 c[1]
那你应该这样使用:(int)&((*p)[1]),而不是上面程序中的 (int)&(*p[1])。
那确实是手误, 宏定义 _INC(x) 里就正确了
lixuda 回复于:2006-10-06 16:36:36
自己测试下,whyglinux 是对啊。
也简单
没有必要用到(*p)[]吧。。
不过楼主厉害
awake 回复于:2006-10-06 16:52:36
引用:原帖由 mik 于 2006-10-6 16:09 发表
2、数组之间的偏移,不是编译时确定,难道是运行时确定 ??
可惜这个数组本身不是静态时确定的。
converse 回复于:2006-10-06 17:11:17
加精鼓励一下.
mik耍了一把编译器,把需要递增的值作为数组地址传给p,然后求以这个地址开始的下一个元素也就实现了加一的目的了,whyglinux那样可能更好看懂一些的,原来的做法麻烦了一点.
mik 回复于:2006-10-06 17:18:09
引用:原帖由 awake 于 2006-10-6 16:52 发表
可惜这个数组本身不是静态时确定的。
在 _inc(100);
这种情形下,是编译器计算的:
movl $101, 4(%esp) movl $.LC0, (%esp) call printf
在另一种情形下,还是要运行时确定:
int i = 0;
printf("%d\n", _inc(i));
movl -4(%ebp), %eax incl %eax movl %eax, 4(%esp) movl $.LC0, (%esp) call printf
awk就是awp加ak 回复于:2006-10-06 17:38:51
呵呵,地址加1 !
win_hate 回复于:2006-10-06 20:36:55
a c99 way
#include <stdio.h>
f(int n) { struct { char a[n]; char b; } *a; printf ("%d\n", sizeof(*a)); }
main (int argc, char **argv) { f(atoi(argv[1])); }
./a.out 1234 1235
[ 本帖最后由 win_hate 于 2006-10-6 20:38 编辑 ]
lovesaka 回复于:2006-10-06 23:17:34
引用:原帖由 win_hate 于 2006-10-6 20:36 发表
a c99 way
#include <stdio.h>
f(int n) { struct { char a[n]; char b; } *a; printf ("%d\n", sizeof(*a)); }
main (int argc, char **argv) { f(atoi(argv[1 ...
这也给想出来了强!!!!
converse 回复于:2006-10-06 23:35:31
win_hate老大的代码如果考虑struct对齐的情况下呢?似乎还要加一个编译选项指明是严格的大小,而不是对齐之后的大小.
win_hate 回复于:2006-10-06 23:58:11
印象里会 gcc 按结构成员中最大的``成员对齐'' 要求来对齐的。这里全是 char,应该不会有问题。加个对齐指令会保险一些。
但我总是记不住对齐指令,要 google,所以就算了。
flw 回复于:2006-10-07 22:18:07
想不通为什么要 [2] int _inc(int i) { char *p = (char *)i; return (int)&(p[1]); // 我一般不写 &(p) 而直接写 p+i; 所以其实说白了还是 p+1 }
int main() { printf("%d\n", _inc(100)); return 0;
}
[ 本帖最后由 flw 于 2006-10-7 22:21 编辑 ]
mik 回复于:2006-10-07 22:27:32
脑子清醒了,是 OK
看,抛出了砖头,把玉给引来了 :)
|