Chinaunix

标题: sizeof究竟是怎样实现的? [打印本页]

作者: tanoak    时间: 2005-06-09 17:32
标题: sizeof究竟是怎样实现的?
sizeof究竟是怎样实现的?能够进行那么多种长度计算
作者: bleem1998    时间: 2005-06-09 17:37
标题: sizeof究竟是怎样实现的?
关注
我猜是编译器在编译的时候就直接支持了
作者: gerysand    时间: 2005-06-09 18:04
标题: sizeof究竟是怎样实现的?
楼上的想法是对的,sizeof,是在编译的时候,查找符号表,判断类型,然后根据基础类型来取值的,如果是struct则是看类型声明符号表来判定,如果字符串则是通过常量表来判断,具体可以参考编译原理的符号表管理章节,一般都有讲,如果没讲,不要读这本书,呵呵
作者: nait    时间: 2005-06-09 18:17
标题: sizeof究竟是怎样实现的?
是啊,sizeof和+, -, *, /这些是一类的,呵呵
作者: kernelxu    时间: 2005-06-09 21:23
标题: sizeof究竟是怎样实现的?
是啊,sizeof和+, -, *, /这些是一类的,呵呵


sizeof()是运算符,不是函数。
作者: 思一克    时间: 2005-06-10 09:53
标题: sizeof究竟是怎样实现的?
是个运算符号。大部分情况下在编译时就运算完毕。特殊情况是



  1. f(int len)
  2. {
  3. char buf[len];
  4.     printf("sizeof buf = %d\n", sizeof(buf));
  5. }

  6. main()
  7. {

  8.     f(1234);

  9. }

复制代码

作者: bleem1998    时间: 2005-06-10 11:26
标题: sizeof究竟是怎样实现的?
:0
长见识了
那这又是怎样实现的呢?
作者: violetwind    时间: 2005-06-10 11:36
标题: sizeof究竟是怎样实现的?
运行时候实现的了----呵呵,不知道对不对?
数组buf的长度在调用函数f前没有确定,编译的时候符号表中还未登记相应的数据项
作者: 思一克    时间: 2005-06-10 11:49
标题: sizeof究竟是怎样实现的?
运行时进行的计算
作者: apollolegend    时间: 2005-06-10 12:17
标题: sizeof究竟是怎样实现的?
sizeof(int)在不同的编译器下会有不同,还是在不同字长的处理器上会有不同。
作者: virmin    时间: 2005-06-10 13:19
标题: sizeof究竟是怎样实现的?
原帖由 "思一克" 发表:
是个运算符号。大部分情况下在编译时就运算完毕。特殊情况是

代码:


f(int len)
{
char buf[len];
   printf("sizeof buf = %d\n", sizeof(buf));
}

main()
{

   f(1234);

}


void f(int len)
{

      char buf[len]; /* 不要误人子弟,这样连编译都通不过滴 */
}

定义数组时,指定数组的长度必须是常量,也就是在编译时能确定的
象这样的写法,根本不可能通过编译,居然还说在运行时确定...
作者: mq110    时间: 2005-06-10 13:23
标题: sizeof究竟是怎样实现的?
思兄 这次应该是犯个错误了。
作者: seeLnd    时间: 2005-06-10 13:25
标题: sizeof究竟是怎样实现的?
[quote]原帖由 "思一克"]是个运算符号。大部分情况下在编译时就运算完毕。特殊情况是 [/quote 发表:

我估计就是编译器自己将代码改掉:
printf("sizeof buf = %d\n", sizeof(buf));
printf("sizeof buf = %d\n", len*sizeof(char));
作者: 思一克    时间: 2005-06-10 13:27
标题: sizeof究竟是怎样实现的?
to mq110,

我实验过的,否则那敢说。

linux i386 GCC v3.2.2

变长ARRAY只可以是STACK变量
作者: seeLnd    时间: 2005-06-10 13:27
标题: sizeof究竟是怎样实现的?
原帖由 "virmin" 发表:
不要误人子弟,这样连编译都通不过滴 */
}

