免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 2359 | 回复: 8
打印 上一主题 下一主题

[C] 存取效率问题 [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2008-08-01 00:21 |只看该作者 |倒序浏览
char s1[] = "aaaaaaaaaaaaaaa";

char *s2 = "bbbbbbbbbbbbbbbbb";
---------------------------------------------
上面两种定义方式,在下面程序中,哪种存取方式更快一点?为什么?
#include<stdio.h>

int main()

{

char a = 1;

char c[] = "1234567890";

char *p ="1234567890";

a = c[1];

a = p[1];

return 0;
}

[ 本帖最后由 c_bee 于 2008-8-1 00:23 编辑 ]

论坛徽章:
0
2 [报告]
发表于 2008-08-01 00:23 |只看该作者
原帖由 c_bee 于 2008-8-1 00:21 发表
char s1[] = "aaaaaaaaaaaaaaa";

char *s2 = "bbbbbbbbbbbbbbbbb";
---------------------------------------------
上面两种定义方式,在下面程序中,哪种存取方式更快一点?为什么?
#include

vo ...


你可以循环一万次
然后time看看
动下手
有点想法了以后大家再讨论更好些

[ 本帖最后由 blizzard213 于 2008-8-1 01:03 编辑 ]

论坛徽章:
0
3 [报告]
发表于 2008-08-01 00:57 |只看该作者
其实...哪个效率高我知道
但我想知道的是
怎么从底层来解释其效率之所以高,因为我得到的答案自己理解不通,解释不了

论坛徽章:
0
4 [报告]
发表于 2008-08-01 01:03 |只看该作者
原帖由 c_bee 于 2008-8-1 00:57 发表
其实...哪个效率高我知道
但我想知道的是
怎么从底层来解释其效率之所以高,因为我得到的答案自己理解不通,解释不了



我的系统不方便
lz可以gcc -S
然后去数汇编指令
查intel开发手册加时钟周期

这个应该不难

这个够底层了吧。。。

我用mingw看了下 你的代码是:

        .file        "effi.c"
        .def        ___main;        .scl        2;        .type        32;        .endef
        .section .rdata,"dr"
LC0:
        .ascii "1234567890\0"
        .text
.globl _main
        .def        _main;        .scl        2;        .type        32;        .endef
_main:
        pushl        %ebp
        movl        %esp, %ebp
        subl        $72, %esp
        andl        $-16, %esp
        movl        $0, %eax
        addl        $15, %eax
        addl        $15, %eax
        shrl        $4, %eax
        sall        $4, %eax
        movl        %eax, -60(%ebp)
        movl        -60(%ebp), %eax
        call        __alloca
        call        ___main
        movb        $1, -9(%ebp)                 // -9(%ebp) : a
        movl        LC0, %eax
        movl        %eax, -40(%ebp)          // -40(%ebp) : char c[] : c[0]
        movl        LC0+4, %eax                 //
        movl        %eax, -36(%ebp)          // c[1]
        movzwl        LC0+8, %eax
        movw        %ax, -32(%ebp)
        movzbl        LC0+10, %eax
        movb        %al, -30(%ebp)           // c[9]
        movl        $LC0, -44(%ebp)
        movzbl        -39(%ebp), %eax          //
        movb        %al, -9(%ebp)               // a = c[1];
        movl        -44(%ebp), %eax          // &p[0];
        incl        %eax                            // &p[1];
        movzbl        (%eax), %eax
        movb        %al, -9(%ebp)               // a = p[1];
        movl        $0, %eax
        leave
        ret
==============================
我加了些简单的注释
lz自己看看吧

数组的初始化进行了全数据拷贝
而指针的初始化没有只通过首地址加偏移寻址

[ 本帖最后由 blizzard213 于 2008-8-1 01:31 编辑 ]

论坛徽章:
0
5 [报告]
发表于 2008-08-01 01:58 |只看该作者
原帖由 c_bee 于 2008-8-1 00:21 发表
char s1[] = "aaaaaaaaaaaaaaa";

char *s2 = "bbbbbbbbbbbbbbbbb";
---------------------------------------------
上面两种定义方式,在下面程序中,哪种存取方式更快一点?为什么?
#include

int ...

如果是那个数组是全局变量,则两者是等同的。

如果像你那样写,指针那个效率高,数组的低。

因为指针的,只需在只读数据区,写一段数据就可以了。

而数组的,不仅要完成上面的操作,而且还要把那段数据copy到栈里去。

[ 本帖最后由 gtkmm 于 2008-8-1 02:00 编辑 ]

论坛徽章:
0
6 [报告]
发表于 2008-08-01 23:55 |只看该作者
如果单论初始化赋值:
char c[] = "1234567890";
char *p ="1234567890";
那的确是指针比地址快,呃,如果只是这样我就没必要问这个问题了:wink:

当然,作为已存在问题的一部分,原因也可以再描述一下:
初始化时,的确如gtkmm所说,数组要整个拷贝到堆栈中,所以慢了

aaaaaaaaaaa是在运行时刻赋值的;
而bbbbbbbbbbb是在编译时就确定的(常量放在静态存储区);
但在以后的存取中,在栈上的数组比指针所指向的字符串(例如堆)快。 ——就是我下面要说的问题了
-------------------------------------------------------
我说的存取效率,其实只是这两句:
a = c[1];
a = p[1];

自己生成了一下汇编代码如下:
; 13   : a = c[1];
  00047 8a 4d f1  mov  cl, BYTE PTR _c$[ebp+1]//属于存储器寻址中的寄存器基址寻址方式
  0004a 88 4d fc  mov  BYTE PTR _a$[ebp], cl
; 14   :
; 15   : a = p[1];
  0004d 8b 55 ec  mov  edx, DWORD PTR _p$[ebp]//为存储器寻址中的基址变址寻址方式
  00050 8a 42 01  mov  al, BYTE PTR [edx+1]
  00053 88 45 fc  mov  BYTE PTR _a$[ebp], al
所以,应该是a=c[1]比a=p[1]快!
用汇编上的寻址方式来解释,因为基址变址寻址比基址方式多了个求地址的中间步骤,所以应该是比前者慢一些

————————————————————————————————————————
昨天发贴后想了半天,觉得应该是这样,班门弄斧了,不知道各位大侠以为如何?

[ 本帖最后由 c_bee 于 2008-8-2 00:08 编辑 ]

论坛徽章:
0
7 [报告]
发表于 2008-08-02 00:02 |只看该作者
原帖由 c_bee 于 2008-8-1 23:55 发表
如果单论初始化赋值:
char c[] = "1234567890";
char *p ="1234567890";
那的确是指针比地址快,当然,如果只是这样我就没必要问这个问题了:wink:
--------------------------------------------------- ...

你的理解是对的,因为数组名可以看到一个常量地址,是立即数,而指针变量是变量,也就需要一次存取操作

论坛徽章:
0
8 [报告]
发表于 2008-08-02 00:46 |只看该作者
我说的存取效率,其实只是这两句:
a = c[1];
a = p[1];
这个似乎只是取。。; lz下面说的是取得时候数组更快?

char c[] = "1234567890";
char *p ="1234567890";
哪个更好呢?
一般情况:我建议是用第一种的。

论坛徽章:
0
9 [报告]
发表于 2008-08-02 01:31 |只看该作者

回复 #6 c_bee 的帖子

使 用 指 针 快
用 数 组 , 编 译 器 老 老 实 实 生 成 固 定 代 码 , 指 针 编 译 器 可 灵 活 进 行 多 种 优 化

char *p = "123456789";
a = p[1];
编 译 器 可 优 化 为 直 接  用 50 代 替 。

char c[] = "123456789";
a = c[1];
只 能 生 成 类 似 以 下 代 码 :
mov eax, $string"123456789"
mov [ebp-12], eax
mov cl, byte ptr [ebp-11]
mov byte ptr [ebp-13], cl
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP