Er det en beste praksis for å vikle arrays og deres lengde variabel i en struct i C?

stemmer
5

Jeg vil begynne å bruke C i Operativsystemet kurs snart, og jeg leser opp på beste praksis for bruk av C slik at hodepine er redusert senere.

Dette har alltid vært en av mine første spørsmål angående matriser som de er enkle å skru opp.

Er det en vanlig praksis ute å pakke en matrise og tilhørende variabel som inneholder den lengden i en struct?

Jeg har aldri sett det i bøker og som regel de holder alltid to separate eller bruke noe sånt sizeof (matrise [] / matrise [1]) slags avtale.

Men med innpakning de to til en struct, vil du være i stand til å passere struct både i verdi og ved henvisning som du ikke kan egentlig gjøre med matriser med mindre bruker pekere, i så fall må igjen holde styr på rekken lengde .

Jeg begynner å bruke C slik at ovennevnte kan være fryktelig galt, er jeg fortsatt student.

Skål, Kai.

Publisert på 19/03/2009 klokken 13:10
kilden bruker
På andre språk...                            


11 svar

stemmer
5

Ja dette er en god praksis å ha i C. Det er helt logisk å vikle relaterte verdier i en inneholdende struktur.

Jeg vil gå stadig lenger. Det vil også tjene formålet å aldri endre disse verdiene direkte. I stedet skrive funksjoner som virker på disse verdiene som et par inni struct å endre lengde og endre data. På den måten kan du legge til invariante sjekker og også gjøre det svært enkelt å teste.

Svarte 19/03/2009 kl. 13:15
kilden bruker

stemmer
3

Det er tre måter.

  1. For statisk matrise (ikke tildeles dynamisk og ikke bestått som peker) størrelse er vet under kompileringen slik at man kan brukes sizeofoperatør, slik som dette:sizeof(array)/sizeof(array[0])
  2. Bruk terminator (spesiell verdi for siste gruppeelement som ikke kan benyttes som vanlig matrise-verdi), som avsluttende null strenger
  3. Bruk ulik verdi, enten som et struct medlem eller uavhengig variabel. Det spiller egentlig ingen rolle, fordi alle de vanlige funksjonene som arbeider med matriser ta egen størrelse variabel, men bli med i matrisen pekeren og størrelse i en struct vil øke kode lesbarhet. Jeg foreslår å bruke til å ha en renere grensesnitt for dine egne funksjoner. Vær oppmerksom på at hvis du passerer struct av verdi, vil kalt funksjon kunne endre array, men ikke størrelsen variabel, så passerer struct pekeren ville være et bedre alternativ.
Svarte 19/03/2009 kl. 13:21
kilden bruker

stemmer
3

Jada, kan du gjøre det. Ikke sikker på om jeg vil kalle det en beste praksis, men det er absolutt en god idé å gjøre Cs heller rudimentære arrays litt mer håndterlig. Hvis du trenger dynamiske matriser, er det nesten et krav for å gruppere de ulike feltene som trengs for å gjøre bokføring sammen.

Noen ganger har du to størrelser i så fall: en nåværende og en tildelt. Dette er en avveining hvor du handle færre tildelinger for litt fart, betale litt minne overhead med.

Mange ganger matriser brukes kun lokalt, og er av statisk størrelse, som er grunnen til at sizeofoperatøren er så praktisk å bestemme antall elementer. Syntaksen er litt av med det, forresten, her er hvordan det vanligvis ser ut:

int array[4711];
int i;

for(i = 0; i < sizeof array / sizeof *array; i++)
{
  /* Do stuff with each element. */
}

Husk at sizeofer ikke en funksjon, blir parentesen ikke alltid nødvendig.

EDIT : En real-world eksempel på en innpakning akkurat det som du beskriver er det Garray typen levert av glib . Det bruker synlige delen av erklæringen er akkurat det du beskriver:

typedef struct {
  gchar *data;
  guint len;
} GArray;

Programmene forventes å bruke den medfølgende API for å få tilgang til matrisen når det er mulig, ikke rote disse feltene direkte.

Svarte 19/03/2009 kl. 13:14
kilden bruker

stemmer
2

Jeg vil si det er en god praksis. Faktisk er det godt nok til at i C ++ de har satt den inn i standard biblioteket og kalte det vector. Når du snakker om arrays i en C ++ forum, vil du bli oversvømt med svar som sier å bruke vectori stedet.

Svarte 19/03/2009 kl. 14:05
kilden bruker

stemmer
2

