Hi,

It is my very first post, im doing it because i know some C basics and now im stuck with more advanced problems, more catchy questions.

Lets say iv allocated a memory block by function called calloc.

i have 1 bit field

struct datatype
 {
       unsigned short int a: 4;
       unsigned short int b: 4;
       unsigned short int c: 5; // 5 mitte 4 ,sest n2itek 9+9 on rohkem kui 16.
       }minu;

And pointer to a bit field.

struct datatype *datatype_ptr ;

Question how to use a memmove on bit field.
(does not work at all)

//memmove((datatype_ptr ) -> b ,(datatype_ptr ) -> c, (sizeof(struct datatype)) * j2rkude_arv );

In this case (code below for whole example), is memmove function more efficient than for loop like:

for(loendur = 0; loendur != j2rkude_arv+2; loendur++) {  
     ((datatype_ptr +loendur) -> a) = ((datatype_ptr +loendur) -> b) ;
     }

Iv written Fibonacci sequence code to demo my skills to myself, school and now to you. Not much but still i hope it is worth looking at.
If you see something that i did not as good as you , let me know. Your feedback and opinions will help me alot.

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


#define max_j2rgud 200000
#define arvutamise_korrad 100000
   
int  skaala_yhikute_vahe  =  arvutamise_korrad/50; 

// Globaalsed muutujad
//-----------------------------------------------------------------------------
struct datatype {
       unsigned short int a: 4;
       unsigned short int b: 4;
       unsigned short int c: 5; // 5 mitte 4 ,sest n2itek 9+9 on rohkem kui 16.
       }minu;

struct datatype *datatype_ptr ;
int j2rkude_arv = 0;
unsigned int arvutuse_nr = 0;




//-----------------------------------------------------------------------------



void liitmine()
{
short unsigned int x = 1; 
short unsigned int j22k;  //(datatype_ptr -> d) ?  1 bit on bitfield

(datatype_ptr -> c) =  (datatype_ptr -> a) + (datatype_ptr -> b);
 
     if ((datatype_ptr -> c) > 9)  {
         j22k = 1;
         (datatype_ptr -> c) %= 10; 
             if ( x >= j2rkude_arv ) {
             j2rkude_arv++;
             }  
         }     
     else {
         j22k = 0;     
     }
     
     for(;x <= j2rkude_arv;x++){
           
         ((datatype_ptr +x) -> c) =  ((datatype_ptr +x) -> a) + ((datatype_ptr +x) -> b) + j22k;
         
             if (((datatype_ptr +x) -> c) > 9)  {
                 j22k = 1;
                 ((datatype_ptr +x) -> c) %= 10;
                      if ( x >= j2rkude_arv ) {
                      j2rkude_arv++;
                      }
             }         
             else{
                 j22k = 0;     
                 }
         } 

}



void fib_liigutus() 
{
int loendur;
     
     for(loendur = 0; loendur != j2rkude_arv+2; loendur++) {  
     ((datatype_ptr +loendur) -> a) = ((datatype_ptr +loendur) -> b) ;
     }
     for(loendur = 0; loendur != j2rkude_arv+2; loendur++) {  
     ((datatype_ptr +loendur) -> b) = ((datatype_ptr +loendur) -> c) ;
     }
//memmove((datatype_ptr ) -> a ,(datatype_ptr ) -> b, (sizeof(struct datatype)) * j2rkude_arv );
//memmove((datatype_ptr ) -> b ,(datatype_ptr ) -> c, (sizeof(struct datatype)) * j2rkude_arv );
}

void vastuse_print()
{
     int y, lugeja;

     for(lugeja = 0; lugeja <=  j2rkude_arv; lugeja++) {
     y = j2rkude_arv - lugeja;
     printf("%u",((datatype_ptr + y  ) -> c));
     }
     printf("\n");     
}

void progressi_baari_skaala() 
{
     printf("\n");  
     printf("|0----------25---------50----------75---------100%c|  \n",'%');  // 50 yhitkut
     
     }

int progressi_baar() 
{
    if((arvutuse_nr % skaala_yhikute_vahe) == 0) {
         printf("|");
         } 
}

void fail_proov()  // example from wiki
{
     
FILE *fp;
    size_t count,a;
    const char *str = "hello\n";
 
    fp = fopen("sample.txt", "w");
    if(fp == NULL) {
        perror("failed to open sample.txt");
    }
    //count = fwrite(str, 1, strlen(str), fp);  datatype_ptr
    //count = fwrite(datatype_ptr, , j2rkude_arv, fp);
    
    for(a = 0; a <= j2rkude_arv; a++) {
    fprintf(fp,"%u",((datatype_ptr + a  ) -> c));
    }
    
    printf("Kirjutas %u baiti. fclose(fp) %s.\n", a, fclose(fp) == 0 ? "6nnestus" : "ei_6nnestunud");

}