定义数组时,指定数组的长度必须是常量,也就是在编译时能确定的
象这样的写法,根本不可能通过编译,居然还说在运行时确定...

gcc早就实现了动态数组, 可以编译通过的
作者: aero    时间: 2005-06-10 13:30
标题: sizeof究竟是怎样实现的?
最开始是gcc开始支持动态数组。现在已经是C99的标准啦。^_^。

gcc还有对case区间的扩展支持呢。
作者: mq110    时间: 2005-06-10 13:35
标题: sizeof究竟是怎样实现的?
原帖由 "思一克" 发表:
to mq110,

我实验过的,否则那敢说。

linux i386 GCC v3.2.2

变长ARRAY只可以是STACK变量


果然行. 思兄是对的. 不好意思哦.
作者: 思一克    时间: 2005-06-10 13:35
标题: sizeof究竟是怎样实现的?
不是这样的。是运行时计算出来的。用了6,7行汇编。

原帖由 "seeLnd" 发表:

我估计就是编译器自己将代码改掉:
printf("sizeof buf = %d\n", sizeof(buf));
printf("sizeof buf = %d\n", len*sizeof(char));

作者: seeLnd    时间: 2005-06-10 13:39
标题: sizeof究竟是怎样实现的?
printf("sizeof buf = %d\n", len*sizeof(char));
这行代码不就是运行时才能算出来么.
作者: 思一克    时间: 2005-06-10 13:42
标题: sizeof究竟是怎样实现的?
to seelnd,

本质上也是你说的那样。
作者: virmin    时间: 2005-06-10 13:43
标题: sizeof究竟是怎样实现的?
第一: 标准C是肯定不支持
第二: C++什么C99标准不太清楚, 但不是所有的C++编译器都支持这个标准,起码VC就不支持

所以,象这样的东西,有条件性限制的,最好给个说明,否则还是容易误导
作者: 思一克    时间: 2005-06-10 13:45
标题: sizeof究竟是怎样实现的?
to virmin,

对不起。我一直用linux gcc. 不知道 VC 怎样。如果舞蹈了,请原谅。
作者: aero    时间: 2005-06-10 13:47
标题: sizeof究竟是怎样实现的?
原帖由 "virmin" 发表:
第一: 标准C是肯定不支持
第二: C++什么C99标准不太清楚, 但不是所有的C++编译器都支持这个标准,起码VC就不支持

所以,象这样的东西,有条件性限制的,最好给个说明,否则还是容易误导


啥叫标准C?

C99标准不是标准C?
作者: virmin    时间: 2005-06-10 13:51
标题: sizeof究竟是怎样实现的?
...
投降!
作者: virmin    时间: 2005-06-10 14:13
标题: sizeof究竟是怎样实现的?
查了一下C99标准, 真不知道该说什么...
而且发现自己使用的两台aix机器, 有一台的编译器较新是支持这个标准的
写了
int n;
char str[n];
....
编译也通过, 寒...
作者: virmin    时间: 2005-06-10 20:27
标题: sizeof究竟是怎样实现的?
提到C语言的历史,就必须提UNIX,也就必须提AT&T贝尔实验室的三位杰出青年:Ken Thompson、Dennis Ritchie和Brian Kernighan。

1966年,23岁的Thompson大学毕业后加入了贝尔实验室。3年后Thompson用汇编设计出一个操作系统,取名UNIX。第二年,Thompson又根据BCPL语言设计出无类型的B语言。无类型的意思相当于说B语言中只有int类型,而没有long、float等其它类型,前面提到的GEL就是无类型语言。

