|
| minus én plus ti Fra : Troels Thomsen |
Dato : 15-03-04 16:23 |
|
Er flg en almindelig konstruktion ?
typedef struct
{
char a;
char data[1];
} S1;
typedef struct
{
char b;
S1 s1obj;
} S2;
void f1(unsigned char dataLength )
{
char i;
S2* ps2 = malloc((sizeof(S2)-1) + dataLength);
for (i = 0 ; i < dataLength ; ++i)
{
ps2->s1obj.data[i] = i; // fill in some data
}
anotherFunc (ps2); // somebody uses this struct and data
}
Jeg synes det er lidt fusket at allokere ét element og så malloce et større
område så det kommer til at passe.
Det er vel _garanteret_ at S1::data ligger til allersidst i S2 structet, så
det _altid_ går godt, eller?
Alternativet var jo bare at 'data' var char pointer. Så laver man structet,
allokerer en char buffer med malloc, assigner pointeren til S1::data.
Det er noget kode der skal køre i en microcontroller. Måske bliver der et
par instruktioner mindre ud af denne måde at gøre det på? Jeg prøver sådan
set bare at forstå hvorfor de har gjort som de har !
mvh Troels
| |
Bertel Brander (15-03-2004)
| Kommentar Fra : Bertel Brander |
Dato : 15-03-04 19:14 |
|
Troels Thomsen wrote:
> Det er vel _garanteret_ at S1::data ligger til allersidst i S2 structet, så
> det _altid_ går godt, eller?
For C (jeg kender ikke nok til C++ til at vide om det er lovligt der):
http://www.eskimo.com/~scs/C-faq/q2.6.html
>
> Alternativet var jo bare at 'data' var char pointer. Så laver man structet,
> allokerer en char buffer med malloc, assigner pointeren til S1::data.
I så fald skal man allokere to gange, en gang for struct'en og
en gang for pointeren.
/b
| |
Bertel Brander (15-03-2004)
| Kommentar Fra : Bertel Brander |
Dato : 15-03-04 19:38 |
|
Bertel Brander wrote:
> Troels Thomsen wrote:
>
>> Det er vel _garanteret_ at S1::data ligger til allersidst i S2
>> structet, så
>> det _altid_ går godt, eller?
>
>
> For C (jeg kender ikke nok til C++ til at vide om det er lovligt der):
> http://www.eskimo.com/~scs/C-faq/q2.6.html
>
Ved nærmere eftertanke;
I C99 (og nogle pre-C99 kompilere) kan man bruge:
struct s
{
int n;
double d[];
};
Så behøver man ikke at trække én fra. I C99 er
det garanteret at hacket virker.
Bemærk også at minus en ikke altid giver den rigtige
størrelse (pga. padding), man kan bruge offsetof()
til at finde den nøjagtige størrelse, hvis det er
vigtigt.
/b
| |
Troels Thomsen (17-03-2004)
| Kommentar Fra : Troels Thomsen |
Dato : 17-03-04 09:33 |
|
>
> struct s
> {
> int n;
> double d[];
> };
>
C99, Ok, det vil lige denne Metrowerks HCS08 compiler så ikke.
Begge de to IAR compilere (den ene fra 1998) vil godt.
> Bemærk også at minus en ikke altid giver den rigtige
> størrelse (pga. padding), man kan bruge offsetof()
> til at finde den nøjagtige størrelse, hvis det er
> vigtigt.
>
Mener du (sizeof(s1) - offsetof(data))?
Men som du skriver er det ofte lige meget, at man får et par bytes for meget
allokeret.
mvh tpt
| |
Bertel Brander (17-03-2004)
| Kommentar Fra : Bertel Brander |
Dato : 17-03-04 17:32 |
|
Troels Thomsen wrote:
>>Bemærk også at minus en ikke altid giver den rigtige
>>størrelse (pga. padding), man kan bruge offsetof()
>>til at finde den nøjagtige størrelse, hvis det er
>>vigtigt.
>>
>
>
> Mener du (sizeof(s1) - offsetof(data))?
Jeg mener offsetof(struct s, a), f.ex:
#include <stdio.h>
struct s
{
int i;
char a[1];
};
int main(void)
{
printf("Sizeof: %d Offsetof: %d\n", sizeof(Struct) - 1,
offsetof(Struct, a));
return 0;
}
Med en tilfældig kompiler får jeg hhv 7 og 4, hvilket måske
ikke er atypisk.
/b
| |
Frederik Hertzum (22-03-2004)
| Kommentar Fra : Frederik Hertzum |
Dato : 22-03-04 20:10 |
|
Bertel Brander wrote:
> Bertel Brander wrote:
>
>> Troels Thomsen wrote:
>>
>>> Det er vel _garanteret_ at S1::data ligger til allersidst i S2
>>> structet, så
>>> det _altid_ går godt, eller?
>>
>>
>> For C (jeg kender ikke nok til C++ til at vide om det er lovligt der):
>> http://www.eskimo.com/~scs/C-faq/q2.6.html
>>
>
> Ved nærmere eftertanke;
>
> I C99 (og nogle pre-C99 kompilere) kan man bruge:
>
> struct s
> {
> int n;
> double d[];
> };
>
> Så behøver man ikke at trække én fra. I C99 er
> det garanteret at hacket virker.
>
Et alternativ ville være
struct s
{
int n;
double * d;
}
void function(int size) // find size på en eller anden måde
{
s * a;
a = malloc(size);
a->d = function_to_find_d(a);
}
Jeg kender ikke C godt nok til at skrive resten af programmet, men det her
skulle gøre det samme og samtidig sikre at det kan compile på GCC compilere
(i hvert fald).
| |
Niels Dybdahl (15-03-2004)
| Kommentar Fra : Niels Dybdahl |
Dato : 15-03-04 22:11 |
|
> Det er noget kode der skal køre i en microcontroller. Måske bliver der et
> par instruktioner mindre ud af denne måde at gøre det på? Jeg prøver sådan
> set bare at forstå hvorfor de har gjort som de har !
I en microcontroller kan der være hardware der forventer at det ligger ud i
en køre. I så fald er det en ret almindelig skrivemåde. Der er vist også
nogen strukturer i Windows API (BITMAPHEADER) som er defineret på lignende
måde. Der er pointen ssv at holde samme struktur i RAM som i en fil.
Niels Dybdahl
| |
|
|