user-0 提问: C语言 数组初始化为0 编译器是如何实现的？为什么比memset更耗时？

回复:
user: user-0
content: 其实 {0} 跟memset执行效率差不多，没多大区别。  我的main函数中，因为第一个调用了{0}方法，调用第一个函数，需要额外消耗掉一些其它时间。  我的测试结果不准确的。  结贴。

user: user-1
content: 无profiler不要谈效率！！尤其在这个云计算、虚拟机、模拟器、CUDA、多核 、多级cache、指令流水线、多种存储介质、……满天飞的时代！

user: user-2
content: 引用 10 楼 slx_391987 的回复:[quote=引用 8 楼 user-2 的回复:] 没有加上有优化吧，  应该都可以被优化成空函数。 编译时去掉了优化选项。[/quote]  那就没有可比性了， memset是充分优化了的。

user: user-0
content: 好吧，自己看了下汇编结果： function1 如下  	pushl	%ebp 	movl	%esp, %ebp 	subl	$1048600, %esp 	leal	-1048584(%ebp), %eax 	movl	$1048576, %edx 	movl	%edx, 8(%esp) 	movl	$0, 4(%esp) 	movl	%eax, (%esp) 	call	memset 	leave 	ret   function2如下：  	pushl	%ebp 	movl	%esp, %ebp 	subl	$1048600, %esp 	movl	$1048576, 8(%esp) 	movl	$0, 4(%esp) 	leal	-1048584(%ebp), %eax 	movl	%eax, (%esp) 	call	memset 	leave 	ret   比较了下，懂了。

user: user-0
content: 引用 8 楼 user-2 的回复:没有加上有优化吧，  应该都可以被优化成空函数。 编译时去掉了优化选项。

user: user-1
content: static char the_fastest_array[ARRAY_SIZE_MAX];//全局静态变量进程加载时就清零 No program run faster than no program! ——《观止 微软创建nt和未来的夺命狂奔》

user: user-2
content: 没有加上有优化吧，  应该都可以被优化成空函数。

user: user-1
content: 《程序员的自我修养——链接、装载与库》

user: user-1
content: 计算机组成原理→DOS命令→汇编语言→C语言（不包括C++）、代码书写规范→数据结构、编译原理、操作系统→计算机网络、数据库原理、正则表达式→其它语言（包括C++）、架构……  对学习编程者的忠告： 多用小脑和手，少用大脑、眼睛和嘴，会更快地学会编程！ 眼过千遍不如手过一遍！ 书看千行不如手敲一行！ 手敲千行不如单步一行！ 单步源代码千行不如单步Debug版对应汇编一行！ 单步Debug版对应汇编千行不如单步Release版对应汇编一行！  VC调试时按Alt+8、Alt+7、Alt+6和Alt+5,打开汇编窗口、堆栈窗口、内存窗口和寄存器窗口看每句C对应的汇编、单步执行并观察相应堆栈、内存和寄存器变化，这样过一遍不就啥都明白了吗。 对VC来说，所谓‘调试时’就是编译连接通过以后，按F10或F11键单步执行一步以后的时候，或者在某行按F9设了断点后按F5执行停在该断点处的时候。 （Turbo C或Borland C用Turbo Debugger调试,Linux或Unix下用GDB调试时,看每句C对应的汇编并单步执行观察相应内存和寄存器变化。）

user: user-0
content: memset如何实现的，我知道。    现在我想知道  {0} 方式编译器是如何实现的。

