Home > Back-end >  How can I set the size of elements in an array in C?
How can I set the size of elements in an array in C?

Time:08-03

I am experimenting a bit with C and want to limit the max size of an element in a char* array to 512 bits. I know how to limit the size of the array on 512 bits, but not the individual array elements.

How would I implement this in C? I am pretty new to C and new to all of this memory allocation stuff.

CodePudding user response:

You're trying to make an array of datatypes that are 64-bytes wide. You can use char for this, but you don't have to.

struct myStruct{
  char data[64];
};

...is an example of a struct containing at least 512 bits.

If you #include <stdint.h>, you can use C-standard fixed-width datatypes like int8_t, which is 8-bits wide, or int64_t, which is 64-bits wide, so you could also do:

struct myStruct{
  int8_t data[64];
};

...or

struct myStruct{
  int64_t data[8];
};

And the only difference would be the size of each individual array member in .data in your struct.

Once you have a struct that is 512 bits wide you can make an array of them like so:

struct myStruct array[ARRAY_LENGTH];

CodePudding user response:

I am experimenting a bit with C and want to limit the max size of an element in a char* array to 512 bits.

If by "char* array" you mean

char *array[NUMBER_OF_ELEMENTS];

then I take you to be failing to distinguish between pointers and the things they point to. The elements of that array are pointers (to char), and they will all have the same size as each other. Typically, that's either 32 or 64 bits in modern C implementations. That has little to do with the objects, if any, to which the pointers point.

If I infer correctly that you are thinking of char pointers that point to the first characters of C strings,* and that you want to express a limitation on the length of those strings, then I'm afraid you're out of luck -- the number of characters in a string is in no way carried by the type or value of a pointer (in)to it. You cannot express limits on that via the type of an array containing the pointers.

But what you can do is use an array of (char) arrays instead of an array of pointers:

char array[NUMBER_OF_STRINGS][512 / CHAR_BIT];

That assumes that 512 is evenly divisible by CHAR_BIT (the number of bits in the representation of type char), which is the only case in which an object's size can be or be limited to exactly 512 bits. That assumption has not always been satisfied in historical C implementations, but it is true of substantially all modern C implementations.

Many people would go even further and assume that CHAR_BIT is 8, which is ubiquitously true for the widely used C implementations for modern general-purpose computers. In that case, they could simply write

char array[NUMBER_OF_STRINGS][64];

The individual strings would be accessed by index, just like the pointers in your char * array, and in most contexts, those would "decay" to pointer to the first elements, so that code such as ...

char *s = array[1];
strcpy(array[42], "Hello, world!");
printf("%s", array[3]);

... is valid and reasonable (at least if NUMBER_OF_STRINGS is larger than the indices used). What that does not allow, however, is assigning directly to the member arrays. You would need to copy data into them, as the second example just above demonstrates.


*For otherwise, it's unclear what you might mean by "max size", as opposed to just "size".

CodePudding user response:

You can use this:

#include <stdint.h>
#include <stdio.h>

typedef struct { uint8_t data[ 64 ]; } block512_t;

int main( void ) {
   printf( "%zu\n", sizeof( block512_t ) );      // 64
   printf( "%zu\n", sizeof( block512_t ) * 8 );  // 512

   block512_t a[ 10 ];
   printf( "%zu\n", sizeof( a[ 0 ] ) );          // 64
   printf( "%zu\n", sizeof( a[ 0 ] ) * 8 );      // 512
}

Explanation follows.


The smallest unit in C is a char, not a bit. You'll need to find the correct number of char values needed.

#include <limits.h>

size_t size = ( 512 / CHAR_BIT )   ( 512 % CHAR_BIT ? 1 : 0 );

Then you can use that to allocate a buffer of the correct size.

unsigned char *buf = malloc( size );   // Dynamic allocation.

unsigned char buf[ size ];             // Static or automatic allocation.

In an environment where CHAR_BIT is 8, size is 64.

In an environment where 512 isn't evenly divisible by CHAR_BIT, there will be some extra bits.


That said, unless you're dealing with special hardware, there's going to be a uint8_t type you could use.

#include <stdint.h>

uint8_t *buf = malloc( 64 );   // Dynamic allocation.

uint8_t buf[ 64 ];             // Static or automatic allocation.

So we've covered how to create one 512 bit value. You say you want an array of them. Well, nothing's stopping you.

In the comments, you mention using a struct. Of course you could do that, and it would help clean things up.

#include <limits.h>
#include <stdio.h>

#define BYTES_NEEDED_FOR_512_BITS ( ( 512 / CHAR_BIT )   ( 512 % CHAR_BIT ? 1 : 0 ) )

typedef struct { unsigned char data[ BYTES_NEEDED_FOR_512_BITS ]; } block_least512_t;

int main( void ) {
   printf( "%zu\n", sizeof( block_least512_t ) );             // 64*
   printf( "%zu\n", sizeof( block_least512_t ) * CHAR_BIT );  // 512*

   block_least512_t a[ 10 ];
   printf( "%zu\n", sizeof( a[ 0 ] ) );                       // 64*
   printf( "%zu\n", sizeof( a[ 0 ] ) * CHAR_BIT );            // 512*
}

* - In an environment where CHAR_BIT is 8.


Of course, you can use uint8_t with this approach.

#include <stdint.h>
#include <stdio.h>

typedef struct { uint8_t data[ 64 ]; } block512_t;

int main( void ) {
   printf( "%zu\n", sizeof( block512_t ) );      // 64
   printf( "%zu\n", sizeof( block512_t ) * 8 );  // 512

   block512_t a[ 10 ];
   printf( "%zu\n", sizeof( a[ 0 ] ) );          // 64
   printf( "%zu\n", sizeof( a[ 0 ] ) * 8 );      // 512
}

Instead of a struct, one could also use a typedef.

typedef unsigned char block_least512_t[ BYTES_NEEDED_FOR_512_BITS ];

While that gets rid of the need to use .data, it would prevent the value from being used like a primitive. For example, block2 = block1; wouldn't work. As such, I recommend against it.

  • Related