Newsgroup: it.comp.lang.c
Titolo: Re: assegnazione nel sorgente


-- 
Cybertoldo
Per rispondermi via email, sostituisci moc.liamg con 
gmail.com

 (idem, meglio: memset(a, 0, sizeof a); )
leggi: memset(a, 'x', sizeof a);
Ciao
(x-post e f/up su it.comp.lang.c)


 anche l'unico per inizializzare un intero array ad un valore qualunque.
Un metodo carino e veloce potrebbe essere quello di sfruttare
una struct che racchiude l'array in questione, usando
un altro array (struct) già inizializzato:
#include <stdio.h>
struct s_type {
        char buff[10];
};
static struct s_type wrap = {
        {'a','b','c'},
};
int main(void)
{
        struct s_type x = wrap;
        printf("%c %c %c\n",
                x.buff[0],x.buff[1],x.buff[2]);
        return 0;
}
Per inciso la copia "x = wrap" potrebbe riguardare
anche più dei 10 byte dell'array a causa
dei "padding" delle struct.
Ma di solito è più veloce dell'equivalente memset/memcpy.
--
Giorgio Silvestri
DSP/Embedded/Real Time OS   Software Engineer

 Ma di solito è più veloce dell'equivalente memset/memcpy.
Piu' veloce? Credo che dipenda molto da come ottimizzi il compilatore.
Ho fatto una rapido test con il gcc, aumentando pero' la dimensione 
dell'array buff a 100:
	struct s_type {
         	char buff[100];
	};
quindi ho generato il codice assembly 'src.s' con "gcc -S src.c"
Compilando con gcc, si vede chiaramente nel codice asm generato che, 
quando avviene la copia dell'oggetto 'wrap' in 'x'
	struct s_type x = wrap;
viene chiamata effettivamente la funzione memcpy (vd. il file src.s sotto).
In pratica, e' come se l'istruzione fosse stata scritta cosi':
	struct s_type x;
	memcpy(&x, &wrap, sizeof(x));
Quando invece le dimensioni della struttura s_type sono piu' contenute, 
il compilatore ottimizza diversamente - e il vantaggio in efficienza 
rispetto a una esplicita chiamata della memcpy potrebbe essere proprio 
questo (almeno con il gcc).
Ciao
== src.s ===
	.file	"src.c"
	.data
	.align 32
	.type	wrap, @object
	.size	wrap, 100
wrap:
	.byte	97
	.byte	98
	.byte	99
	.zero	97
	.section	.rodata
.LC0:
	.string	"%c %c %c\n"
	.text
.globl main
	.type	main, @function
main:
	pushl	%ebp
	movl	%esp, %ebp
	subl	$120, %esp
	andl	$-16, %esp
	movl	$0, %eax
	addl	$15, %eax
	addl	$15, %eax
	shrl	$4, %eax
	sall	$4, %eax
	subl	%eax, %esp
	leal	-100(%ebp), %ecx
	movl	$wrap, %edx
	movl	$100, %eax
	subl	$4, %esp
	pushl	%eax
	pushl	%edx
	pushl	%ecx
==>	call	memcpy
	addl	$16, %esp
	movb	-98(%ebp), %al
	movsbl	%al,%edx
	movb	-99(%ebp), %al
	movsbl	%al,%ecx
	movb	-100(%ebp), %al
	movsbl	%al,%eax
	pushl	%edx
	pushl	%ecx
	pushl	%eax
	pushl	$.LC0
	call	printf
	addl	$16, %esp
	movl	$0, %eax
	leave
	ret
	.....


> un altro array (struct) già inizializzato:
...cmq, parlando di "efficienza", quello che dici e' giusto - i 
compilatori spesso fanno /una copia/ tra dati (invece di una 
inizializzazione) come dici tu.
Riagganciandomi al mio post originale, ho fatto un'altra prova con il 
gcc, facendogli ancora produrre un listato in assembly. I sorgenti di 
prova sono i due sotto (z.c e z1.c).
Sorprendentemente (si fa per dire! :) ) entrambi producono un codice asm 
"praticamente" equivalente (vedi z.s e z1.s piu' sotto). In entrambi 
viene chiamata la memcpy() che andra' a copiare una regione dati 
'statica' azzerata (nb. parlo sempre del gcc su Linux e arch. x86 - in 
altri sistemi, e con altri compilatori, il modello di ottimizzazione 
puo' essere differente).
Ciao
=== z.c =====
#include <stdio.h>
int main(void)
{
	int an[1000] = { 0 };
	return 0;
}
=== z1.c =====
#include <stdio.h>
#include <string.h>
static int anZero[1000];
int main(void)
{
	int an[1000];
	memcpy(an, anZero, sizeof(an));
	return 0;
}
=============
=== z.s =====
         .file   "z.c"
         .section        .rodata
         .align 32
         .type   C.0.1657, @object
         .size   C.0.1657, 4000
C.0.1657:
         .zero   4000
         .text
.globl main
         .type   main, @function
main:
         pushl   %ebp
         movl    %esp, %ebp
         subl    $4008, %esp
         andl    $-16, %esp
         movl    $0, %eax
         addl    $15, %eax
         addl    $15, %eax
         shrl    $4, %eax
         sall    $4, %eax
         subl    %eax, %esp
         leal    -4000(%ebp), %ecx
         movl    $C.0.1657, %edx
         movl    $4000, %eax
         subl    $4, %esp
         pushl   %eax
         pushl   %edx
         pushl   %ecx
         call    memcpy
         addl    $16, %esp
         movl    $0, %eax
         leave
         ret
         .size   main, .-main
         ...
=== z1.s =====
         .file   "z1.c"
         .text
.globl main
         .type   main, @function
main:
         pushl   %ebp
         movl    %esp, %ebp
         subl    $4008, %esp
         andl    $-16, %esp
         movl    $0, %eax
         addl    $15, %eax
         addl    $15, %eax
         shrl    $4, %eax
         sall    $4, %eax
         subl    %eax, %esp
         leal    -4000(%ebp), %eax
         movl    %eax, %ecx
         movl    $anZero, %edx
         movl    $4000, %eax
         subl    $4, %esp
         pushl   %eax
         pushl   %edx
         pushl   %ecx
         call    memcpy
         addl    $16, %esp
         movl    $0, %eax
         leave
         ret
         .size   main, .-main
         .local  anZero
         .comm   anZero,4000,32
         ...
=========


 questo (almeno con il gcc).
Esattamente. Anche nel sistema che uso accade qualcosa di analogo.
