A doubt of hexadecimal and c

3

The exercise that is proposed to do in C is as follows:

More or less the approach is clear to me the table represents the values of tab [] in hexadecimal and on the right its expression in ASCII, as it tells us to do it according to the example and since 1Byte is 2 hexadecimal characters I must assume that each element of the array must occupy 4Bytes (I do not know if this is by agreement or some other reason, as I understand int occupies 2Bytes in C, so I suppose it would be because the one who poses the problem wants to do it), well my The question is as follows: As I see to represent the elements of tab [] only two hexadecimal characters are used, that is, (N1) * 16 ^ 1 + (N2) * 16 ^ 0, so the maximum I can write is 0xff = 255, if in the array I write a number greater than 255 what is the way to represent it here? well I guess the other 3Bytes are for something not?

    
asked by latiagertrutis 22.07.2017 в 03:20
source

2 answers

2

the int type was defined as a word in the micro architectures 8086, 80286, however from the 80386, int is by default a double word

Basically what they ask you is to print lines of 16B in 2 columns, the first column is the hexadecimal representation in groups of 2B while the second column is the representation in ascii.

The pseucode would be the following

void
print_memory (const void *addr, size_t size)
{
  for(cada byte en [addr, addr + size])
   {
      imprimir byte en hex
      if(se ha imprimido 2B)
        {
          imprimir espacio
        }

      if(se han imprimido 16B)
        {
          imprimir los 16B anteriores en ascii
          imprimir salto de linea
        }

   }
   imprimir en forma alineada los ascii de la línea incompleta
   imprimir salto de linea
}

Implementation is trivial

print_memory.c

#include <ctype.h> // isprint
#include <stdio.h>  // printf
#include <stdlib.h> // size_t

#define LINE_IN_BYTES         0x10 
#define WORD_IN_BYTES         2
#define HEX_DIGIT_PER_CHAR    2

#define IS_ODD(x) (x % 2 == 1)

              void print_memory (const void*, size_t);
static        void print_ascii (const void*, size_t);
static inline void print_spaces (size_t);

int
main (void)
{
  int tab[10] = {0, 23, 150, 255, 12, 16, 21, 42};
  char m[17] = "Hola mundo";

  print_memory (tab, sizeof(tab));
  print_memory (m, sizeof(m));  

  return 0;
}

void
print_memory (const void *addr, size_t size)
{
  size_t i;
  size_t resto;
  const unsigned char *c;

  if (addr == NULL)
      return; 

  for (i = 1; i <= size; i++)
    {
      c = (addr + i - 1);
      printf ("%02hhx", *c);

      if (i % WORD_IN_BYTES == 0)
        {
          putchar (' ');
        }

      if (i % LINE_IN_BYTES == 0)
        {
          print_ascii (c - LINE_IN_BYTES + 1, LINE_IN_BYTES);
          printf ("\n");
        }
    }

    if ((resto = size % LINE_IN_BYTES) > 0) // falta ascii que imprimir
      {
        print_spaces ((HEX_DIGIT_PER_CHAR + 0.5) * (LINE_IN_BYTES - resto)); // rellena lo faltante
        if(IS_ODD (resto))
            putchar (' '); // alinea a palabra 
        print_ascii (c - resto + 1, resto);
        printf ("\n");
      }
}


static void 
print_ascii (const void *addr, size_t size)
{
  size_t i;
  const unsigned char *c;

  for (i = 0; i < size; i++)
    {
      c = (addr + i);
      if (isprint (*c))
        putchar (*c);
      else
        putchar ('.');
    } 
}

static inline 
void 
print_spaces (size_t size)
{
  size_t i;
  for (i = 0; i < size; i++)
    {
      putchar(' ');   
    }
}

Compile it

