Gå til innhold

C: Lengden av en double buffer.


Anbefalte innlegg

Gitt følgende kode

 

#include <stdio.h>
#include <malloc.h>

int main(int argc, char **argv) {
   int x;
   double *buf = (double*)malloc(sizeof(double)*5*5);
   
   for(x=0; x<15; x++)
       buf[x] = x + 0.25;
}

 

Hvordan finner jeg ut hvor mange double(25) det er plass til i buf?.

Hvordan kan jeg finne ut hvor mange elementer(15) det er i buf?

 

Ørjan...

Endret av Orjanp
Lenke til kommentar
Videoannonse
Annonse
Gitt følgende kode

 

#include <stdio.h>
#include <malloc.h>

int main(int argc, char **argv) {
   int x;
   double *buf = (double*)malloc(sizeof(double)*5*5);
   
   for(x=0; x<15; x++)
       buf[x] = x + 0.25;
}

 

Hvordan finner jeg ut hvor mange double(25) det er plass til i buf?.

Hvordan kan jeg finne ut hvor mange elementer(15) det er i buf?

 

Ørjan...

7096024[/snapback]

 

sizeof(double) * 25 forteller kun `malloc' om _størrelser_; ikke _antallet_ av noe. Antall må du holde styr på selv på et eller annet vis.

 

Når du vet at `malloc'-kallet gikk bra - altså at det ikke returnerte NULL kan du regne ut hvor mange elementer av en viss type (altså størrelse) du får plass til i minnet du har allokert fordi du vet den totale størrelsen og størrelsen til hvert enkelt element du ønsker å lagre. F.eks:

 

#include <stdio.h>

int main()
{
 printf("sizeof(int): %d\n", sizeof(int));
 printf("sizeof(double): %d\n", sizeof(double));
 return 0;
}

/*
lars@ibmr52:~/programming/c$ gcc -g -Wall a.c -o a && ./a
sizeof(int): 4
sizeof(double): 8
*/

 

..dette betyr at "for hver double" jeg allokerer har plass til to int'er, så på min maskin er dette sikkert:

 

#include <stdio.h>
#include <stdlib.h>
#include <assert.h>

int main()
{
 assert((sizeof(double) / 2) == sizeof(int));
 
 int* i = malloc(sizeof(double) * 1);
 i[0] = 1234;
 i[1] = 4321;

 printf("i[0]: %d\n", i[0]);
 printf("i[1]: %d\n", i[1]);

 free(i);  

 return 0;
}

/*
lars@ibmr52:~/programming/c$ gcc -g -Wall a.c -o a && ./a
i[0]: 1234
i[1]: 4321
*/

 

..uhm.. vel, heh .. uansett -- poenget er at malloc har ikke noe forhold til antall i det hele tatt; kun størrelse minne den skal forsøke å allokere.

 

Måten man løser disse tingene på er ved ting som:

 

typedef struct {
 void* data;
 size_t num_elements;
} Stuff;

 

..og/eller..

 

void someFunction(void* data, size_t num_elements);

 

..altså man må holde styr på _antall_ separat. :}

Endret av lnostdal
Lenke til kommentar
En annen ting. Er det mulig å sende inn deler av et array til en funksjon? En eller annen subarray sak? f.eks. element 0 - 5.

7099160[/snapback]

 

nei, et array er ikke noe annet en ett "flytende" allokert minnesegment - det inneholder hverken informasjon om:

 

* antall elementer

* start-index (0)

* slutt-index (5)

 

du må bygge et "språk" over disse tingene (pekere og arrays) ved å abstrahere v.h.a. structs og funksjoner .. dette har gått fryktelig fort og det kan hende jeg må redigere denne posten litt ettersom det kan være endel bugs her, men her har du en ting som "reflekterer" array eller minnesegmenter og pakker dem inn i strukturer og funksjoner (blir nesten OOP) som gjør at man har litt mer meta-data å jobbe med når man skal gjøre ting:

 

edit: koden i dette forumet blir selvfølgelig seendes helt jævlig ut, så her: http://paste.lisp.org/display/28235

 

#include <stdio.h>
#include <stdlib.h>
#include <string.h>


typedef char bool;