user: user-1
content: page	,132 		title	memset - set sections of memory	all	to one byte ;*** ;memset.asm	- set a	section	of memory to all one byte ; ;		Copyright (c) Microsoft	Corporation. All rights	reserved. ; ;Purpose: ;		contains the memset() routine ; ;*******************************************************************************  		.xlist 		include	cruntime.inc 		.list  page ;*** ;char *memset(dst, value, count) - sets	"count" bytes at "dst" to "value" ; ;Purpose: ;		Sets the first "count" bytes of the memory starting ;		at "dst" to the character value "value". ; ;		Algorithm: ;		char * ;		memset (dst, value,	count) ;				char *dst; ;				char value; ;				unsigned int count; ;				{ ;				char *start	= dst; ; ;				while (count--) ;						*dst++ = value; ;				return(start); ;				} ; ;Entry: ;		char *dst -	pointer	to memory to fill with value ;		char value - value to put in dst bytes ;		int	count -	number of bytes	of dst to fill ; ;Exit: ;		returns	dst, with filled bytes ; ;Uses: ; ;Exceptions: ; ;*******************************************************************************  		CODESEG  	extrn	_VEC_memzero:near 	extrn	__sse2_available:dword  		public	memset memset proc	\ 		dst:ptr	byte, \ 		value:byte,	\ 		count:dword  		OPTION PROLOGUE:NONE, EPILOGUE:NONE  		.FPO	( 0, 3,	0, 0, 0, 0 )  		mov		edx,[esp + 0ch]	; edx =	"count" 		mov		ecx,[esp + 4]	; ecx points to	"dst"  		test	edx,edx			; 0? 		jz		short toend		; if so, nothing to	do  		xor		eax,eax 		mov		al,[esp	+ 8]	; the byte "value" to be stored  ; Special case large block zeroing using SSE2 support 	test	al,al ;	memset using zero initializer? 	jne		dword_align 	cmp		edx,080h ; block size exceeds size threshold? 	jb		dword_align 	cmp		DWORD PTR __sse2_available,0 ; SSE2	supported? 	je		dword_align  	jmp		_VEC_memzero ; use fast	zero SSE2 implementation 	; no return  ; Align	address	on dword boundary dword_align:  		push	edi				; preserve edi 		mov		edi,ecx			; edi =	dest pointer  		cmp		edx,4			; if it's less then 4 bytes 		jb		tail			; tail needs edi and edx to	be initialized  		neg		ecx 		and		ecx,3			; ecx =	# bytes	before dword boundary 		jz		short dwords	; jump if address already aligned  		sub		edx,ecx			; edx =	adjusted count (for	later) adjust_loop: 		mov		[edi],al 		add		edi,1 		sub		ecx,1 		jnz		adjust_loop  dwords: ; set all 4	bytes of eax to	[value] 		mov		ecx,eax			; ecx=0/0/0/value 		shl		eax,8			; eax=0/0/value/0  		add		eax,ecx			; eax=0/0val/val  		mov		ecx,eax			; ecx=0/0/val/val  		shl		eax,10h			; eax=val/val/0/0  		add		eax,ecx			; eax =	all	4 bytes	= [value]  ; Set dword-sized blocks 		mov		ecx,edx			; move original	count to ecx 		and		edx,3			; prepare in edx byte count	(for tail loop) 		shr		ecx,2			; adjust ecx to	be dword count 		jz		tail			; jump if it was less then 4 bytes  		rep		stosd main_loop_tail: 		test	edx,edx			; if there is no tail bytes, 		jz		finish			; we finish, and it's time to leave ; Set remaining	bytes  tail: 		mov		[edi],al		; set remaining	bytes 		add		edi,1  		sub		edx,1			; if there is some more	bytes 		jnz		tail			; continue to fill them  ; Done finish: 		mov		eax,[esp + 8]	; return dest pointer 		pop		edi				; restore edi  		ret  toend: 		mov		eax,[esp + 4]	; return dest pointer  		ret  memset	endp  		end

