Thread: printing array's content with offset different behavior

  1. #1
    Registered User
    Join Date
    Jan 2016
    Posts
    84

    printing array's content with offset different behavior

    Hello,

    I want to print array's content with offset so I save the bytes in specific locations in the array.

    The process works fine for different offset but it isn't with certain ones.

    For example, I have any array of 64-bytes.

    I want to save data after the first 8-bytes, so I adjust the array's index:
    Code:
    display_buffer[i+8]=Alphabet[i];
    It also works OK with 16 and 24 offsets, but not with 32! Why is that.

    Here is my code:
    Code:
    uint8_t Alphabet[208]={
    0x42, 0x42, 0x42, 0x7e, 0x42, 0x42, 0x7e, 0x0, //A
    0x3e, 0x42, 0x42, 0x7e, 0x42, 0x42, 0x3e, 0x0, //B
    0x3c, 0x42, 0x2, 0x2, 0x2, 0x42, 0x3c, 0x0    ,//C
    0x3e, 0x42, 0x42, 0x42, 0x42, 0x42, 0x3e, 0x0, //D
    0x7e, 0x2, 0x2, 0x7e, 0x2, 0x2, 0x7e, 0x0     ,//E
    0x2, 0x2, 0x2, 0x3e, 0x2, 0x2, 0x7e, 0x0,      //F
    0x3c, 0x42, 0x62, 0x2, 0x2, 0x42, 0x3c, 0x0,   //G
    0x42, 0x42, 0x42, 0x7e, 0x42, 0x42, 0x42, 0x0, //H
    0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x0, //I
    0x18, 0x24, 0x20, 0x20, 0x20, 0x20, 0x70, 0x0, //J
    0x22, 0x12, 0xa, 0x6, 0xa, 0x12, 0x22, 0x0,    //K
    0x7e, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x0,       //L
    0x41, 0x41, 0x41, 0x49, 0x55, 0x63, 0x41, 0x0, //M
    0x41, 0x61, 0x51, 0x49, 0x45, 0x43, 0x41, 0x0, //N
    0x3c, 0x42, 0x42, 0x42, 0x42, 0x42, 0x3c, 0x0, //O
    0x2, 0x2, 0x2, 0x3e, 0x42, 0x42, 0x3e, 0x0,    //P
    0xbc, 0x62, 0x52, 0x42, 0x42, 0x42, 0x3c, 0x0,//Q
    0x62, 0x12, 0xa, 0x3e, 0x42, 0x42, 0x3c, 0x0,  //R
    0x1c, 0x22, 0x4, 0x8, 0x10, 0x22, 0x1c, 0x0,   //S
    0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x3e, 0x0,       //T
    0x3c, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x0, //U
    0x8, 0x14, 0x22, 0x41, 0x41, 0x41, 0x41, 0x0,  //V
    0x63, 0x55, 0x49, 0x41, 0x41, 0x41, 0x41, 0x0, //W
    0x41, 0x22, 0x14, 0x8, 0x14, 0x22, 0x41, 0x0,  //X
    0x8, 0x8, 0x8, 0x8, 0x14, 0x22, 0x41, 0x0,     //Y
    0x3e, 0x2, 0x4, 0x8, 0x10, 0x20, 0x3e, 0x0    //Z
     };
    
        int8_t i,k;
        uint8_t offset=no_of_device*8, buffer_size=offset*2;
        uint8_t display_buffer[buffer_size];
    
        for (i=0;i<buffer_size;i++)             // initialize array to zero
        display_buffer[i]=0;
    
    
        for (i=0;i<buffer_size;i++)             // copy data to display_buffer with offset
        display_buffer[i+40]=Alphabet[i];
    
    
        printf("before shifting action\n");     // printing array's content before shifting
        for (i=0;i<buffer_size;i++){
        printf("%.2x, ",display_buffer[i]);
        if(i%8==7) printf("\n");}
    
    
        printf("after shifting action\n");      // printing array's content after shifting
        for (i=0;i<buffer_size;i++){
        for (k=0;k<8;k++){
        display_buffer[i]>>=1;
        printf("%.2x, ",display_buffer[i]);}printf("\n");}
    So, because I'm initializing the array to zero, when applying offsets of any number to exactly 28, but after 28 the bytes before the offset are filled with certain data where they should be zeros.
    Last edited by wolfrose; 02-27-2018 at 05:26 PM. Reason: add information

  2. #2
    Registered User
    Join Date
    Dec 2017
    Posts
    1,628
    Your loop indices are int8_t and so are (most likely) limited to max +127. Incrementing from there will (most likely) wrap around to -128 and start counting up to 0 where it will repeat over and over if your limit is >= 128 (since the index will always be less than 128). I don't really understand what you're trying to do in the program so I'm not sure what else to say, but try making your loop indices int instead of int8_t.

    Looks like you might need a modulus on this line:
    Code:
    display_buffer[(i + 40) % buffer_size] = Alphabet[i];
    You don't say what no_of_device is or why buffer_size is no_of_device*16.
    Last edited by john.c; 02-27-2018 at 06:16 PM.
    A little inaccuracy saves tons of explanation. - H.H. Munro

  3. #3
    Registered User
    Join Date
    Jan 2016
    Posts
    84
    OK well thank you for reply.

    1. My indices are maximum the number of buffer_size which is in this case 64, I know it's not exceeding +127.
    2. What I'm trying to do is that I'm initializing the array before with zeros, so it should be all zeros before copying data to the array. Then when I want to copy data into the array in specific locations. So I'm not copying all the location, where the locations which don't receive any data remains 0s.
    3. So, I'm indexing with offset so I want to jump and leave specific bytes with 0s and copy data after; for example, after the first 8-bytes or after 16-bytes .. etc.
    4. no_of_device is number of LED matrix where each one need 8-bytes that's why I multiply it with 2 and the second multiplication is for extra blank space for shifting process.
    5. The modulus didn't work. The code is working upto 28 of offset but with 29 it's not working! That's the problem.

  4. #4
    Registered User
    Join Date
    Dec 2017
    Posts
    1,628
    Your code is hard to make sense of. It's pretty screwed up. That's why I took a stab at the pointless use of int8_t for the indices. How the hell would I know what no_of_devices is set to? (You seem to imply that it is 4 now.)


    Anyway, look at this:
    Code:
        for (i = 0; i < buffer_size; i++)
            display_buffer[i + 40] = Alphabet[i];
    Do you see anything wrong there?
    How big is Alphabet?
    Is it okay to access display_buffer[buffer_size-1 + 40] ?
    What are you trying to do?
    A little inaccuracy saves tons of explanation. - H.H. Munro

  5. #5
    Registered User
    Join Date
    Jan 2016
    Posts
    84
    int8_t is when I want a for loop which work in descending order and I want to reach index of 0 so I have to do like the following:
    Code:
    for (i=10;i>=0;i--)
    Yes, it's 4 sorry I just copied the function and not with the arguments in the main.

    Code:
    void set_data_up (uint8_t no_of_device, uint8_t data)
    data should receive a pointer, but now I'm not applying it in the test code.

    ================================================== ===

    Answering your questions:
    1. I can't say there's nothing wrong and insist that I'm right, I'm a beginner in C so I'm not an expert to say it's really a good piece of code
    2. Alphabet is big, it's 208 bytes, but I only want a part of this array for testing, because I'm just in the beginning to develop a function which convert one string letter of 1-byte to dot matrix 8-byte.
    3. Well, I have to work in order of 8-bytes moving in Alphabet array, so 40 is actually an offset of 5 dot matrix letters which is 5*8=40.
    4. I fixed the code with two ways:

    a) With a pointer:
    Code:
        uint8_t *p;
        p = display_buffer;
    
    
        for (i=0;i<buffer_size;i++)             // initialize array to zero
        *(p+i)=0;
    
    
        for (i=0;i<buffer_size;i++)             // copy data to display_buffer with offset
        *(p+offset+i)=Alphabet[i];
    b) Starting with offset value:
    Code:
    for (i=0;i<buffer_size;i++)             // initialize array to zero
        display_buffer[i]=0;
    
    
        for (i=32;i<buffer_size;i++)             // copy data to display_buffer with offset
        display_buffer[i]=Alphabet[i];

  6. #6
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,659
    for (i=0;i<buffer_size;i++) // copy data to display_buffer with offset
    display_buffer[i+40]=Alphabet[i];

    Fix your buffer overflow before doing anything else.
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.

  7. #7
    Registered User
    Join Date
    Jan 2016
    Posts
    84
    Oh, yes absolutely!

    Sorry, I thought it won't just overflow.

    Thank you,

  8. #8
    Registered User
    Join Date
    Jan 2016
    Posts
    84
    I have another question:

    I have a problem shifting data to specific locations in a 64-bit register. I've done well in 32-bit register.
    But this one gives a warning and also not shifting the data to the wanted location.

    This one would work with shifts 0, 8, 16 and 24 but not with 32 or more.
    Code:
        uint64_t map_buffer=0;
        map_buffer |= 0xff << 32;                 // loading data into map_buffer
    So, if I want to shift this data to the last location in the 64-bit register, so the output should be like this: 0xff000000.

  9. #9
    misoturbutc Hodor's Avatar
    Join Date
    Nov 2013
    Posts
    1,787
    Quote Originally Posted by wolfrose View Post
    I have another question:

    I have a problem shifting data to specific locations in a 64-bit register. I've done well in 32-bit register.
    But this one gives a warning and also not shifting the data to the wanted location.

    This one would work with shifts 0, 8, 16 and 24 but not with 32 or more.
    Code:
        uint64_t map_buffer=0;
        map_buffer |= 0xff << 32;                 // loading data into map_buffer
    So, if I want to shift this data to the last location in the 64-bit register, so the output should be like this: 0xff000000.
    Section 6.4.4.1 of the C Standard says that for a hexadecimal constant (in your case 0xff) its type shall be the first of the following types that can fit the value:
    int
    unsigned int
    long int
    unsigned long int
    long long int
    unsigned long long int
    0xff can fit in an int so its type is int. The next important thing you need to be aware of is the size of an int in bits (not necessarily know the answer, but be aware of it). It's quite feasible that an int on your machine is 16 bits or more likely 32 bits. Therefore shifting left 32 bits is going to shift all the bits out so that the number becomes all zero bits; i.e. 0. You therefore have to coerce the compiler into making 0xff a 64 bit value if you want to do what you're trying to do. You can use a suffix (probably 0xffULL) but the drawback of that is that you don't really know if that's 64 bits either so the best way is to probably cast it... i.e. (uint64_t)0xff << 32;

  10. #10
    Registered User
    Join Date
    Jan 2016
    Posts
    84
    Thank you very much

    Problem solved.

    I just have to type cast 0xff.

    Yes, I'm working basically to program Arduino board which has 8-bit microcontroller, I'm trying to fix the shifting problem because I want to shift 8-bit data of an array into a buffer of 64-bit in this case.

    But I want to change the buffer to an array so I can shift a lot of data as the size of data in the source array.

    Thank you for the support and help.
    Last edited by wolfrose; 03-01-2018 at 06:18 AM.

  11. #11
    Registered User
    Join Date
    Jan 2016
    Posts
    84
    How about this one? Is it reasonable line?

    I did it with the 8-bit register with type cast (uint64_t)

    But how about 8-bit array's content.


    Code:
            uint64_t map_buffer=0;
        for (i=0;i<8;i++)
    map_buffer |= (uint64_t)data_reg[i] << i*8;          // loading data into map_buffer
    It's working with the first 4-bytes, the rest 4-bytes won't show up.
    Last edited by wolfrose; 03-01-2018 at 10:57 AM.

  12. #12
    Registered User
    Join Date
    Dec 2017
    Posts
    1,628
    In what sense do they not "show up"?
    Code:
    #include <stdio.h>
    #include <inttypes.h>
    
    int main() {
        uint8_t data_reg[] = {1,2,3,4,5,6,7,8};
        uint64_t map_buffer = 0;
    
        for (int i = 0; i < 8; i++)
            map_buffer |= (uint64_t)data_reg[i] << i * 8;
    
        printf("%.16"PRIX64"\n", map_buffer);
    
        return 0;
    }
    A little inaccuracy saves tons of explanation. - H.H. Munro

  13. #13
    Registered User
    Join Date
    Jan 2016
    Posts
    84
    Absolutely works like a charm, really thank you for your kind replies and continuous support. I just want to finish LED matrix programming.

    Each display needs 8-bytes because it's 8x8, so I draw an entire byte on a row of 8 LEDs and so on.

    Now, working with drawing the same byte on an entire matrix, when I finish, then I move on to writing letters on a display. Thank you again

  14. #14
    Registered User
    Join Date
    Jan 2016
    Posts
    84
    I have a related question to the same code I'm working on.

    It's about bits shifting in an array, should I post it here or open a new thread?


    Anyway, in case it's fine to post the question here, this is my problem:

    Code:
    uint8_t i,k,s,p,u,l,o,e;uint8_t buffer1[40],bit_mask[40];                  // buffer1 for shifting data & bit_mask for saving the carried bit
    
    
    for (k=0;k<40;k++){                                // initialize both arrays to 0
    buffer1[k]=0;bit_mask[k]=0;}
    
    
    for (k=0;k<8;k++)
    buffer1[k]=0x80;                                   // put this value for testing in the first 8-bytes then shift it to the next 8-bytes
    
    
    for (i=0;i<40;i++)
    {printf("shift %d\n",i);                           // prints no. of shifts
    
    
            for (k=0;k<40;k++)
            {
                printf("0x%.2x\t",buffer1[k+(e*8)]);   // print the data in order of 8-bytes at total of 40-bytes
               if (k%8==7)printf("\n");                // after printing 8-bytes put a new line
            }printf("\n");                             // new line after 40-bytes of each  shift
    
    
        for (k=0;k<40;k++)                             // scan whole array
        {
                if (buffer1[k] & 0x80)                 // test MSB of each byte
                bit_mask[k+8] = 0x01;                  // taking the address of the next parallel byte
        }
    
    
        for (k=0;k<40;k++)                             // shift every byte
        buffer1[k]<<=1;
        for (k=0;k<40;k++)                             // copy the carried bit to the parallel byte
        buffer1[k]|=bit_mask[k];
    
    
        for (k=0;k<40;k++)                             // clear bit_mask content for the next test
        bit_mask[k]=0;
    
    
    }
    The code works OK until shift 33, there shouldn't be any data to shift. Instead, there is a new data coming to the first 8-bytes! Where did that data come from. As I put the test data out of the 40-shift loops.
    Last edited by wolfrose; 03-17-2018 at 01:07 AM. Reason: edit code

  15. #15
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,659
    1. Your indentation sucks -> Indentation style - Wikipedia

    2. i,k,s,p,u,l,o,e
    Just meaningless.
    i,j,k are fine for loop control variables, but everything else needs a meaningful name.

    3. What is the value of e?
    > printf("0x%.2x\t",buffer1[k+(e*8)]);
    If it's anything other than zero, you lose.
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Replies: 2
    Last Post: 07-25-2015, 01:26 AM
  2. How To: Content of Array to String
    By rishiraj in forum C Programming
    Replies: 7
    Last Post: 04-17-2014, 12:57 PM
  3. How to copy the content of an array into a pointer
    By firstoption in forum C Programming
    Replies: 2
    Last Post: 09-22-2011, 09:31 AM
  4. printing array content - spot the error
    By nosnowking in forum C Programming
    Replies: 5
    Last Post: 02-04-2009, 05:50 PM
  5. changing the array content !!
    By mehuldoshi in forum C Programming
    Replies: 2
    Last Post: 06-29-2002, 06:33 AM

Tags for this Thread