文章详情

  • 游戏榜单
  • 软件榜单
关闭导航
热搜榜
热门下载
热门标签
php爱好者> php文档>简单小代码:不用计算、不用位操作来实

简单小代码:不用计算、不用位操作来实

时间:2006-10-08  来源:qfox

 简单小代码:不用计算、不用位操作来实现 加 1

http://www.chinaunix.net 作者:mik  发表于:2006-10-07 22:27:32
【发表评论】【查看原文】【C/C++讨论区】【关闭】

用位操作虽然可以实现加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

看,抛出了砖头,把玉给引来了 :)

相关阅读 更多 +
排行榜 更多 +
皇帝养成之第一纨绔

皇帝养成之第一纨绔

角色扮演 下载
黎明苏醒

黎明苏醒

角色扮演 下载
快救救小姐姐吧

快救救小姐姐吧

冒险解谜 下载