What does [0] = addr & 0xff do?

I am currently studying the book "Shellcoder Reference", I have a strong understanding of c, but recently I came across a piece of code that I cannot understand.

Here is the code snippet:

          char a[4];
          unsigned int addr = 0x0806d3b0;
          a[0] = addr & 0xff;
          a[1] = (addr & 0xff00) >> 8; 
          a[2] = (addr & 0xff0000) >> 16;
          a[3] = (addr) >> 24;

So the question is what is it, what is addr and 0xff (and the three lines below it), and what does → 8 do for it (I know that it divides it 8 times by 2)? Ps: feel free to tell me if you have any ideas for tags that I should use.

+4
source share
8 answers

addr - 32 , a - 8 . , 32 addr a, .

:

a[1] = (addr & 0xff00) >> 8; 

.

  • addr & 0xff00 8 15 addr, 0x0000d300.
  • >> 8 , 0x0000d300 0x000000d3.
  • a[1].
+6

. , . :

a[0] = addr & 0xff; /* gets the LSB 0xb0 */
a[1] = (addr & 0xff00) >> 8; /* gets the 2nd LSB 0xd3 */
a[2] = (addr & 0xff0000) >> 16; /* gets 2nd MSB 0x06 */
a[3] = (addr) >> 24; /* gets the MSB 0x08 */

, , "a" .

+3
unsigned char a[4]; /* I think using unsigned char is better in this case */
unsigned int addr = 0x0806d3b0;
a[0] = addr & 0xff; /* get the least significant byte 0xb0 */
a[1] = (addr & 0xff00) >> 8; /* get the second least significant byte 0xd3 */
a[2] = (addr & 0xff0000) >> 16; /* get the second most significant byte 0x06 */
a[3] = (addr) >> 24; /* get the most significant byte 0x08 */
+2

-, addr, a, .

a[0] = addr & 0xff;

, 0xff ; , , , . ,

a[3] = (addr) >> 24;

, .

+1

32- 4 . , , , char (8 ). , , , .. .

+1

endianness little-endian a.

.

+1

, .

    char a[4];
    unsigned int addr = 0x0806d3b0;
    a[0] = addr & 0xff;
    a[1] = (addr & 0xff00) >> 8; 
    a[2] = (addr & 0xff0000) >> 16;
    a[3] = (addr) >> 24;

    int i = 0;
    for( ; i < 4; i++ )
    {
        printf( "a[%d] = %02x\t", i, (unsigned char)a[i] );
    }
    printf("\n" );

:

a[0] = b0   a[1] = d3   a[2] = 06   a[3] = 08
+1

, , . , char - . C. , .

While we are in this state, we can also tidy up the code, make it overly explicit in order to avoid possible errors in the future, delete some implicit declarations such as integer literals, etc.

#include <stdint.h>

uint8_t a[4];
uint32_t addr = 0x0806d3b0UL;
a[0] = addr & 0xFFu;
a[1] = (addr >>  8) & 0xFFu;
a[2] = (addr >> 16) & 0xFFu;
a[3] = (addr >> 24) & 0xFFu;

Masks & 0xFFu, strictly speaking, are not needed, but they can save you from some false positive warnings from the compiler about the wrong integer types. Alternatively, each shift result can be distinguished to uint8_t, and that would be nice too.

+1
source

Source: https://habr.com/ru/post/1617041/


All Articles