$ gcc print_memory.c -o print_memory -Wall -Werror; ./print_memory | cat -e
0000 0000 1700 0000 9600 0000 ff00 0000 ................$
0c00 0000 1000 0000 1500 0000 2a00 0000 ............*...$
0000 0000 0000 0000                     ........$
486f 6c61 206d 756e 646f 0000 0000 0000 Hola mundo......$
00                                      .$

Observations: Do not worry about the endianness , since it does not vary much, since ANSI C specifies that the elements in an array should be stored as they are declared, the first element of the array being the least address in memory.

Your arrangement

               MAYOR

    0         4
    ===========
              0      tab + 36
    -----------
              0      tab + 32
    -----------
             42      tab + 28
    -----------
             21      tab + 24
    -----------
             16      tab + 20
    -----------
             12      tab + 16
    -----------
            255      tab + 12   
    -----------
            150      tab +  8
    -----------
             23      tab +  4
    -----------
              0      tab +  0
    ===========        
MENOR

Whatever the endianness , the previous figure does not change.

Little endian

The previous figure for little endian would be the following

               MAYOR

    0         4 
    ===========
    0x0000 0000      tab + 36
    -----------
    0x0000 0000      tab + 32
    -----------
    0x2A00 0000      tab + 28
    -----------
    0x1500 0000      tab + 24
    -----------
    0x1000 0000      tab + 20
    -----------
    0x0C00 0000      tab + 16
    -----------
    0xFF00 0000      tab + 12   
    -----------
    0x9600 0000      tab +  8
    -----------
    0x1700 0000      tab +  4
    -----------
    0x0000 0000      tab +  0
    ===========        
MENOR

Big endian

               MAYOR

    0         4 
    ===========
    0x0000 0000      tab + 36
    -----------
    0x0000 0000      tab + 32
    -----------
    0x0000 002A     tab + 28
    -----------
    0x0000 0015      tab + 24
    -----------
    0x0000 0010      tab + 20
    -----------
    0x0000 000C      tab + 16
    -----------
    0x0000 00FF      tab + 12   
    -----------
    0x0000 0096      tab +  8
    -----------
    0x0000 0017      tab +  4
    -----------
    0x0000 0000      tab +  0
    ===========        
MENOR
    
answered by 22.07.2017 / 09:43
source
1
  

I do not know if this is by agreement or some other reason, as I have   understood int occupies 2Bytes in C.

What returns sizeof(int) depends on the compiler, but currently it is much more common than int have a size of 4 bytes, this would be 8 hexadecimal digits.

  

If in the array I write a number greater than 255 which is the form of   represent it here?

If you look at what the function returns print_memory you will realize that each element of tab corresponds to 8 digits in hexadecimal, that is, 0 will be printed as 0000 0000 , 255 will be printed as ff00 0000 , what happens if we go from 255 ?, then nothing, for example 256 would be printed as 1000 0000 , to explain why this would happen more clearly realize this program that does almost the same as the one that shows in the statement .

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

void print_memory(int *array, size_t size) {
  int i, times = size / sizeof(int);

  for (i = 0; i < times; i++) {
    printf("%08x ", array[i]);

    if ((i + 1) % 4 == 0)
      printf("\n");
  }
}

int main() {
  int tab[10] = {256, 23, 150, 255, 12, 16, 21, 42};

  print_memory(tab, sizeof(tab));

  return 0;
}

If we execute it, we will obtain:

00000100 00000017 00000096 000000ff
0000000c 00000010 00000015 0000002a
00000000 00000000

As you see, 255 is represented by 000000ff , but in the original program it is printed in Little Endian , so so there is ff000000 , that is, 256 which would be represented by 00000100 in the original program would be shown as 10000000 , the problem of this is that confusion originates, since you could not know if 10000000 represents 256, 1 or 12 (if you look at your sentence 12 it is also printed as 10000000 )

In summary

The program of the statement does the same as the one I put above, but it prints the hexadecimal numbers in little endian format, and for the part of the characters it will only be necessary to print what these numbers represent in ASCII code.

    
answered by 22.07.2017 в 07:03