1972年,Thompson好友Ritchie在B语言的基础上发明了有类型的C语言(最初称为new B语言)。C语言的主要目就是用来编写UNIX操作系统,也因此,多年来,运行在UNIX操作系统的C语言一直是公认的标准。因C语言脱胎于无类型的B语言,C语言是弱类型语言——不进行强类型检查,此后的标准C逐渐加强了类型检查。

1973年,Thompson重新用C语言改写了UNIX操作系统,成功突破操作系统必须用汇编语言的禁区,用C语言编写的操作系统在移植性和代码效率方面做到了最好的平衡。UNIX操作系统上使用的二进制可执行文件格式就是COFF格式。后来微软崛起时,吸纳了大量UNIX程序员,新的二进制可执行文件格式PE就建立在COFF基础上,这已经是后话。

1978年,由Kernighan和Ritchie合著了著名的“The C Programming Language”一书,简称为《K&R C》。这本书受到了广泛的赞誉,被誉为C语言的圣经,其二人也因此而名声大振。这时期各种版本的C语言都以此作蓝本,K&R C成了事实上的标准。CCS的编译器就支持K&R C。经典又俏皮的入门例子“hello word”即源于此书,笔者在写本书第二章时还专门查询了原书的写法。

1983年夏天,美国国家标准化组织(ANSI)成立了C 语言工作小组X3J11,开始了C语言的标准化。标准化工作费时六年,冗长又拖拉:既要考虑兼容事实标准K&R C,又有各方利益在此角斗,比如,微软希望把自己编译器上的关键字far、near等加入到标准中,微软背后倚持的是:PC上的C语言用户当时已是多数。直到1989年冬天,才正式出台了通常称之为ANSI C的标准,常简称为:标准C或C89。紧接着,更权威的国际标准化组织(ISO)做了些页面调整的小改动后,接纳了ANSI C。随后,1990年初,ANSI又重新采纳了ISO标准。至此C语言的世界标准和美国标准合二为一。

1983年还有一件值得一提的事,Thompson与Ritchie同获计算机界的最高奖——图灵奖

至此业界的C编译器都开始向标准C靠拢或兼容。标准C的地位确定下来,但仍有一些改进。

1995年,ISO对C语言标准做了第一次修订,主要添加了一些函数库。1999年,ISO添加了一些新特性,如变长数组(即数组长度可动态变更)等;也废除了一些非常不好的特性,如外部函数不显式声明就直接引用(主要是为了加强类型检查)等,这个版本被称为C99。但C99显然没有获得C89那样的成功,直到今天,也很少有编译器支持。很大的原因是:能引领风潮的PC机的C用户,大都已经投入C++怀抱。现今真正使用C的领域大都是嵌入式开发、驱动和系统内核等,这些用户显然对运行效率非常敏感,而实现C99的新特性(如变长数组)意味着运行效率降低。

考虑到人类喜欢知道事情最终结果的天性,也为了对人物叙述有始有终,所以简述贝尔实验室的三位杰出人物近况如下:

Thompson:1998年与Ritchie同获国家技术奖。2000年,从贝尔实验室退休,时年59岁。

Ritchie:现仍在贝尔实验室,计算科学研发中心系统软件部经理,专注于操作系统、语言、硬件等。

Kernighan:2000年,从贝尔实验室退休。如今受聘于普林斯顿大学计算机科学系。

C易学,却随着经验的增长而经久耐用。”——Kernighan
作者: virmin    时间: 2005-06-10 20:35
标题: sizeof究竟是怎样实现的?
原帖由 "aero" 发表:


啥叫标准C?

C99标准不是标准C?

狭义上标准C应该指ANSI C吧,以前也没去弄个究竟,只知道ANSI C,连C89也不知道...sigh..
不过C99好象没彻底取代C89的地位,
做C做了这么久,居然还有这么个标准不知道...
作者: mq110    时间: 2005-06-10 20:39
标题: sizeof究竟是怎样实现的?
首先 佩服virmin 的执着的精神.
其次 感谢你又给大家找到这么好的资料去读.
作者: Ecore    时间: 2005-06-10 21:05
标题: sizeof究竟是怎样实现的?
原帖由 "kernelxu" 发表:


