Splitting a sequence of binary digits based on inputs in c
Splitting a sequence of binary digits based on inputs in c
I have an array of binary digits that represent an address. I want to now segregate this address into 3 parts or arrays that are tag
, index
and offset
and the number of bits for each of these three are determined by the user.
For better clarity, this is the code:
tag
index
offset
char* bin_val_addr;
while(fscanf(FP, "%s %lx", str, &addr) != EOF)
bin_val_addr = long_to_binary(addr);
char* array_Tag = malloc(no_Tag_bits * sizeof(char*));
char* array_Index = malloc(no_Index_bits * sizeof(char*));
memcpy(array_Tag, bin_val_addr, no_Tag_bits * sizeof(char*));
memcpy(array_Index, bin_val_addr, no_Index_bits * sizeof(char*));
printf("TAG array is: %sn", array_Tag);
printf("INDEX array is: %sn", array_Index);
And the function long_to_binary is as follows:
char* long_to_binary(unsigned long k)
static char c[65];
c[0] = '';
unsigned long val;
for (val = 1UL << (sizeof(unsigned long)*8-1); val > 0; val >>= 1)
strcat(c, ((k & val) == val) ? "1" : "0");
return c;
I looked up ways to split arrays and found that memcpy
can be used but I am going wrong somewhere while implementing this. Can someone help me out here?
memcpy
okay so I'd have to change the
sizeof(char*)
statement right?– Sam
Sep 16 '18 at 22:02
sizeof(char*)
Yes, if you want to allocate a string that can hold N characters then you need to malloc(N+1), rather than malloc(N * sizeof(char *)).
– jarmod
Sep 16 '18 at 22:04
And why is the way I return c wrong?
– Sam
Sep 16 '18 at 22:04
Ah, it's static. Did not notice that earlier. It's OK in that case (I'm not a big fan but it will work).
– jarmod
Sep 16 '18 at 22:05
1 Answer
1
If bin_val_addr
contains the sequence of 1s
and 0s
in the order tag
, index
and offset
, then the following copies from the beginning of bin_val_addr
for both array_Tag
and array_Index
, e.g.
bin_val_addr
1s
0s
tag
index
offset
bin_val_addr
array_Tag
array_Index
memcpy(array_Tag, bin_val_addr, no_Tag_bits * sizeof(char*));
memcpy(array_Index, bin_val_addr, no_Index_bits * sizeof(char*));
If array_Index
begins after array_Tag
in bin_val_addr
, then you would need to offset your source for array_Index
by no_Tag_bits
.
array_Index
array_Tag
bin_val_addr
array_Index
no_Tag_bits
(and note you are mixing bits and bytes (you have characters '1'
and '0'
not bits). So, unless you need 8-bytes per-character, sizeof(char*)
should be sizeof(char)
-- which is always 1
and should be eliminated from your allocations)
'1'
'0'
sizeof(char*)
sizeof(char)
1
For example, allocating to hold the characters specified in each array (+1
for the nul-terminating character), you could do:
+1
char *array_Tag = malloc(no_Tag_bits + 1);
char *array_Index = malloc(no_Index_bits + 1);
and you must validate each allocation, because malloc
can and will fail returning NULL
on memory exhaustion, e.g.
malloc
NULL
if (!array_Tag)
perror ("malloc-array_Tag");
exit (EXIT_FAILURE);
Putting those pieces together and nul-terminating each string, you would have:
memcpy (array_Tag, bin_val_addr, no_Tag_bits);
array_Tag[no_Tag_bits] = 0;
memcpy (array_Index, bin_val_addr + no_Tag_bits, no_Index_bits);
array_Index[no_Index_bits] = 0;
Which would now allow you to output the arrays as strings:
printf ("TAG array is: %sn", array_Tag);
printf ("INDEX array is: %sn", array_Index);
Lastly, your use of fscanf
invites Undefined Behavior on a matching or input failure where less that the total number of conversions specified takes place. Instead of checking against EOF
, you should validate with the number of conversions specified actually occurred, e.g.
fscanf
EOF
while (fscanf (FP, "%s %lx", str, &addr) == 2)
After making those changes, and presuming your long_to_binary
is working as you intend, let me know if you have further questions.
long_to_binary
Thanks for contributing an answer to Stack Overflow!
But avoid …
To learn more, see our tips on writing great answers.
Required, but never shown
Required, but never shown
By clicking "Post Your Answer", you agree to our terms of service, privacy policy and cookie policy
If you want to store, for example, 1010 in a string then that string will need to be at least 5 characters in length (4 to hold 1010 and 1 to hold the string's null terminator). Your code is incorrectly allocating 4 char pointers, when it should allocate 5 chars. There are other problems here too, for example the way you are returning 'c' from the long_to_binary() function needs to change.
– jarmod
Sep 16 '18 at 22:00