Programming 版 (精华区)
发信人: SwordLea (飞刀李), 信区: Programming
标 题: [合集] 由bsearch引起的讨论
发信站: 哈工大紫丁香 (2003年12月07日08:59:03 星期天), 站内信件
────────────────────────────────────────
xceman (辉->光阴匆匆似流水) 于 2003年12月03日16:18:31 星期三 说道:
一般比较函数的返回至应该设置成int类型,
我为了节省空间设置成了char类型(8位整形数),
在函数内部比较的时候一切正常,但是作为函数指针放到bsearch中的时候,
在bsearch中就出错,不能够将返回至正确的复制,出错的代码是这一段:
if (!(result = (*compare)(key,mid)))
return(mid);
这是c库函数bsearch源代码中的一段,出错的现象很奇怪:
compare函数的返回值是0,但是result运行后的赋值却是2304!
将这段代码单独拿到外面测试,result运行后的赋值却是0,正常。
如果将compare地返回值类型换成short(16位整形),一切正常;
换成int,也一切正常。
不知道是什么原因??
────────────────────────────────────────
iamxiaohan (潇寒) 于 2003年12月03日17:09:35 星期三 说道:
什么什么什么呀,说得太详细了~~~ 看不懂~~~ ^_^
你是想做什么?调用bsearch用返回值为char的做比较函数出错是吧?
【 在 xceman (辉->光阴匆匆似流水) 的大作中提到: 】
: 一般比较函数的返回至应该设置成int类型,
: 我为了节省空间设置成了char类型(8位整形数),
: 在函数内部比较的时候一切正常,但是作为函数指针放到bsearch中的时候,
: 在bsearch中就出错,不能够将返回至正确的复制,出错的代码是这一段:
: if (!(result = (*compare)(key,mid)))
────────────────────────────────────────
artist (手艺人) 于 2003年12月03日17:21:16 星期三 说道:
个人观点:
1 空间不是这么省地,作为函数返回值,即使你设成char型,由于内存分配的对齐需要,
也占用2个或4个字节。
2 你的result是int型吧,不同类型的变量赋值时,建议采用强制类型转换。
用result=(int)(*compare)(key,mid);再试试。
一家之言,仅供参考。
【 在 xceman (辉->光阴匆匆似流水) 的大作中提到: 】
: 一般比较函数的返回至应该设置成int类型,
: 我为了节省空间设置成了char类型(8位整形数),
: 在函数内部比较的时候一切正常,但是作为函数指针放到bsearch中的时候,
: 在bsearch中就出错,不能够将返回至正确的复制,出错的代码是这一段:
: if (!(result = (*compare)(key,mid)))
────────────────────────────────────────
xceman (辉->光阴匆匆似流水) 于 2003年12月03日19:59:16 星期三 说道:
嗯哪,完全同意你的两个观点,
不过是一不小心用错了,现在程序是可以正确运行,因为我将返回值改成int了,
不过还是不明白,如果返回值是char,为什么不行?
即使是对齐,也不应该出现问题,
况且将这段bsearch中的代码放到别的地方就没问题了
【 在 artist (手艺人) 的大作中提到: 】
: 个人观点:
: 1 空间不是这么省地,作为函数返回值,即使你设成char型,由于内存分配的对齐需要,
: 也占用2个或4个字节。
: 2 你的result是int型吧,不同类型的变量赋值时,建议采用强制类型转换。
: 用result=(int)(*compare)(key,mid);再试试。
────────────────────────────────────────
xceman (辉->光阴匆匆似流水) 于 2003年12月03日19:59:34 星期三 说道:
嘿嘿,你理解的就是我要问的
【 在 iamxiaohan (潇寒) 的大作中提到: 】
: 什么什么什么呀,说得太详细了~~~ 看不懂~~~ ^_^
: 你是想做什么?调用bsearch用返回值为char的做比较函数出错是吧?
: 【 在 xceman (辉->光阴匆匆似流水) 的大作中提到: 】
: : 一般比较函数的返回至应该设置成int类型,
: : 我为了节省空间设置成了char类型(8位整形数),
: : 在函数内部比较的时候一切正常,但是作为函数指针放到bsearch中的时候,
: : 在bsearch中就出错,不能够将返回至正确的复制,出错的代码是这一段:
: : if (!(result = (*compare)(key,mid)))
────────────────────────────────────────
Sun (大灯泡) 于 2003年12月03日20:12:49 星期三 说道:
bsearch要的函数指针类型无论如何不能更改
【 在 xceman (辉->光阴匆匆似流水) 的大作中提到: 】
: 一般比较函数的返回至应该设置成int类型,
: 我为了节省空间设置成了char类型(8位整形数),
: 在函数内部比较的时候一切正常,但是作为函数指针放到bsearch中的时候,
: 在bsearch中就出错,不能够将返回至正确的复制,出错的代码是这一段:
: if (!(result = (*compare)(key,mid)))
────────────────────────────────────────
xceman (辉->光阴匆匆似流水) 于 2003年12月03日20:45:04 星期三 说道:
the reason??
【 在 Sun (大灯泡) 的大作中提到: 】
: bsearch要的函数指针类型无论如何不能更改
: 【 在 xceman (辉->光阴匆匆似流水) 的大作中提到: 】
: : 一般比较函数的返回至应该设置成int类型,
: : 我为了节省空间设置成了char类型(8位整形数),
: : 在函数内部比较的时候一切正常,但是作为函数指针放到bsearch中的时候,
: : 在bsearch中就出错,不能够将返回至正确的复制,出错的代码是这一段:
: : if (!(result = (*compare)(key,mid)))
────────────────────────────────────────
iamxiaohan (潇寒) 于 2003年12月03日20:46:09 星期三 说道:
参数的退压栈问题
【 在 xceman (辉->光阴匆匆似流水) 的大作中提到: 】
: 嘿嘿,你理解的就是我要问的
: 【 在 iamxiaohan (潇寒) 的大作中提到: 】
: : 什么什么什么呀,说得太详细了~~~ 看不懂~~~ ^_^
: : 你是想做什么?调用bsearch用返回值为char的做比较函数出错是吧?
────────────────────────────────────────
Sun (大灯泡) 于 2003年12月03日20:54:13 星期三 说道:
因为它就是要
int (*fcmp)(const void*, const void*)
这种类型的函数指针,也是按照这种类型去调用
你改了类型,它不知道,自然配合可能出现问题
至于为什么代码拷贝出来没有问题,可能是库预先编译的执行代码和你自己编译的还是有
些区别吧
【 在 xceman (辉->光阴匆匆似流水) 的大作中提到: 】
: the reason??
: 【 在 Sun (大灯泡) 的大作中提到: 】
: : bsearch要的函数指针类型无论如何不能更改
────────────────────────────────────────
kylix (智贤fans) 于 2003年12月03日21:14:47 星期三 说道:
也许是老的库文件里面生成.o或.a的时候用的是int *,他改后的源文件
变成char *,但在编译连接时用的是老的库文件,所以可能出现问题
【 在 Sun (大灯泡) 的大作中提到: 】
: 因为它就是要
: int (*fcmp)(const void*, const void*)
: 这种类型的函数指针,也是按照这种类型去调用
: 你改了类型,它不知道,自然配合可能出现问题
: 至于为什么代码拷贝出来没有问题,可能是库预先编译的执行代码和你自己编译的还是有
: 些区别吧
: 【 在 xceman (辉->光阴匆匆似流水) 的大作中提到: 】
: : the reason??
────────────────────────────────────────
Sun (大灯泡) 于 2003年12月03日21:19:59 星期三 说道:
比较奇怪的是,他节省空间的手段是让函数返回值从int到char
这能节省空间吗?
函数返回值是用EAX传的
【 在 kylix (智贤fans) 的大作中提到: 】
: 也许是老的库文件里面生成.o或.a的时候用的是int *,他改后的源文件
: 变成char *,但在编译连接时用的是老的库文件,所以可能出现问题
: 【 在 Sun (大灯泡) 的大作中提到: 】
: : 因为它就是要
: : int (*fcmp)(const void*, const void*)
: : 这种类型的函数指针,也是按照这种类型去调用
: : 你改了类型,它不知道,自然配合可能出现问题
: : 至于为什么代码拷贝出来没有问题,可能是库预先编译的执行代码和你自己编译的还是有
: : 些区别吧
────────────────────────────────────────
iamxiaohan (潇寒) 于 2003年12月03日21:35:21 星期三 说道:
这到是其次,对于char编译器可以翻译指令为 mov eax , al ; ^_^
关键是int函数指针与char函数指针根本就是不同的类型,在连接程序的时候,对于函
数定位的计算是要出错的,这很可能激出WINDOWS跳出非法内存访问框框,
它没跳已经万幸了 ^_^
【 在 Sun (大灯泡) 的大作中提到: 】
: 比较奇怪的是,他节省空间的手段是让函数返回值从int到char
: 这能节省空间吗?
: 函数返回值是用EAX传的
: 【 在 kylix (智贤fans) 的大作中提到: 】
: : 也许是老的库文件里面生成.o或.a的时候用的是int *,他改后的源文件
: : 变成char *,但在编译连接时用的是老的库文件,所以可能出现问题
────────────────────────────────────────
hotman (风) 于 Wed Dec 3 22:35:04 2003 说道:
1,什么叫节省空间?例如是节省磁盘空间或者ROM空间,还是节省运行内存空间?如果是
前者的话——那就把程序写小点,少定义全局变量(这都是占数据段的),如果是后者,
那就少使用内存,例如少申请一块堆中的内存或者函数内部变量尽量少,尤其是大数组。
2,返回值基本上都是使用AX或者EAX返回的,这要看编译器是如何生成了,例如BC31肯定
是AX,VC的肯定是EAX。
3,对于bsearch的参数compare可以强类型转换一下,例如(int (*)(char *, char *))P,
这样就不会导致函数堆栈错误了。
4,谈到边界问题,对于bsearch本来就是要快一些,如果再搞个char,如体系结构中所说
,这可能反而会影响速度了,计算机运算机器字长总比非字长快。是否边界对齐,这可以
从编译器选项中选择,一般优化速度都边界对齐的。
【 在 iamxiaohan 的大作中提到: 】
: 这到是其次,对于char编译器可以翻译指令为 mov eax , al ; ^_^
: 关键是int函数指针与char函数指针根本就是不同的类型,在连接程序的时候,对于函
: 数定位的计算是要出错的,这很可能激出WINDOWS跳出非法内存访问框框,
: 它没跳已经万幸了 ^_^
: 【 在 Sun (大灯泡) 的大作中提到: 】
: : 比较奇怪的是,他节省空间的手段是让函数返回值从int到char
: : 这能节省空间吗?
: : 函数返回值是用EAX传的
────────────────────────────────────────
Sun (大灯泡) 于 2003年12月04日08:09:03 星期四 说道:
mov eax, al了也不能节省空间呀
【 在 iamxiaohan (潇寒) 的大作中提到: 】
: 这到是其次,对于char编译器可以翻译指令为 mov eax , al ; ^_^
: 关键是int函数指针与char函数指针根本就是不同的类型,在连接程序的时候,对于函
: 数定位的计算是要出错的,这很可能激出WINDOWS跳出非法内存访问框框,
: 它没跳已经万幸了 ^_^
: 【 在 Sun (大灯泡) 的大作中提到: 】
: : 比较奇怪的是,他节省空间的手段是让函数返回值从int到char
: : 这能节省空间吗?
: : 函数返回值是用EAX传的
────────────────────────────────────────
Sun (大灯泡) 于 2003年12月04日08:10:45 星期四 说道:
你的意思是调用bsearch的时候强转?
好像应该也不成,那样并没有改变compare函数的实质
【 在 hotman (风) 的大作中提到: 】
: 1,什么叫节省空间?例如是节省磁盘空间或者ROM空间,还是节省运行内存空间?如果是
: 前者的话——那就把程序写小点,少定义全局变量(这都是占数据段的),如果是后者,
: 那就少使用内存,例如少申请一块堆中的内存或者函数内部变量尽量少,尤其是大数组。
:
:
: 2,返回值基本上都是使用AX或者EAX返回的,这要看编译器是如何生成了,例如BC31肯定
: 是AX,VC的肯定是EAX。
:
: 3,对于bsearch的参数compare可以强类型转换一下,例如(int (*)(char *, char *))P,
: 这样就不会导致函数堆栈错误了。
:
────────────────────────────────────────
Sun (大灯泡) 于 2003年12月04日08:22:54 星期四 说道:
不再犯臆想的错误,刚才实验了一下
compare函数必须定义返回值为int,否则编译不能通过,估计xceman也是用了类型强转了
强转后,编译没问题
以char为返回值,最后只用al
16: char c = 0;
004010B8 mov byte ptr [ebp-4],0
17: return c;
004010BC mov al,byte ptr [ebp-4]
18: }
所以bsearch调用compare的结果是取决于此时EAX高24位是什么
【 在 hotman (风) 的大作中提到: 】
: 1,什么叫节省空间?例如是节省磁盘空间或者ROM空间,还是节省运行内存空间?如果是
: 前者的话——那就把程序写小点,少定义全局变量(这都是占数据段的),如果是后者,
: 那就少使用内存,例如少申请一块堆中的内存或者函数内部变量尽量少,尤其是大数组。
:
:
: 2,返回值基本上都是使用AX或者EAX返回的,这要看编译器是如何生成了,例如BC31肯定
: 是AX,VC的肯定是EAX。
:
: 3,对于bsearch的参数compare可以强类型转换一下,例如(int (*)(char *, char *))P,
: 这样就不会导致函数堆栈错误了。
:
────────────────────────────────────────
xceman (辉->光阴匆匆似流水) 于 2003年12月04日09:23:10 星期四 说道:
【 在 hotman (风) 的大作中提到: 】
1,什么叫节省空间?例如是节省磁盘空间或者ROM空间,还是节省运行内存空间?如果是
前者的话——那就把程序写小点,少定义全局变量(这都是占数据段的),如果是后者,
那就少使用内存,例如少申请一块堆中的内存或者函数内部变量尽量少,尤其是大数组。
2,返回值基本上都是使用AX或者EAX返回的,这要看编译器是如何生成了,例如BC31肯定
是AX,VC的肯定是EAX。
3,对于bsearch的参数compare可以强类型转换一下,例如(int (*)(char *, char *))P
这样就不会导致函数堆栈错误了。
_________俺就是这么做地,嘿嘿
4,谈到边界问题,对于bsearch本来就是要快一些,如果再搞个char,如体系结构中所说
,这可能反而会影响速度了,计算机运算机器字长总比非字长快。是否边界对齐,这可以
从编译器选项中选择,一般优化速度都边界对齐的。
【 在 iamxiaohan 的大作中提到: 】
: 这到是其次,对于char编译器可以翻译指令为 mov eax , al ; ^_^
: 关键是int函数指针与char函数指针根本就是不同的类型,在连接程序的时候,对于函
: 数定位的计算是要出错的,这很可能激出WINDOWS跳出非法内存访问框框,
: 它没跳已经万幸了 ^_^
: 【 在 Sun (大灯泡) 的大作中提到: 】
: : 比较奇怪的是,他节省空间的手段是让函数返回值从int到char
: : 这能节省空间吗?
: : 函数返回值是用EAX传的
────────────────────────────────────────
xceman (辉->光阴匆匆似流水) 于 2003年12月04日09:24:53 星期四 说道:
对于节省空间等问题,俺最多是从编译的角度来考虑,
想这样从汇编的角度考虑,俺还不太适应,还得多多学习//blush
【 在 Sun (大灯泡) 的大作中提到: 】
: mov eax, al了也不能节省空间呀
: 【 在 iamxiaohan (潇寒) 的大作中提到: 】
: : 这到是其次,对于char编译器可以翻译指令为 mov eax , al ; ^_^
: : 关键是int函数指针与char函数指针根本就是不同的类型,在连接程序的时候,对于函
: : 数定位的计算是要出错的,这很可能激出WINDOWS跳出非法内存访问框框,
: : 它没跳已经万幸了 ^_^
────────────────────────────────────────
iamxiaohan (潇寒) 于 2003年12月04日10:10:06 星期四 说道:
不光是compare的值的问题,如果是返回值那么最多是程序执行有误,而不会跳内存错误,
而这是会存在内存非法访问的问题
【 在 Sun (大灯泡) 的大作中提到: 】
: 不再犯臆想的错误,刚才实验了一下
: compare函数必须定义返回值为int,否则编译不能通过,估计xceman也是用了类型强转了
: 强转后,编译没问题
: 以char为返回值,最后只用al
: 16: char c = 0;
: 004010B8 mov byte ptr [ebp-4],0
: 17: return c;
: 004010BC mov al,byte ptr [ebp-4]
: 18: }
: 所以bsearch调用compare的结果是取决于此时EAX高24位是什么
────────────────────────────────────────
kylix (智贤fans) 于 2003年12月04日10:14:14 星期四 说道:
不会节省什么空间,全都是在寄存器里面处理的,我估计
他是想少用个局部变量什么的,呵呵,不过好像没必要啊,这个
东西的内存是堆栈段的。
【 在 Sun (大灯泡) 的大作中提到: 】
: 比较奇怪的是,他节省空间的手段是让函数返回值从int到char
: 这能节省空间吗?
: 函数返回值是用EAX传的
: 【 在 kylix (智贤fans) 的大作中提到: 】
: : 也许是老的库文件里面生成.o或.a的时候用的是int *,他改后的源文件
: : 变成char *,但在编译连接时用的是老的库文件,所以可能出现问题
────────────────────────────────────────
Sun (大灯泡) 于 2003年12月04日10:20:28 星期四 说道:
内存非法访问地没有呀,where?
【 在 iamxiaohan (潇寒) 的大作中提到: 】
: 不光是compare的值的问题,如果是返回值那么最多是程序执行有误,而不会跳内存错误,
: 而这是会存在内存非法访问的问题
: 【 在 Sun (大灯泡) 的大作中提到: 】
: : 不再犯臆想的错误,刚才实验了一下
: : compare函数必须定义返回值为int,否则编译不能通过,估计xceman也是用了类型强转了
: : 强转后,编译没问题
: : 以char为返回值,最后只用al
: : 16: char c = 0;
: : 004010B8 mov byte ptr [ebp-4],0
: : 17: return c;
────────────────────────────────────────
iamxiaohan (潇寒) 于 2003年12月04日10:22:57 星期四 说道:
int与char型函数的内存布局是不同的,他们被link函数重定位,函数指针作为参数是通
过,压栈实现的。本来要用int的栈,现在用了char栈~~~
不信,可以自己写bsearch的实现函数,在windows下,马上就有内存错误框弹出 ^_^
【 在 Sun (大灯泡) 的大作中提到: 】
: 内存非法访问地没有呀,where?
: 【 在 iamxiaohan (潇寒) 的大作中提到: 】
: : 不光是compare的值的问题,如果是返回值那么最多是程序执行有误,而不会跳内存错误,
: : 而这是会存在内存非法访问的问题
────────────────────────────────────────
Sun (大灯泡) 于 2003年12月04日10:25:49 星期四 说道:
【 在 iamxiaohan (潇寒) 的大作中提到: 】
: int与char型函数的内存布局是不同的,他们被link函数重定位,函数指针作为参数是通
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^有根据吗?
对于函数指针来说,就是一个32b的地址而已,不管它是什么类型、什么参数
只不过编译器检查一下类型是否匹配
: 过,压栈实现的。本来要用int的栈,现在用了char栈~~~
: 不信,可以自己写bsearch的实现函数,在windows下,马上就有内存错误框弹出 ^_^
: 【 在 Sun (大灯泡) 的大作中提到: 】
: : 内存非法访问地没有呀,where?
────────────────────────────────────────
iamxiaohan (潇寒) 于 2003年12月04日10:26:50 星期四 说道:
用objdump可以看
【 在 Sun (大灯泡) 的大作中提到: 】
【 在 iamxiaohan (潇寒) 的大作中提到: 】
: int与char型函数的内存布局是不同的,他们被link函数重定位,函数指针作为参数是通
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^有根据吗?
对于函数指针来说,就是一个32b的地址而已,不管它是什么类型、什么参数
只不过编译器检查一下类型是否匹配
: 过,压栈实现的。本来要用int的栈,现在用了char栈~~~
: 不信,可以自己写bsearch的实现函数,在windows下,马上就有内存错误框弹出 ^_^
: 【 在 Sun (大灯泡) 的大作中提到: 】
: : 内存非法访问地没有呀,where?
────────────────────────────────────────
Sun (大灯泡) 于 2003年12月04日10:41:22 星期四 说道:
这样一个程序
main()
{
char ch[100] = {0};
char a=1;
bsearch(&a, ch, 100, 1, (int(*)(const void*, const void*))comp);
bsearch(&a, ch, 100, 1, comp1);
return 0;
}
char comp(const void* a, const void* b)
{
char c = 0;
return c;
}
int comp1(const void* a, const void* b)
{
int i = 0;
return i;
}
main()的汇编代码:
11: bsearch(&a, ch, 100, 1, (int(*)(const void*, const void*))comp);
00401055 push offset @ILT+5(_comp) (0040100a)
0040105A push 1
0040105C push 64h
0040105E lea eax,[ebp-64h]
00401061 push eax
00401062 lea ecx,[ebp-68h]
00401065 push ecx
00401066 call bsearch (004010d0)
0040106B add esp,14h
12: bsearch(&a, ch, 100, 1, comp1);
0040106E push offset @ILT+10(_comp1) (0040100f)
00401073 push 1
00401075 push 64h
00401077 lea edx,[ebp-64h]
0040107A push edx
0040107B lea eax,[ebp-68h]
0040107E push eax
0040107F call bsearch (004010d0)
00401084 add esp,14h
comp的
18: char c = 0;
004010B8 mov byte ptr [ebp-4],0
19: return c;
004010BC mov al,byte ptr [ebp-4]
comp1的
24: int i = 0;
0040D548 mov dword ptr [ebp-4],0
25: return i;
0040D54F mov eax,dword ptr [ebp-4]
26: }
bsearch的
59: if (!(result = (*compare)(key,mid)))
00401136 mov ecx,dword ptr [mid]
00401139 push ecx
0040113A mov edx,dword ptr [key]
0040113D push edx
0040113E call dword ptr [compare]
00401141 add esp,8
00401144 mov dword ptr [result],eax
00401147 cmp dword ptr [result],0
0040114B jne bsearch+82h (00401152)
60: return(mid);
0040114D mov eax,dword ptr [mid]
【 在 iamxiaohan (潇寒) 的大作中提到: 】
: 用objdump可以看
: 【 在 Sun (大灯泡) 的大作中提到: 】
: 【 在 iamxiaohan (潇寒) 的大作中提到: 】
: : int与char型函数的内存布局是不同的,他们被link函数重定位,函数指针作为参数是通
: ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^有根据吗?
: 对于函数指针来说,就是一个32b的地址而已,不管它是什么类型、什么参数
: 只不过编译器检查一下类型是否匹配
: : 过,压栈实现的。本来要用int的栈,现在用了char栈~~~
────────────────────────────────────────
deem (沙丘男爵) 于 2003年12月04日13:57:50 星期四 说道:
这个 asm dump 不错,叫什么名字?每次我都用objdump,还要自己和
sourcecode对上,这个看上去不用。
【 在 Sun (大灯泡) 的大作中提到: 】
: 这样一个程序
: main()
: {
: char ch[100] = {0};
: char a=1;
: bsearch(&a, ch, 100, 1, (int(*)(const void*, const void*))comp);
: bsearch(&a, ch, 100, 1, comp1);
: return 0;
: }
: char comp(const void* a, const void* b)
────────────────────────────────────────
lofe (〖感激生活〗) 于 2003年12月04日14:03:08 星期四 说道:
【 在 Sun (大灯泡) 的大作中提到: 】
: 不再犯臆想的错误,刚才实验了一下
: compare函数必须定义返回值为int,否则编译不能通过,估计xceman也是用了类型强转了
: 强转后,编译没问题
: 以char为返回值,最后只用al
: 16: char c = 0;
: 004010B8 mov byte ptr [ebp-4],0
: 17: return c;
: 004010BC mov al,byte ptr [ebp-4]
: 18: }
: 所以bsearch调用compare的结果是取决于此时EAX高24位是什么
这句话让我想起了如果把 char 返回值赋予 int i 怎么样呢?经验告诉我们明显能得
到正确结果的,那么编译器又是怎么做到的?下面这几行代码表明了大案:
如果将char或short型函数返回值赋予int型变量,编译器先将返回结果 al或ax 进行
符号扩展(movsx eax, al/ax),然后再进行赋值。
bsearch中,由于comp的返回值被声明为int型,因此 al 没有被符号扩展,而整个eax
直接被当作结果,于是高24位是没意义的。
注意 main 中 对 i 和 j 赋值对应的汇编代码:
对i赋值时作了扩展,而对j时没有,因而j的结果是错误的。
///////////////////////////////////////////////////////////////////////////
#include "stdafx.h"
char foo(void) { return 0; }
int (*bar)(void) = (int(*)(void)) (foo);
int main(int argc, char* argv[])
{
int i, j;
i = foo();
j = bar();
return 0;
}
//////////////////////////////////////////////////////////////////////////
PUBLIC ?foo@@YADXZ ; foo
PUBLIC ?bar@@3P6AHXZA ; bar
_DATA SEGMENT
?bar@@3P6AHXZA DD FLAT:?foo@@YADXZ ; bar
_DATA ENDS
_TEXT SEGMENT
?foo@@YADXZ PROC NEAR ; foo
; 6 : char foo(void) { return 0; }
push ebp
mov ebp, esp
xor al, al
pop ebp
ret 0
?foo@@YADXZ ENDP ; foo
_TEXT ENDS
PUBLIC _main
_TEXT SEGMENT
_i$ = -4
_j$ = -8
_main PROC NEAR
; 11 : {
push ebp
mov ebp, esp
sub esp, 8
; 12 : int i, j;
; 13 :
; 14 : i = foo();
call ?foo@@YADXZ ; foo
movsx eax, al
mov DWORD PTR _i$[ebp], eax
; 15 : j = bar();
call DWORD PTR ?bar@@3P6AHXZA ; bar
mov DWORD PTR _j$[ebp], eax
; 16 :
; 17 : return 0;
xor eax, eax
; 18 : }
mov esp, ebp
pop ebp
ret 0
_main ENDP
_TEXT ENDS
────────────────────────────────────────
Sun (大灯泡) 于 2003年12月04日17:08:14 星期四 说道:
Visual Studio 6.0, haha
【 在 deem (沙丘男爵) 的大作中提到: 】
: 这个 asm dump 不错,叫什么名字?每次我都用objdump,还要自己和
: sourcecode对上,这个看上去不用。
: 【 在 Sun (大灯泡) 的大作中提到: 】
: : 这样一个程序
: : main()
: : {
: : char ch[100] = {0};
: : char a=1;
────────────────────────────────────────
hotman (风) 于 Thu Dec 4 18:06:12 2003 说道:
呵呵,我当然要用过才能敢下结论了:-)
1,VC中
#include <search.h>
#include <string.h>
#include <stdio.h>
char compare( char **arg1, char **arg2 ); /* Declare a function for compare */
void main( int argc, char **argv )
{
char **result;
char *key = "cat";
int i;
/* Sort using Quicksort algorithm: */
qsort( (void *)argv, (size_t)argc, sizeof( char * ), (int (*)(const
void*, const void*))compare );
for( i = 0; i < argc; ++i ) /* Output sorted list */
printf( "%s ", argv[i] );
/* Find the word "cat" using a binary search algorithm: */
result = (char **)bsearch( (char *) &key, (char *)argv, argc,
sizeof( char * ), (int (*)(const void*, const vo
id*))compare );
if( result )
printf( "\n%s found at %Fp\n", *result, result );
else
printf( "\nCat not found!\n" );
}
//int compare( char **arg1, char **arg2 )
char compare( char **arg1, char **arg2 )
{
/* Compare all of both strings: */
return _strcmpi( *arg1, *arg2 );
}
2,BC31中:
#include <search.h>
#include <string.h>
#include <stdio.h>
char compare( char **arg1, char **arg2 ); /* Declare a function for compare */
void main( int argc, char **argv )
{
char **result;
char *key = "cat";
int i;
/* Sort using Quicksort algorithm: */
qsort( (void *)argv, (size_t)argc, sizeof( char * ), (int (*)(const
void*, const void*))compare );
for( i = 0; i < argc; ++i ) /* Output sorted list */
printf( "%s ", argv[i] );
/* Find the word "cat" using a binary search algorithm: */
result = (char **)bsearch( (char *) &key, (char *)argv, argc,
sizeof( char * ), (int (*)(const void*, const vo
id*))compare );
if( result )
printf( "\n%s found at %Fp\n", *result, result );
else
printf( "\nCat not found!\n" );
}
//int compare( char **arg1, char **arg2 )
char compare( char **arg1, char **arg2 )
{
/* Compare all of both strings: */
return strcmp( *arg1, *arg2 );
}
3,GCC中
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
char compare( char **arg1, char **arg2 ); /* Declare a function for compare */
int main( int argc, char **argv )
{
char **result;
char *key = "cat";
int i;
/* Sort using Quicksort algorithm: */
qsort( (void *)argv, (size_t)argc, sizeof( char * ), (int (*)(const
void*, const void*))compare );
for( i = 0; i < argc; ++i ) /* Output sorted list */
printf( "%s ", argv[i] );
/* Find the word "cat" using a binary search algorithm: */
result = (char **)bsearch( (char *) &key, (char *)argv, argc,
sizeof( char * ), (int (*)(const void*, const vo
id*))compare );
if( result )
printf( "\n%s found at %Fp\n", *result, result );
else
printf( "\nCat not found!\n" );
return 0;
}
//int compare( char **arg1, char **arg2 )
char compare( char **arg1, char **arg2 )
{
/* Compare all of both strings: */
return _strcmpi( *arg1, *arg2 );
}
我想应该基本上覆盖了当前一般流行的编译器了吧。
【 在 Sun 的大作中提到: 】
: 不再犯臆想的错误,刚才实验了一下
: compare函数必须定义返回值为int,否则编译不能通过,估计xceman也是用了类型强..
: 强转后,编译没问题
: 以char为返回值,最后只用al
: 16: char c = 0;
: 004010B8 mov byte ptr [ebp-4],0
: 17: return c;
: 004010BC mov al,byte ptr [ebp-4]
: 18: }
: 所以bsearch调用compare的结果是取决于此时EAX高24位是什么
: 【 在 hotman (风) 的大作中提到: 】
: : 1,什么叫节省空间?例如是节省磁盘空间或者ROM空间,还是节省运行内存空间?..
: : 前者的话——那就把程序写小点,少定义全局变量(这都是占数据段的),如果是..
: : 那就少使用内存,例如少申请一块堆中的内存或者函数内部变量尽量少,尤其是大..
: :
: :
: : 2,返回值基本上都是使用AX或者EAX返回的,这要看编译器是如何生成了,例如BC..
: : 是AX,VC的肯定是EAX。
: :
: : 3,对于bsearch的参数compare可以强类型转换一下,例如(int (*)(char *, char..
: (以下引言省略...)
────────────────────────────────────────
deem (沙丘男爵) 于 2003年12月04日18:11:49 星期四 说道:
^_^,看错了,我以为是tsearch,原来是bsearch,搞错平台了
【 在 Sun (大灯泡) 的大作中提到: 】
: Visual Studio 6.0, haha
: 【 在 deem (沙丘男爵) 的大作中提到: 】
: : 这个 asm dump 不错,叫什么名字?每次我都用objdump,还要自己和
: : sourcecode对上,这个看上去不用。
────────────────────────────────────────
Sun (大灯泡) 于 2003年12月04日18:13:22 星期四 说道:
从前面分析看,你这个程序好使只能是因为运气好
【 在 hotman (风) 的大作中提到: 】
: 呵呵,我当然要用过才能敢下结论了:-)
: 1,VC中
: #include <search.h>
: #include <string.h>
: #include <stdio.h>
:
: char compare( char **arg1, char **arg2 ); /* Declare a function for compare */
:
:
: void main( int argc, char **argv )
: {
────────────────────────────────────────
hotman (风) 于 Thu Dec 4 18:42:33 2003 说道:
VC中,调试你的程序如下所示:同样可以工作
#include <search.h>
char comp(const void* a, const void* b);
int comp1(const void* a, const void* b);
main()
{
char ch[] = {1, 2, 3, 4, 5, 6, 7, 8, 9};
char a=9;
char *r = (char*)bsearch(&a, ch, sizeof(ch), sizeof(char), (int(*)(const v
oid*, const void*))comp);
//bsearch(&a, ch, 100, 1, comp1);
return 0;
}
char comp(const void* a, const void* b)
{
//char c = 0;
//return c;
return (*(char*)a - *(char*)b);
}
int comp1(const void* a, const void* b)
{
int i = 0;
return i;
}
【 在 Sun 的大作中提到: 】
: 这样一个程序
: main()
: {
: char ch[100] = {0};
: char a=1;
: bsearch(&a, ch, 100, 1, (int(*)(const void*, const void*))comp);
: bsearch(&a, ch, 100, 1, comp1);
: return 0;
: }
: char comp(const void* a, const void* b)
: {
: char c = 0;
: return c;
: }
: int comp1(const void* a, const void* b)
: {
: int i = 0;
: return i;
: }
: main()的汇编代码:
: (以下引言省略...)
────────────────────────────────────────
Sun (大灯泡) 于 2003年12月04日18:57:07 星期四 说道:
19: return (*(char*)a - *(char*)b);
0040D57C mov eax,dword ptr [ebp+8]
0040D57F movsx eax,byte ptr [eax]
0040D582 mov ecx,dword ptr [ebp+0Ch]
0040D585 movsx edx,byte ptr [ecx]
0040D588 sub eax,edx
20: }
为了计算减法,EAX全用上了,所以100%没问题
但是,这么做绝对是危险的。毛主席教导我们说,一切事情不能只看表面现象
从本质看,这样做是非常危险的,只要编译器换一种实现方法,就会出问题
这种用法并不符合ANSI C
【 在 hotman (风) 的大作中提到: 】
: VC中,调试你的程序如下所示:同样可以工作
: #include <search.h>
:
: char comp(const void* a, const void* b);
: int comp1(const void* a, const void* b);
: main()
: {
: char ch[] = {1, 2, 3, 4, 5, 6, 7, 8, 9};
: char a=9;
:
: char *r = (char*)bsearch(&a, ch, sizeof(ch), sizeof(char), (int(*)(const v
────────────────────────────────────────
iamxiaohan (潇寒·System Programmer ^_^) 于 2003年12月04日21:55:01 星期四 说道:
出什么问题?
【 在 Sun (大灯泡) 的大作中提到: 】
: 19: return (*(char*)a - *(char*)b);
: 0040D57C mov eax,dword ptr [ebp+8]
: 0040D57F movsx eax,byte ptr [eax]
: 0040D582 mov ecx,dword ptr [ebp+0Ch]
: 0040D585 movsx edx,byte ptr [ecx]
: 0040D588 sub eax,edx
: 20: }
: 为了计算减法,EAX全用上了,所以100%没问题
: 但是,这么做绝对是危险的。毛主席教导我们说,一切事情不能只看表面现象
────────────────────────────────────────
Sun (大灯泡) 于 2003年12月05日00:03:48 星期五 说道:
xceman那样的问题
【 在 iamxiaohan (潇寒·System Programmer ^_^) 的大作中提到: 】
: 出什么问题?
: 【 在 Sun (大灯泡) 的大作中提到: 】
: : 19: return (*(char*)a - *(char*)b);
: : 0040D57C mov eax,dword ptr [ebp+8]
: : 0040D57F movsx eax,byte ptr [eax]
: : 0040D582 mov ecx,dword ptr [ebp+0Ch]
: : 0040D585 movsx edx,byte ptr [ecx]
: : 0040D588 sub eax,edx
: : 20: }
: : 为了计算减法,EAX全用上了,所以100%没问题
: : 但是,这么做绝对是危险的。毛主席教导我们说,一切事情不能只看表面现象
────────────────────────────────────────
lofe (〖感激生活〗) 于 2003年12月05日09:22:58 星期五 说道:
我在 gcc version 3.2.1 [FreeBSD] 20021119 (release) 下也试了一下
结果是对于gcc来说是没有问题的,原因在于即使返回值是char或short,
gcc使用的仍然是整个eax,而不是只操作 al。这与vc编译器不同。
也就是说xceman的问题在gcc下应该不会出现,谁验证一下,hehe
源代码:
char foo(void) { return 0; }
int (*bar)(void) = (int (*)(void))foo;
int main(void)
{
int i, j;
i = j = 0xCCCCCCCC;
i = foo();
j = bar();
printf("i = 0x%08X, j = 0x%08X\n", i, j);
return 0;
}
gcc -S foo.c得到 foo.s,部分内容如下:
.globl foo
.type foo,@function
foo:
pushl %ebp
movl %esp, %ebp
movl $0, %eax
leave
ret
.globl main
.type main,@function
main:
...
call foo
movsbl %al,%eax ;由于是char到int的转换,符号扩展仍然进行了
movl %eax, -4(%ebp)
movl bar, %eax
call *%eax
movl %eax, -8(%ebp)
结果是:
%./foo
i = 0x00000000, j = 0x00000000
%
而vc则是
i = 0x00000000, j = 0xCCCCCC00
Press any key to continue
【 在 Sun (大灯泡) 的大作中提到: 】
: 从前面分析看,你这个程序好使只能是因为运气好
: 【 在 hotman (风) 的大作中提到: 】
: : 呵呵,我当然要用过才能敢下结论了:-)
: : 1,VC中
: : #include <search.h>
: : #include <string.h>
: : #include <stdio.h>
: : char compare( char **arg1, char **arg2 ); /* Declare a function for compare */
────────────────────────────────────────
lofe (〖感激生活〗) 于 2003年12月05日09:27:24 星期五 说道:
3054看了吗?还有上面这篇
我觉得问题已经清晰了呀,还是我的分析有问题?
【 在 Sun (大灯泡) 的大作中提到: 】
: xceman那样的问题
: 【 在 iamxiaohan (潇寒·System Programmer ^_^) 的大作中提到: 】
: : 出什么问题?
────────────────────────────────────────
Sun (大灯泡) 于 2003年12月05日09:31:28 星期五 说道:
结论就是:
依赖具体的编译器实现。可能同种编译器不同参数也会产生不同效果
所以这样的用法要禁止,它是不符合C标准的
【 在 lofe (〖感激生活〗) 的大作中提到: 】
: 3054看了吗?还有上面这篇
: 我觉得问题已经清晰了呀,还是我的分析有问题?
: 【 在 Sun (大灯泡) 的大作中提到: 】
: : xceman那样的问题
────────────────────────────────────────
lofe (〖感激生活〗) 于 2003年12月05日09:44:59 星期五 说道:
这就是了,编译器的不同效果就在于对返回值eax的处理上,
gcc将char或short放入eax,而vc则直接放入al或ax。其他
的编译器大概不外乎这两种处理之一。
【 在 Sun (大灯泡) 的大作中提到: 】
: 结论就是:
: 依赖具体的编译器实现。可能同种编译器不同参数也会产生不同效果
: 所以这样的用法要禁止,它是不符合C标准的
: 【 在 lofe (〖感激生活〗) 的大作中提到: 】
: : 3054看了吗?还有上面这篇
: : 我觉得问题已经清晰了呀,还是我的分析有问题?
────────────────────────────────────────
Sun (大灯泡) 于 2003年12月05日09:48:59 星期五 说道:
也许还有用栈传返回值的……
【 在 lofe (〖感激生活〗) 的大作中提到: 】
: 这就是了,编译器的不同效果就在于对返回值eax的处理上,
: gcc将char或short作符号扩展后返回eax,而vc则直接返回
: al或ax。其他的编译器大概不外乎这两种处理之一。
: 【 在 Sun (大灯泡) 的大作中提到: 】
: : 结论就是:
: : 依赖具体的编译器实现。可能同种编译器不同参数也会产生不同效果
: : 所以这样的用法要禁止,它是不符合C标准的
────────────────────────────────────────
lofe (〖感激生活〗) 于 2003年12月05日09:56:07 星期五 说道:
也许,不过那样得到的代码比如库函数,兼容性很不好吧,
因为大多数别的编译器都认为函数调用的返回结果在eax中
我推测:要能够调用gnu的库函数或者winapi,编译器就必须
用eax返回结果,不知道对不对,不要砍我,hehe
【 在 Sun (大灯泡) 的大作中提到: 】
也许还有用栈传返回值的……
【 在 lofe (〖感激生活〗) 的大作中提到: 】
: 这就是了,编译器的不同效果就在于对返回值eax的处理上,
: gcc将char或short作符号扩展后返回eax,而vc则直接返回
: al或ax。其他的编译器大概不外乎这两种处理之一。
: 【 在 Sun (大灯泡) 的大作中提到: 】
: : 结论就是:
: : 依赖具体的编译器实现。可能同种编译器不同参数也会产生不同效果
: : 所以这样的用法要禁止,它是不符合C标准的
────────────────────────────────────────
Sun (大灯泡) 于 2003年12月05日10:09:58 星期五 说道:
gnu的库函数也是可以重新编译的呀。:)
再说,咱不是说一定会这样,而是说可能如何
也许在另一个架构的CPU之下,还会有更出乎我们意料的实现方法
【 在 lofe (〖感激生活〗) 的大作中提到: 】
: 也许,不过那样得到的代码比如库函数,兼容性很不好吧,
: 因为大多数别的编译器都认为函数调用的返回结果在eax中
: 我推测:要能够调用gnu的库函数或者winapi,编译器就必须
: 用eax返回结果,不知道对不对,不要砍我,hehe
: 【 在 Sun (大灯泡) 的大作中提到: 】
: 也许还有用栈传返回值的……
: 【 在 lofe (〖感激生活〗) 的大作中提到: 】
: : 这就是了,编译器的不同效果就在于对返回值eax的处理上,
────────────────────────────────────────
iamxiaohan (潇寒·System Programmer ^_^) 于 2003年12月05日13:56:08 星期五 说道:
bsearch本来就是依赖编译器的实现函数,
一切以void*做为通用参量的函数都是与编译器级具体的计算机体系结构相关的,
它们不能产生可移植代码
【 在 Sun (大灯泡) 的大作中提到: 】
: 结论就是:
: 依赖具体的编译器实现。可能同种编译器不同参数也会产生不同效果
: 所以这样的用法要禁止,它是不符合C标准的
: 【 在 lofe (〖感激生活〗) 的大作中提到: 】
: : 3054看了吗?还有上面这篇
: : 我觉得问题已经清晰了呀,还是我的分析有问题?
────────────────────────────────────────
lofe (〖感激生活〗) 于 2003年12月05日14:26:14 星期五 说道:
【 在 iamxiaohan (潇寒·System Programmer ^_^) 的大作中提到: 】
: bsearch本来就是依赖编译器的实现函数,
bsearch是c的标准库函数,只要你按照c标准来调用,就不依赖于编译器。
: 一切以void*做为通用参量的函数都是与编译器级具体的计算机体系结构相关的,
: 它们不能产生可移植代码
void*参数可以说是为了简化接口,尤其是在callback中,它是让这个函数的
实现者来解释其意义,而跟编译器没有任何关系。
eg. int main(int argc, void *p) {return 0;} 显然是可以移植的
: 【 在 Sun (大灯泡) 的大作中提到: 】
: : 结论就是:
: : 依赖具体的编译器实现。可能同种编译器不同参数也会产生不同效果
: : 所以这样的用法要禁止,它是不符合C标准的
────────────────────────────────────────
iamxiaohan (潇寒·System Programmer ^_^) 于 2003年12月05日14:32:49 星期五 说道:
不能这样说,
bserach不是ANSI C的标准所规定的,只是编译器厂商提供的库,
关键是里面设计到了这样一个void* p的使用,
考虑一下bsearch的实现,
因为是void*,所以编译器无法知道指针的所指对象的大小,也就是指针所指对象
所占的内存,这就只能过过程序指定来实现了,
对于 void* p ;
如果是char,那么 p++ 就是移动一个字节,
如果是 int,那么在 intel i386 结构上 p++ 就是
p = (void*)( (unsigned int)p + 4 ) ;
这是按照intel以低低高高的存放原理实现的,
但在其它cpu结构下,不一定是以低低高高实现的,因此使用上要出问题的
【 在 lofe (〖感激生活〗) 的大作中提到: 】
: 【 在 iamxiaohan (潇寒·System Programmer ^_^) 的大作中提到: 】
: : bsearch本来就是依赖编译器的实现函数,
: bsearch是c的标准库函数,只要你按照c标准来调用,就不依赖于编译器。
: : 一切以void*做为通用参量的函数都是与编译器级具体的计算机体系结构相关的,
: : 它们不能产生可移植代码
: void*参数可以说是为了简化接口,尤其是在callback中,它是让这个函数的
: 实现者来解释其意义,而跟编译器没有任何关系。
: eg. int main(int argc, void *p) {return 0;} 显然是可以移植的
────────────────────────────────────────
lofe (〖感激生活〗) 于 2003年12月05日15:31:56 星期五 说道:
【 在 iamxiaohan (潇寒·System Programmer ^_^) 的大作中提到: 】
: 不能这样说,
: bserach不是ANSI C的标准所规定的,只是编译器厂商提供的库,
刚才特地上搜索了一下,bsearch 是ANSI C的标准函数,位于stdlib,
就像malloc一样.
。
: 关键是里面设计到了这样一个void* p的使用,
: 考虑一下bsearch的实现,
: 因为是void*,所以编译器无法知道指针的所指对象的大小,也就是指针所指对象
: 所占的内存,这就只能过过程序指定来实现了,
: 对于 void* p ;
: 如果是char,那么 p++ 就是移动一个字节,
: 如果是 int,那么在 intel i386 结构上 p++ 就是
: p = (void*)( (unsigned int)p + 4 ) ;
: 这是按照intel以低低高高的存放原理实现的,
你说的这些都是对的,compare是我们自己提供的,因而我们知道。
而实际上 bsearch也知道void *p 的大小,因为 base有了,size 为
每个元素的占据的空间,一共有nmemb个元素,剩下的就是指针运算,
遍历了。
man bsearch:
SYNOPSIS
#include <stdlib.h>
void *bsearch(const void *key, const void *base, size_t nmemb,
size_t size, int (*compar)(const void *, const void *));
DESCRIPTION
The bsearch() function searches an array of nmemb objects, the initial
member of which is pointed to by base, for a member that matches the
object pointed to by key. The size of each member of the array is
specified by size.
────────────────────────────────────────
Sun (大灯泡) 于 2003年12月05日16:22:33 星期五 说道:
问题不是出在void*,而是出在作为返回值的char
【 在 iamxiaohan (潇寒·System Programmer ^_^) 的大作中提到: 】
: 不能这样说,
: bserach不是ANSI C的标准所规定的,只是编译器厂商提供的库,
: 关键是里面设计到了这样一个void* p的使用,
: 考虑一下bsearch的实现,
: 因为是void*,所以编译器无法知道指针的所指对象的大小,也就是指针所指对象
: 所占的内存,这就只能过过程序指定来实现了,
: 对于 void* p ;
: 如果是char,那么 p++ 就是移动一个字节,
: 如果是 int,那么在 intel i386 结构上 p++ 就是
: p = (void*)( (unsigned int)p + 4 ) ;
: 这是按照intel以低低高高的存放原理实现的,
────────────────────────────────────────
iamxiaohan (潇寒·System Programmer ^_^) 于 2003年12月05日22:23:51 星期五 说道:
我是说另外一个问题,是关于void*的移值性问题。
【 在 Sun (大灯泡) 的大作中提到: 】
: 问题不是出在void*,而是出在作为返回值的char
: 【 在 iamxiaohan (潇寒·System Programmer ^_^) 的大作中提到: 】
: : 不能这样说,
: : bserach不是ANSI C的标准所规定的,只是编译器厂商提供的库,
: : 关键是里面设计到了这样一个void* p的使用,
: : 考虑一下bsearch的实现,
: : 因为是void*,所以编译器无法知道指针的所指对象的大小,也就是指针所指对象
: : 所占的内存,这就只能过过程序指定来实现了,
: : 对于 void* p ;
: : 如果是char,那么 p++ 就是移动一个字节,
────────────────────────────────────────
iamxiaohan (潇寒·System Programmer ^_^) 于 2003年12月05日22:24:35 星期五 说道:
同STL一样,只是一种规定,每个编译器厂自行提供在特定平台下的实现
【 在 lofe (〖感激生活〗) 的大作中提到: 】
: 【 在 iamxiaohan (潇寒·System Programmer ^_^) 的大作中提到: 】
: : 不能这样说,
: : bserach不是ANSI C的标准所规定的,只是编译器厂商提供的库,
: 刚才特地上搜索了一下,bsearch 是ANSI C的标准函数,位于stdlib,
: 就像malloc一样.
: 。
: : 关键是里面设计到了这样一个void* p的使用,
: : 考虑一下bsearch的实现,
: : 因为是void*,所以编译器无法知道指针的所指对象的大小,也就是指针所指对象
────────────────────────────────────────
Sun (大灯泡) 于 2003年12月05日22:59:13 星期五 说道:
void*应该不会有移植问题吧?这个是纯C的
【 在 iamxiaohan (潇寒·System Programmer ^_^) 的大作中提到: 】
: 我是说另外一个问题,是关于void*的移值性问题。
: 【 在 Sun (大灯泡) 的大作中提到: 】
: : 问题不是出在void*,而是出在作为返回值的char
────────────────────────────────────────
iamxiaohan (潇寒·System Programmer ^_^) 于 2003年12月06日07:29:39 星期六 说道:
C语言不是JAVA,在语法上就不是可移植的。
对于void*,关键就是内存定位不可移植,在低低高高的体系结构的机子上,
它是以+定位,在不是低低高高的体系结构上,它以-定位,因此,你写的程序
就不能在两个体系结构不同的机器上移植。
【 在 Sun (大灯泡) 的大作中提到: 】
: void*应该不会有移植问题吧?这个是纯C的
: 【 在 iamxiaohan (潇寒·System Programmer ^_^) 的大作中提到: 】
: : 我是说另外一个问题,是关于void*的移值性问题。
────────────────────────────────────────
artist (手艺人) 于 2003年12月06日10:45:55 星期六 说道:
个人认为:
1 C程序也好,Java程序也好,要想移植,都需要在目标体系结构的机器上重新编译。
毕竟C和Java都是高级语言,不能直接在目标机上运行。
2 Java所谓的移植性好,也是指将Java代码统统编译成通用中间形式,大概叫Java
bytecode 吧,而各种目标机都有自己的bytecode解释器,解释出来的还是各自的机
器码。
3 高级语言程序一般都是可移植的,只要有对应目标机的编译器。编译器越强大,移植
越方便。
一家之言,仅供参考。
【 在 iamxiaohan (潇寒·System Programmer ^_^) 的大作中提到: 】
: C语言不是JAVA,在语法上就不是可移植的。
: 对于void*,关键就是内存定位不可移植,在低低高高的体系结构的机子上,
: 它是以+定位,在不是低低高高的体系结构上,它以-定位,因此,你写的程序
: 就不能在两个体系结构不同的机器上移植。
: 【 在 Sun (大灯泡) 的大作中提到: 】
: : void*应该不会有移植问题吧?这个是纯C的
────────────────────────────────────────
Sun (大灯泡) 于 2003年12月06日12:38:02 星期六 说道:
好像不全对。
除非你对int或者float这样的sizeof>1的类型的存储空间进行逐字节的操作,否则是不会
遇到高高低低的问题的(这个学名叫big end...和small end...., end开头的单词,具体
怎么拼忘了,手头也查不到,谁知道?)。高高低低的问题已经通过类型进行隐藏了。
比如:
int i;
void* p= (void*)&i;
*(int*)p = 12345;
在任何计算机上面的语句都是有效的
【 在 iamxiaohan (潇寒·System Programmer
^_^) 的大作中提到: 】: C语言不是JAVA,在语法上就不是可移植的。
: 对于void*,关键就是内存定位不可移植,在低低高高的体系结构的机子上,
: 它是以+定位,在不是低低高高的体系结构上,它以-定位,因此,你写的程序
: 就不能在两个体系结构不同的机器上移植。
: 【 在 Sun (大灯泡) 的大作中提到: 】
: : void*应该不会有移植问题吧?这个是纯C的
────────────────────────────────────────
deem (沙丘男爵) 于 2003年12月06日14:25:52 星期六 说道:
BIG endian
little endian
【 在 Sun (大灯泡) 的大作中提到: 】
: 好像不全对。
: 除非你对int或者float这样的sizeof>1的类型的存储空间进行逐字节的操作,否则是不会
: 遇到高高低低的问题的(这个学名叫big end...和small end...., end开头的单词,具体
: 怎么拼忘了,手头也查不到,谁知道?)。高高低低的问题已经通过类型进行隐藏了。
: 比如:
: int i;
: void* p= (void*)&i;
: *(int*)p = 12345;
: 在任何计算机上面的语句都是有效的
────────────────────────────────────────
lofe (〖感激生活〗) 于 2003年12月06日15:02:30 星期六 说道:
概念问题,原来你说的是二进制上的跨平台问题。
移植是指源码级的吧?
没有人能用C直接写出二进制通用程序,k&r估计也不能。
否则就不会有com,corba
【 在 iamxiaohan (潇寒·System Programmer ^_^) 的大作中提到: 】
: 同STL一样,只是一种规定,每个编译器厂自行提供在特定平台下的实现
: 【 在 lofe (〖感激生活〗) 的大作中提到: 】
: : 刚才特地上搜索了一下,bsearch 是ANSI C的标准函数,位于stdlib,
: : 就像malloc一样.
: : 。
────────────────────────────────────────
lofe (〖感激生活〗) 于 2003年12月06日15:07:42 星期六 说道:
只有一个例外,不同平台之间的通信问题,比如tcp/ip,存在网络字节顺序问题,:-)
【 在 Sun (大灯泡) 的大作中提到: 】
: 好像不全对。
: 除非你对int或者float这样的sizeof>1的类型的存储空间进行逐字节的操作,否则是不会
: 遇到高高低低的问题的(这个学名叫big end...和small end...., end开头的单词,具体
: 怎么拼忘了,手头也查不到,谁知道?)。高高低低的问题已经通过类型进行隐藏了。
: 比如:
: int i;
: void* p= (void*)&i;
: *(int*)p = 12345;
: 在任何计算机上面的语句都是有效的
────────────────────────────────────────
Sun (大灯泡) 于 2003年12月06日15:11:03 星期六 说道:
这就是对sizeof>1的进行逐字节的操作呀
【 在 lofe (〖感激生活〗) 的大作中提到: 】
: 只有一个例外,不同平台之间的通信问题,比如tcp/ip,存在网络字节顺序问题,:-)
: 【 在 Sun (大灯泡) 的大作中提到: 】
: : 好像不全对。
: : 除非你对int或者float这样的sizeof>1的类型的存储空间进行逐字节的操作,否则是不会
: : 遇到高高低低的问题的(这个学名叫big end...和small end...., end开头的单词,具体
: : 怎么拼忘了,手头也查不到,谁知道?)。高高低低的问题已经通过类型进行隐藏了。
: : 比如:
: : int i;
: : void* p= (void*)&i;
────────────────────────────────────────
lofe (〖感激生活〗) 于 2003年12月06日15:23:26 星期六 说道:
想了又想,好像你刚好写反了,^_^
【 在 Sun (大灯泡) 的大作中提到: 】
: 这就是对sizeof>1的进行逐字节的操作呀
~~~~~~~~~~~~既然是逐字节,那就相当于sizeof==1了,:-)
程序设计实践 8.6节专门讨论了这个移植问题,解决办法是:
写可移植的代码,总按照正规的顺序写出各个字节,(在另一端)再
一次一个字节的读回,把数据重装起来
这个方法也可以推广到结构。。。
: 【 在 lofe (〖感激生活〗) 的大作中提到: 】
: : 只有一个例外,不同平台之间的通信问题,比如tcp/ip,存在网络字节顺序问题,:-)
────────────────────────────────────────
Sun (大灯泡) 于 2003年12月06日15:34:03 星期六 说道:
不是写反了,是不严密
我的意思是比如
int i=1;
char* p = (char*)&i;
*p = 0;
这样将使i==0,在x86上。但是这样就默认了x86的endian
【 在 lofe (〖感激生活〗) 的大作中提到: 】
: 想了又想,好像你刚好写反了,^_^
: 【 在 Sun (大灯泡) 的大作中提到: 】
: : 这就是对sizeof>1的进行逐字节的操作呀
: ~~~~~~~~~~~~既然是逐字节,那就相当于sizeof==1了,:-)
: 程序设计实践 8.6节专门讨论了这个移植问题,解决办法是:
: 写可移植的代码,总按照正规的顺序写出各个字节,(在另一端)再
: 一次一个字节的读回,把数据重装起来
────────────────────────────────────────
ecomer (ecomer) 于 2003年12月06日18:38:03 星期六 说道:
char* p = (char*)i;是什么意思?
觉得应该是 char*p = (char*)(&i); 这样p才能取道i的地址。
【 在 Sun (大灯泡) 的大作中提到: 】
: 不是写反了,是不严密
: 我的意思是比如
: int i=1;
: char* p = (char*)i;
: *p = 0;
: 这样将使i==0,在x86上。但是这样就默认了x86的endian
────────────────────────────────────────
Sun (大灯泡) 于 2003年12月06日20:35:54 星期六 说道:
是少了一个&,谢谢
【 在 ecomer (ecomer) 的大作中提到: 】
: char* p = (char*)i;是什么意思?
: 觉得应该是 char*p = (char*)(&i); 这样p才能取道i的地址。
: 【 在 Sun (大灯泡) 的大作中提到: 】
: : 不是写反了,是不严密
: : 我的意思是比如
: : int i=1;
: : char* p = (char*)i;
: : *p = 0;
────────────────────────────────────────
Powered by KBS BBS 2.0 (http://dev.kcn.cn)
页面执行时间:617.418毫秒