sizeof()是运算符,不是函数。


书中强调过.
sizeof()运算符
作者: 飞灰橙    时间: 2005-06-11 21:12
标题: sizeof究竟是怎样实现的?
typedef struct
{
     char c[2];
} TYPE_T;

sizeof (TYPE_T) = ?
作者: seeLnd    时间: 2005-06-12 12:22
标题: sizeof究竟是怎样实现的?
原帖由 "飞灰橙" 发表:
YPE_T;

sizeof (TYPE_T) = ?

有什么奇怪之处?
作者: higher555    时间: 2005-06-12 12:41
标题: sizeof究竟是怎样实现的?
第一次把C的历史了解得这么清楚!!
呵呵.....~~~
很感兴趣!!
努力学习!!
作者: netyang    时间: 2005-06-12 14:51
标题: sizeof究竟是怎样实现的?
学习了,学习了!

不过不值得为这个sizeof()运算符争成这样吧?

要不贴出来源码看看!
作者: mike_chen    时间: 2005-06-13 09:20
标题: sizeof究竟是怎样实现的?
同意楼主
作者: 飞灰橙    时间: 2005-07-01 15:08
标题: sizeof究竟是怎样实现的?
原帖由 "seeLnd" 发表:

有什么奇怪之处?


我在這邊試驗結果
有的編譯器出來是2,
有的是4,
都是編的32位的代碼.
作者: albcamus    时间: 2005-07-02 12:33
标题: sizeof究竟是怎样实现的?
原帖由 "飞灰橙" 发表:


我在這邊試驗結果
有的編譯器出來是2,
有的是4,
都是編的32位的代碼.


加上__attribute__((packed))肯定就都是2了。
作者: gerysand    时间: 2005-07-02 16:28
标题: sizeof究竟是怎样实现的?
看了思一克的代码,编译了一下,看了个究竟

  1. void f(int len)
  2. {
  3.         char array[len];
  4.         array[0]='a';
  5.         printf("sizeof array=%d\n",sizeof(len));
  6. }
复制代码


编译后

  1.         .file        "test.c"
  2.         .section        .rodata
  3. .LC0:
  4.         .string        "sizeof array=%d\n"
  5.         .text
  6. .globl f
  7.         .type        f, @function
  8. f:
  9.         pushl        %ebp
  10.         movl        %esp, %ebp
  11.         pushl        %ebx
  12.         subl        $4, %esp       
  13.         movl        %esp, %ebx
  14.         movl        8(%ebp), %eax        //取len到eax
  15.         decl        %eax
  16.         incl        %eax
  17.         addl        $15, %eax        //和下边三句合起来做16字节对齐,不知道干啥
  18.         shrl        $4, %eax        //
  19.         sall        $4, %eax        //
  20.         subl        %eax, %esp        //分配动态数组
  21.         movl        %esp, %eax        //接下来的代码就容易看了
  22.         movb        $97, (%eax)
  23.         subl        $8, %esp
  24.         pushl        $4
  25.         pushl        $.LC0
  26.         call        printf
  27.         addl        $16, %esp
  28.         movl        %ebx, %esp
  29.         movl        -4(%ebp), %ebx
  30.         leave
  31.         ret
  32.         .size        f, .-f
  33.         .section        .note.GNU-stack,"",@progbits
  34.         .ident        "GCC: (GNU) 3.3.2 20031022 (Red Hat Linux 3.3.2-1)"
复制代码