typedef struct {
 /* We build an abstraction over plain arrays/memory-allocations that contain
    more information. */
 size_t num_elements;
 size_t element_size;
 bool reflection;
 void* data;
} Vector;


Vector* reflectArray(void* array, size_t num_elements, size_t element_size){
 // Constructor.
 Vector* vector = malloc(sizeof(Vector));
 vector->data = array;
 vector->num_elements = num_elements;
 vector->element_size = element_size;
 vector->reflection = 1;
 return vector;}


void deleteVector(Vector* vector) {
// Destructor.
 if(!vector->reflection)
   free(vector->data);
 free(vector);}


void* getVectorElt(Vector* vector, size_t index){
 return(vector->data + (vector->element_size * index));}


typedef void (*VectorCallback)(void*);


void iterateVector(Vector* vector, VectorCallback vector_callback){
 {size_t i = 0;
   for(; i != vector->num_elements; i++) 
     vector_callback(getVectorElt(vector, i));}}


typedef struct {
 size_t start_index;
 size_t end_index;
 Vector* vector;
} VectorSegment;


VectorSegment* newVectorSegment(Vector* vector, size_t start_index, size_t end_index){
 // Constructor.
 VectorSegment* vector_segment = malloc(sizeof(VectorSegment));
 vector_segment->vector = vector;
 vector_segment->start_index = start_index;
 vector_segment->end_index = end_index;
 return(vector_segment);}


void deleteVectorSegment(VectorSegment* vector_segment){
 // Destructor.
 free(vector_segment);}


void iterateVectorSegment(VectorSegment* vector_segment, VectorCallback vector_callback){
 // Set up fake environment so we can reuse code in `iterateVector'.
 {Vector* tmp =
     reflectArray(getVectorElt(vector_segment->vector, vector_segment->start_index),
                  vector_segment->end_index - vector_segment->start_index,
                  vector_segment->vector->element_size);
   iterateVector(tmp, vector_callback);
   deleteVector(tmp);}}



//// USER CODE ////

void printVectorOfDoubles(double* vector_element){
 printf("vector_element: %f\n", *vector_element);}



int main(){
 double double_array[6] = { 0.0, 1.0, 2.0, 3.0, 4.0, 5.0 };

 Vector* vector = reflectArray(double_array, 6, sizeof(double));
 printf("iterateVector:\n");
 iterateVector(vector, (VectorCallback)&printVectorOfDoubles);

 printf("\n\niterateVectorSegment:\n");
 VectorSegment* vector_segment = newVectorSegment(vector, 2, 4);
 iterateVectorSegment(vector_segment, (VectorCallback)&printVectorOfDoubles);

 deleteVectorSegment(vector_segment);
 deleteVector(vector);
 return 0;}

 

lars@ibmr52:~/programming/c$ gcc -Wall -g a.c -o a && ./a
iterateVector:
vector_element: 0.000000
vector_element: 1.000000
vector_element: 2.000000
vector_element: 3.000000
vector_element: 4.000000
vector_element: 5.000000


iterateVectorSegment:
vector_element: 2.000000
vector_element: 3.000000

Endret av lnostdal
Lenke til kommentar

en mulig optimalisering (eller kanskje det går tregere?):

 

void iterateVectorSegment(VectorSegment* vector_segment, VectorCallback vector_callback){
 // NOTE: Temporary leaves `vector_segment->vector' in a non-sane state.
 // Set up fake environment so we can reuse code in `iterateVector'.
 Vector* vector = vector_segment->vector;
 void* old_data = vector->data;
 vector->data = getVectorElt(vector, vector_segment->start_index);
 size_t old_num_elements = vector->num_elements;
 vector->num_elements = vector_segment->end_index - vector_segment->start_index;
 iterateVector(vector, vector_callback);

 // Restore original environment.
 vector->data = old_data;
 vector->num_elements = old_num_elements;}

 

edit:

