Home > front end >  How can I put int or size_t variables into a char array?
How can I put int or size_t variables into a char array?

Time:02-22

Hello everyone so i want to put a size_t variable of a number up to 4096 in order to keep track of how much "memory" i used in the array (yes it has to be a char array). So for example

#include <stdio.h>
#include <unistd.h>
int main(void)
{
char mem[4096] = {0};
size_t size = 4095;
mem[0] = size;
//then somehow be able to size = mem[0] to be able to recall the size later. 
    return 0;
}

I just want to be able to put a number in the first array elment in order to be able to keep track of how many elements ive used. Im implementating a heap memory and i also have to implement malloc(), and free() i have a char array that simulates the heap memory, and i cant use global/ static local variables but i want to be able to keep track of the heap size. My best thought of action was to store the heap size in the "Heap" (char array) to be able to keep track of it.

CodePudding user response:

If you must use a char array for storing the number of bytes used, you have (at least) two choices:

  1. create a union of an uint16_t with the array. This will allow you to use the first two bytes to hold the number of bytes used.
  2. essentially the same as #1 but do the math manually, and maintain the bytes yourself.

I'd recommend #1.

CodePudding user response:

About the most straightforward way to do this that is defined by the C standard is with to copy the bytes from the size object to the memory:

memcpy(&mem[index], &size, sizeof size);

Good compilers with optimization enabled will optimize this to a store from size to memory if they can determine &mem[index] is suitably aligned (or an unaligned store instruction is available and a good method). The reverse, to retrieve the size, is memcpy(&size, &mem[index], sizeof size);.

It can be done with unions, but that may be cumbersome in this situation. The union would have to include the entire array.

Old C code would simply cast an address in mem to the desired type, as with * (size_t *) &mem[index] = size;. However, the C standard does not define the behavior when an array defined as an array of char is accessed through a size_t lvalue as the above does. This worked with old compilers, and modern compilers may still support it if an appropriate switch is given to ask the compiler to support it, but it is needless, so new code should avoid this in favor of more portability.

Note that you do not need to use a size_t if the size will only be 4096. For this, you can use uint16_t.

Another option is to calculate the two bytes:

static void RecordSize(unsigned char *memory, uint16_t size)
{
    memory[0] = size >> 8; // Record high bits.
    memory[1] = size;      // Record low bits.
        // This will automatically “chop off” high bits.
}

static uint16_t RetrieveSize(unsigned char *memory)
{
    return (uint16_t) memory[0] << 8 | memory[1];
}

…

RecordSize(&mem[index], size);
…
size = RetrieveSize(&mem[index];

That would be used more rarely than the direct copy, but it could be useful if data is being recorded in memory to transmit to another computer system that may use a different byte ordering for its integers. This method explicitly stores the high bits first and the low bits second (or the code could be written to do the opposite, as desired).

Note that this code uses unsigned char. You should generally prefer to use unsigned char for manipulations of bytes as arbitrary data, as it avoids some problems that can occur with signed types. (The C standard leaves it implementation-defined whether the char type is signed or unsigned.)

  •  Tags:  
  • c
  • Related