如果不是大家争论,还真不知道有这种用法,汗阿[/code]
作者: SANFXUNIL    时间: 2005-07-02 18:35
标题: sizeof究竟是怎样实现的?
对于变量求大小,就是查符号表的得到的。所以在宏定义中规定了不能使用sizeof运算符,因为那时符号表还没有填入东西。
作者: yuxh    时间: 2005-07-02 18:48
标题: sizeof究竟是怎样实现的?
[quote]原帖由 "SANFXUNIL"]对于变量求大小,就是查符号表的得到的。所以在宏定义中规定了不能使用sizeof运算符,因为那时符号表还没有填入东西。[/quote 发表:

这个有关系吗?
我经常在宏中用sizeof,没觉得有什么问题呀!
作者: 我有太多的问题    时间: 2005-12-08 23:36
我认为是不同的系统下有不同,好象较早期的是2,后来是4,新的有的是8
作者: yjh777    时间: 2005-12-09 10:46
原帖由 SANFXUNIL 于 2005-7-2 18:35 发表
对于变量求大小,就是查符号表的得到的。所以在宏定义中规定了不能使用sizeof运算符,因为那时符号表还没有填入东西。


宏只是预编译时简单的串替换而已,有你说的那种讲究吗?!不要zhuguanyice呀.
下面是内核里搜到的.没有一千也有八百行.
..............
arch/alpha/kernel/setup.c, line 108 -- #define N(a) (sizeof(a)/sizeof(a[0]))
arch/arm/lib/gcclib.h, line 13 -- #define SI_TYPE_SIZE (sizeof (SItype) * BITS_PER_UNIT)
arch/arm/mm/init.c, line 57 -- #define TABLE_SIZE ((TABLE_OFFSET + PTRS_PER_PTE) * sizeof(void *))
arch/arm/mm/mm-armo.c, line 32 -- #define MEMC_TABLE_SIZE (256*sizeof(unsigned long))
arch/cris/drivers/sync_serial.c, line 184 -- #define NUMBER_OF_PORTS (sizeof(ports)/sizeof(sync_port))
arch/cris/drivers/parport.c, line 174 -- #define NR_PORTS (sizeof(port_table)/sizeof(struct etrax100par_struct))
arch/cris/drivers/serial.c, line 590 -- #define NR_PORTS (sizeof(rs_table)/sizeof(struct e100_serial))
arch/i386/kernel/apm.c, line 484 -- #define ERROR_COUNT (sizeof(error_table)/sizeof(lookup_t))
arch/i386/kernel/mca.c, line 194 -- #define MCA_STANDARD_RESOURCES (sizeof(mca_standard_resources)/sizeof(struct
...............
作者: cjaizss    时间: 2005-12-09 10:46
sizeof是在预编译的时候实现的
作者: robinliu76    时间: 2005-12-09 20:52
标题: C99是支持动态数组的啊!
:)
作者: lenovo    时间: 2005-12-10 03:21
原帖由 virmin 于 2005-6-10 20:35 发表

狭义上标准C应该指ANSI C吧,以前也没去弄个究竟,只知道ANSI C,连C89也不知道...sigh..
不过C99好象没彻底取代C89的地位,
做C做了这么久,居然还有这么个标准不知道...

正如你给的资料所说,C89和ANSI C已经合二为一了。
的确C99没有流行起来,
有些编译器现在还不支持它。
作者: whyglinux    时间: 2005-12-10 12:12
>> sizeof是在预编译的时候实现的

注意:sizeof 不是预处理命令,而是运算符。其运算只能在编译预处理之后进行。

思一克 在上面提到的是一种特殊和有趣的情况:对于变长数组,其 sizeof 运算是在运行阶段进行的。这也是我所了解的关于 sizeof 运算符的唯一例外的情况。除此之外,sizeof运算都是在编译阶段进行的。