det er også mer vanlig at testen i for-loopen i `iterateVector' ser slik ut:

 

i < vector->num_elements

Endret av lnostdal
Lenke til kommentar
Takk. Det var i grunn det jeg trodde fordi jeg ikke har klart å finne noe via google.

 

En annen ting. Er det mulig å sende inn deler av et array til en funksjon? En eller annen subarray sak? f.eks. element 0 - 5.

 

Ørjan...

7099160[/snapback]

Ja, du kan sende inn deler ut å bale så mye som lnostdal:

 

#include <windows.h>
#include <climits>
#include <iostream>

using namespace std;

void tax(double arr[], int len) {
   int i;
   for (i=0; i<len; i++) {
       arr[i] *= 1.22;
   }
}

void cout_array(const double arr[], int len) {
   int i;
   for (i=0; i<len; i++) {
       cout << arr[i] << endl;
   }
}


int main(int argc, char *argv[]) {
   int x;
   double arr[10] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
   
   cout_array(arr, 10);
   
   tax(arr, 5); // tax element 0 - 5
   
   cout << "-----\n";
   cout_array(arr, 10);
   
   tax(&arr[5], 5); // tax element 5 - 10
   
   cout << "-----\n";
   cout_array(arr, 10);

   system("PAUSE");
   return 0;
}

Lenke til kommentar
Takk. Det var i grunn det jeg trodde fordi jeg ikke har klart å finne noe via google.

 

En annen ting. Er det mulig å sende inn deler av et array til en funksjon? En eller annen subarray sak? f.eks. element 0 - 5.

 

Ørjan...

7099160[/snapback]

Ja, du kan sende inn deler ut å bale så mye som lnostdal:

 

Forstår du forskjellene mellom det du gjør og det jeg gjør - og fordeler/bakdeler ved hver av dem?

 

Forresten - om man først skal bruke C++ så bruker man templates for å generere kode for utskrift og behandling av forskjellige typer.

 

* Du skriver ikke ut arrayer og minnesegmenter av ukjente typer (eller tar ikke hensyn til "utvidbarhet").

* Du resirkulerer ikke koden for iterasjon over ukjente typer.

* m.m.

Endret av lnostdal
Lenke til kommentar

Da åpnes denne igjen.

 

Heretter kan dere nøye dere med å kommentere feil og ulemper med den faktiske koden/implementasjonen som foreslås. Hva trådstarter er ute etter er det bare han som kan og skal kommentere. I dette tilfellet var han godt fornøyd med svarene, og da er alt greit.

 

En rekke poster om bakerier og brødsmuler er slettet. Det er synd, da noen av dem også inneholdt verdifull on-topic informasjon.

 

Jeg minner om retningslinjene: Om noen troller eller går off topic, så ikke kommenter det i tråden. Send oss en rapport, så ordner vi opp, og så slipper trådstarter at tråden hans blir en off topic krangel, og dere slipper reaksjoner fra moderator:

 

Jeg har oppdaget brudd på retningslinjene. Hva gjør jeg?

 

Det du i alle fall ikke skal gjøre er å svare i den tråden der hvor regelbruddet er. Dette vil kun gi tråden unødvendig oppmerksomhet. Og du vil selv bli regelbryter dersom du poster informasjon i tråden som ikke er i samsvar med hva den egentlig handler om. Hvis du ser et regelbrudd skal du først og fremst bruke funksjonen "Rapporter" i forumet. Til høyre over hvert innlegg er det en knapp hvor det står "Report" og hvis du trykker på denne føres du til et skjema du kan fylle ut. Rapporten din vil så bli lagt til i listen over rapporter og en moderator vil så behandle regelbruddet neste gang han går over listen og behandler rapporter. Hvis det er et krisetilfelle som krever øyeblikkelig oppmerksomhet kan du også ta kontakt med moderatorer mer direkte ved å enten sende en E-post, en melding eller se etter annen kontaktinfo i profilen til en moderator. Husk at selv de som bryter retningslinjene er beskyttet av retningslinjene igjen og ved utskjelling av disse risikerer at du selv kan bli advart eller i verste tilfelle utestengt.

 

Geir :)

Endret av tom waits for alice
Lenke til kommentar

Opprett en konto eller logg inn for å kommentere

Du må være et medlem for å kunne skrive en kommentar

Opprett konto

Det er enkelt å melde seg inn for å starte en ny konto!

Start en konto

Logg inn

Har du allerede en konto? Logg inn her.

Logg inn nå
  • Hvem er aktive   0 medlemmer

    • Ingen innloggede medlemmer aktive
×
×
  • Opprett ny...