int main(int argc, char *argv)
{
unsigned int a = 0;
clock_t start, finish;
start = clock();



datatype_ptr = (struct datatype *)calloc(max_j2rgud, sizeof(struct datatype));

    if (datatype_ptr == NULL) {
    printf("M2lu eraldus eba6nnestus a\n"); 
    }


(datatype_ptr) -> b = 1;

progressi_baari_skaala();
progressi_baar();

    for(arvutuse_nr = 1; arvutuse_nr <= arvutamise_korrad; arvutuse_nr++)  {
        liitmine();
        //printf("%u - ",arvutuse_nr+1);
        //vastuse_print();
        fib_liigutus() ;
        progressi_baar();
    }
 
 
finish = clock(); 


printf("\n"); 
printf("%u. Fib. nr. on %u arvj2rku pikk.\n",arvutuse_nr,j2rkude_arv+1); 
printf("Arvutusteks aega kulus %f sekundit\n", ((double)finish - start) / CLOCKS_PER_SEC);        
  
fail_proov();
  
  
free(datatype_ptr);
system("PAUSE");

return 0;
}

Sorry for long code that is not in correct language.
The code calculates about 100k fib numbers in 30 sec, you can see a 100% type progress bar in consonle. Output is last fib number in txt file.


Thank you in advance !

Edited 5 Years Ago by m1n1m3: aah ...cant fix topic name, im very sorry.

I didn't read your post in its entirety but I can inform you about this...On Intel/AMD machines the smallest addressable memory is a byte. If you have to work with bits they are not directly addressable so you have to use masking operations to access them...e.g. You can't point a memory pointer at bits only bytes.

Edited 5 Years Ago by gerard4143: n/a

Hi,

i have 1 bit field

No, you have 3 bit fields, packed into a word.

And pointer to a bit field.

Bit fields don't have address, so you cannot have a pointer to them.

Question how to use a memmove on bit field.
(does not work at all)

//memmove((datatype_ptr ) -> b ,(datatype_ptr ) -> c, (sizeof(struct datatype)) * j2rkude_arv );

memmove requires addresses, those arguments you pass are not address, 4-bit long bit field is not an address.

Don't use bit fields. They're implementation dependent, not portable. They are only good for os specific and platform specific software, like device drivers.

>Don't use bit fields. They're implementation dependent, not portable.
Bit fields are quite portable, provided you don't make unwarranted assumptions about the storage layout.

Edited 5 Years Ago by Narue: n/a

>Don't use bit fields. They're implementation dependent, not portable.
Bit fields are quite portable, provided you don't make unwarranted assumptions about the storage layout.

gerard4143, ckoy, Narue thank you for replies.


"Bit fields don't have address, so you cannot have a pointer to them."

There is a great possibility that im wrong but im still stand my opinion. How is possible something like:

(datatype_ptr -> c) =  (datatype_ptr -> a) + (datatype_ptr -> b)

Afterall, *datatype_ptr is struct pointer that points to bit field element c?


Where or how i can use bit fields in a way that i can make my programming better (speed, memory usage)? For example embedded application like 8bit MCU. What can i do with bit field?

One more question... How i can measure code performance, like execution speed. Atm. im using Dev C++ copiler, i feel like it is important to add at this point.
Does stucture- or bit field datatype usage increase execution and calculation speed?


Thank you in advance!

Edited 5 Years Ago by m1n1m3: n/a

First, datatype_ptr is a pointer to a block of memory that contains the structure elements. When you use datatype_ptr->b the compiler may(I say may because it really depends on how the memory's allotted for your structure) use masking operations to access the value stored at datatype_ptr->b..

"Does stucture- or bit field datatype usage increase execution and calculation speed?"

Generally no, the added masking operations will create more code.

"Bit fields don't have address, so you cannot have a pointer to them."

There is a great possibility that im wrong but im still stand my opinion. How is possible something like:

(datatype_ptr -> c) =  (datatype_ptr -> a) + (datatype_ptr -> b)

Compiler magic. Consider the following example program using bit fields:

#include <stdio.h>

int main(void)
{
    struct datatype {
        unsigned a: 2;
        unsigned b: 2;
        unsigned c: 4;
    } var = {0};
 
    var.a = 2;
    var.b = 3;
    var.c = var.a + var.b;

    printf("%d + %d = %d\n", var.a, var.b, var.c);

    return 0;
}

The generated code might look more like this:

#include <stdio.h>

int main(void)
{
    struct datatype {
        unsigned _base;
    } var = {0};

    var._base |= 2U;
    var._base |= 3U << 2;
    var._base |= ((var._base & 0x3) + (var._base >> 2 & 0x3)) << 4;

    printf("%d + %d = %d\n", 
        var._base & 0x3, 
        var._base >> 2 & 0x3, 
        var._base >> 4 & 0xF);

    return 0;
}

Bit fields are something of a sugar coating for syntactic convenience. Under the hood you still have tried and true bit twiddling going on.

Where or how i can use bit fields in a way that i can make my programming better (speed, memory usage)? For example embedded application like 8bit MCU. What can i do with bit field?

Personally, I only use them for flags. :) Pretty much all other times I'm working at the bit level, I pack and unpack the bits manually for more control and portability.

One more question... How i can measure code performance, like execution speed.

Look for a good profiler. It will trace your execution and give you statistics from start to finish.

Does stucture usage or bit field increase execution or calculation speed?

As usual, the answer is "it depends". Bit fields generally won't be slower than manual bit twiddling though, unless you run an exceptionally stupid compiler.

This article has been dead for over six months. Start a new discussion instead.