对于变长数组,只有C99标准和一些编译器自己的扩展支持;C89(ANSI C)以及标准C++都不支持变长数组。
作者: flw2    时间: 2005-12-12 11:35
ANSI C 与C89是一样的.除了一个区别.:一个是美国标准,一个是国际标准.
以前一直在想为什么数组的长度要是常量.感觉动态数组是很容易支持的. 就是为数组的定义加一段代码,留出一段栈空间就可以了,结束析构的时候调整一下就可以了,而数据段就不好办了. 理论上应该可以实现吧,如果不在乎浪费点的话.
作者: lenovo    时间: 2005-12-12 11:46
原帖由 flw2 于 2005-12-12 11:35 发表
ANSI C 与C89是一样的.除了一个区别.:一个是美国标准,一个是国际标准.
以前一直在想为什么数组的长度要是常量.感觉动态数组是很容易支持的. 就是为数组的定义加一段代码,留出一段栈空间就可以了,结束析构的时候调 ...

这一段栈空间你准备留多大?
作者: ktdid    时间: 2005-12-12 12:11
http://bbs.chinaunix.net/viewthr ... &extra=page%3D2
作者: ChinaDream    时间: 2005-12-13 02:25
原帖由 tanoak 于 2005-6-9 17:32 发表
sizeof究竟是怎样实现的?能够进行那么多种长度计算


sizeof()是编译器驱动功能,编译器在文法分析时根据符号中的size实数去replace!

类似
char Buffer[4096]={0};
其中{0}表示编译器会把变量放在.idata段里,表示变量已经被初始化成0!
char Buffer[4096];是放在.data段的!
作者: lnshg    时间: 2005-12-14 11:26
原帖由 apollolegend 于 2005-6-10 12:17 发表
sizeof(int)在不同的编译器下会有不同,还是在不同字长的处理器上会有不同。


关注中。。。期待解答
作者: shaoxia    时间: 2005-12-14 13:46
标题: 哪里有"The C Programming Language"电子书啊
听说"The C Programming Language"是经典巨著,小弟又是刚刚入道,便想看看.
作者: aobai    时间: 2008-05-09 04:23


[ 本帖最后由 aobai 于 2008-5-9 04:25 编辑 ]
作者: sdu_lizhipeng    时间: 2008-05-09 09:11
此贴2年半之后让它重见天日,我觉得里面的气氛很好,也曾在百度知道上看过类似的帖子,可给人的感觉却差异很大.
在这里混的人凭的不是知识水平的高低,而是凭的对知识的钻研与追求,孜孜不倦,以致永恒.
作者: stoneyrh    时间: 2008-05-09 09:45
编译的时候决定,运行的时候看到的只是一常数
作者: lipingtababa    时间: 2008-05-23 10:12
char Buffer[4096]={0};
其中{0}表示编译器会把变量放在.idata段里,表示变量已经被初始化成0!
char Buffer[4096];是放在.data段的!

你是什么格式啊?
我昨晚看的书,如果是ELF格式,char Buffer[4096]={0};应该在.data段里,而char Buffer[4096];则在.bss段里,两者区别无非是一个有初始化,一个没有
作者: prc    时间: 2008-05-23 16:20
原帖由 SANFXUNIL 于 2005-7-2 18:35 发表
对于变量求大小,就是查符号表的得到的。所以在宏定义中规定了不能使用sizeof运算符,因为那时符号表还没有填入东西。

这个解释了长久以来一直在我心头的疑惑...
作者: ffxzzh    时间: 2011-10-26 14:03
#define   SIZEOF(x)           
  ({   typeof   (x)   _x;            
  (char   *)((&_x+1))   -   (char   *)(&_x);})
作者: ljpdxj    时间: 2011-10-26 14:34
to mq110,

我实验过的,否则那敢说。

linux i386 GCC v3.2.2

变长ARRAY只可以是STACK变量
思一克 发表于 2005-06-10 13:27



    对的哈,动态数组属于gcc对c标准的扩展部分
作者: yulihua49    时间: 2011-10-26 15:50
运行时进行的计算
思一克 发表于 2005-06-10 11:49



    错,编译时实现。




欢迎光临 Chinaunix (http://bbs.chinaunix.net/) Powered by Discuz! X3.2