For offentlig API jeg vil gå med array og størrelsen verdien separert. Det er hvordan det blir håndtert i de fleste (om ikke alle) c bibliotek jeg vet. Hvordan håndtere det internt det er helt opp til deg. Så bruker en struktur pluss noen hjelpefunksjoner / makroer som gjør de vanskelige delene for deg er en god idé. Det er alltid noe som gjør meg head-verke å revurdere hvordan du setter inn et element eller fjerne en, så det er en god kilde til problemer. Løse som en gang og generisk, hjelper deg å få bugs fra begynnelsen lav. En fin gjennomføring for dynamiske og generiske arrays er kvec .

Svarte 19/03/2009 kl. 13:41
kilden bruker

stemmer
1

Hvis du bruker statiske arrays du har tilgang til størrelsen på array ved hjelp sizeof operatør. Hvis du vil sette det inn i struct, kan du sende det til å fungere i verdi, referanse og peker. Passerer argument ved referanse, og av pekeren er den samme på sammenstillingen nivå (Jeg er nesten sikker på det).

Men hvis du bruker dynamiske matriser, trenger du ikke vet størrelsen på matrisen ved kompilering. Så du kan lagre denne verdien i struct, men du vil også lagre bare en peker til array i struktur:

struct Foo {
  int *myarray;
  int size;
};

Så du kan passere denne strukturen av verdi, men hva du virkelig gjøre er å føre pekeren til int (pekeren til array) og int (størrelsen på array).

Etter min mening vil det ikke hjelpe deg mye. Det eneste som er i pluss, er at du oppbevarer størrelse og rekken på ett sted, og det er lett å få størrelsen på array. Hvis du vil bruke mye av dynamiske matriser kan du gjøre det på denne måten. Men hvis du vil bruke noen matriser, vil lettere være å ikke bruke strukturer.

Svarte 19/03/2009 kl. 13:40
kilden bruker

stemmer
1

Jeg har ikke sett det gjort i bøkene mye heller, men jeg har gjort det samme det samme for en stund nå. Det virker bare å være fornuftig å "pakke" disse tingene sammen. Jeg finner det spesielt nyttig hvis man trenger å returnere en tildelt rekken fra en metode for eksempel.

Svarte 19/03/2009 kl. 13:17
kilden bruker

stemmer
1

Jeg ser ikke noe galt med å gjøre det, men jeg tror grunnen til at det ikke gjøres vanligvis er på grunn av overhead pådratt av en slik struktur. De fleste C er bart metall-kode for ytelseshensyn og som sådan, er abstractions ofte unngås.

Svarte 19/03/2009 kl. 13:14
kilden bruker

stemmer
0

Jeg tror denne delen av spørsmålet ditt er bakover:

"Men med innpakning de to til en struct, vil du være i stand til å passere struct både i verdi og ved henvisning som du ikke kan egentlig gjøre med matriser med mindre bruker pekere, i så fall må igjen holde styr på matrisen lengde."

Ved hjelp av pekere når du passerer arrays rundt er standard virkemåte; som ikke kjøpe deg noe i form av bestått hel rekke av verdi. Hvis du ønsker å kopiere hele matrise i stedet for å ha det forfallet til en peker du trenger å pakke array i en struct. Se dette svaret for mer informasjon:

Pass utvalg av verdi til rekursiv funksjon mulig?

Og her er mer på den spesielle oppførselen til matriser:

http://denniskubes.com/2012/08/20/is-c-pass-by-value-or-reference/

Svarte 14/12/2014 kl. 17:51
kilden bruker

stemmer
0

vurderer du kan beregne lengden på array (i byte, det vil si, ikke # elementer) og kompilatoren vil erstatte sizeof () kaller med den faktiske verdien (det er ikke en funksjon, samtaler til det blir erstattet av kompilatoren med verdien det avkastning '), så den eneste grunnen til at du ønsker å pakke det inn i en struct er for lesbarhet.

Det er ikke en vanlig praksis, hvis du gjorde det, noen ser på koden din vil anta lengden feltet var noen spesiell verdi, og ikke bare array størrelse. Det er en fare som lurer i forslaget, så du må være forsiktig med å kommentere den riktig.

Svarte 19/03/2009 kl. 13:19
kilden bruker

stemmer
0

Jeg har aldri sett det gjort på den måten, men jeg har ikke gjort OS nivå arbeid i over et tiår ... :-) Virker som en fornuftig tilnærming ved første øyekast. Eneste bekymring vil være å sørge for at størrelsen liksom forblir nøyaktig ... Beregning behov har ikke denne bekymringen.

Svarte 19/03/2009 kl. 13:16
kilden bruker

Cookies help us deliver our services. By using our services, you agree to our use of cookies. Learn more