user: user-1
content: 因为C:\Program Files\Microsoft Visual Studio 10.0\VC\crt\src\intel\memset.asm [code=asm		page	,132 		title	memset - set sections of memory	all	to one byte ;*** ;memset.asm	- set a	section	of memory to all one byte ; ;		Copyright (c) Microsoft	Corporation. All rights	reserved. ; ;Purpose: ;		contains the memset() routine ; ;*******************************************************************************  		.xlist 		include	cruntime.inc 		.list  page ;*** ;char *memset(dst, value, count) - sets	"count" bytes at "dst" to "value" ; ;Purpose: ;		Sets the first "count" bytes of the memory starting ;		at "dst" to the character value "value". ; ;		Algorithm: ;		char * ;		memset (dst, value,	count) ;				char *dst; ;				char value; ;				unsigned int count; ;				{ ;				char *start	= dst; ; ;				while (count--) ;						*dst++ = value; ;				return(start); ;				} ; ;Entry: ;		char *dst -	pointer	to memory to fill with value ;		char value - value to put in dst bytes ;		int	count -	number of bytes	of dst to fill ; ;Exit: ;		returns	dst, with filled bytes ; ;Uses: ; ;Exceptions: ; ;*******************************************************************************  		CODESEG  	extrn	_VEC_memzero:near 	extrn	__sse2_available:dword  		public	memset memset proc	\ 		dst:ptr	byte, \ 		value:byte,	\ 		count:dword  		OPTION PROLOGUE:NONE, EPILOGUE:NONE  		.FPO	( 0, 3,	0, 0, 0, 0 )  		mov		edx,[esp + 0ch]	; edx =	"count" 		mov		ecx,[esp + 4]	; ecx points to	"dst"  		test	edx,edx			; 0? 		jz		short toend		; if so, nothing to	do  		xor		eax,eax 		mov		al,[esp	+ 8]	; the byte "value" to be stored  ; Special case large block zeroing using SSE2 support 	test	al,al ;	memset using zero initializer? 	jne		dword_align 	cmp		edx,080h ; block size exceeds size threshold? 	jb		dword_align 	cmp		DWORD PTR __sse2_available,0 ; SSE2	supported? 	je		dword_align  	jmp		_VEC_memzero ; use fast	zero SSE2 implementation 	; no return  ; Align	address	on dword boundary dword_align:  		push	edi				; preserve edi 		mov		edi,ecx			; edi =	dest pointer  		cmp		edx,4			; if it's less then 4 bytes 		jb		tail			; tail needs edi and edx to	be initialized  		neg		ecx 		and		ecx,3			; ecx =	# bytes	before dword boundary 		jz		short dwords	; jump if address already aligned  		sub		edx,ecx			; edx =	adjusted count (for	later) adjust_loop: 		mov		[edi],al 		add		edi,1 		sub		ecx,1 		jnz		adjust_loop  dwords: ; set all 4	bytes of eax to	[value] 		mov		ecx,eax			; ecx=0/0/0/value 		shl		eax,8			; eax=0/0/value/0  		add		eax,ecx			; eax=0/0val/val  		mov		ecx,eax			; ecx=0/0/val/val  		shl		eax,10h			; eax=val/val/0/0  		add		eax,ecx			; eax =	all	4 bytes	= [value]  ; Set dword-sized blocks 		mov		ecx,edx			; move original	count to ecx 		and		edx,3			; prepare in edx byte count	(for tail loop) 		shr		ecx,2			; adjust ecx to	be dword count 		jz		tail			; jump if it was less then 4 bytes  		rep		stosd main_loop_tail: 		test	edx,edx			; if there is no tail bytes, 		jz		finish			; we finish, and it's time to leave ; Set remaining	bytes  tail: 		mov		[edi],al		; set remaining	bytes 		add		edi,1  		sub		edx,1			; if there is some more	bytes 		jnz		tail			; continue to fill them  ; Done finish: 		mov		eax,[esp + 8]	; return dest pointer 		pop		edi				; restore edi  		ret  toend: 		mov		eax,[esp + 4]	; return dest pointer  		ret  memset	endp  		end ][/code]

user: user-0
content: 引用 1 楼 slx_391987 的回复:不知道反汇编能够看出端倪来， 有无大神帮忙反汇编一下？ 小弟不会。 能够  --- >   能否。。

user: user-0
content: 不知道反汇编能够看出端倪来， 有无大神帮忙反汇编一下？ 小弟不会。