#include <stdio.h>
#include <stdlib.h>
void get_nbits(int num, int n);
void replace_nbits(int num, int n, int val);
void get_nbits_from_pos(int num, int n, int pos);
void replace_nbits_from_pos(int num, int n, int pos, int val);
void toggle_bits_from_pos(int num, int n, int pos);
void print_bits(unsigned int num, int n);
int main()
{
printf("\tThis program is to show the below mentioned bitwise functions\n\n");
printf("Select bit operation from below list:\n1. get_nbits\n2. set_nbits\n3. get_nbits_from_pos\n");
printf("4. set_nbits_from_pos\n5. toggle_bits_from_pos\n6. print_bits\n");
printf("Enter your choice: ");
int choice,num,n,pos,val;
scanf("%d",&choice);
switch(choice)
{
case 1:
printf("Enter number: ");
scanf("%d",&num);
printf("Enter n: ");
scanf("%d",&n);
get_nbits(num,n);
printf("\n");
break;
case 2:
printf("Enter number: ");
scanf("%d",&num);
printf("Enter n: ");
scanf("%d",&n);
printf("Enter val: ");
scanf("%d",&val);
replace_nbits(num,n,val);
printf("\n");
break;
case 3:
printf("Enter number: ");
scanf("%d",&num);
printf("Enter n: ");
scanf("%d",&n);
printf("Enter pos: ");
scanf("%d",&pos);
get_nbits_from_pos(num,n,pos);
printf("\n");
break;
case 4:
printf("Enter number: ");
scanf("%d",&num);
printf("Enter n: ");
scanf("%d",&n);
printf("Enter val: ");
scanf("%d",&val);
printf("Enter pos: ");
scanf("%d",&pos);
replace_nbits_from_pos(num,n,pos,val);
printf("\n");
break;
case 5:
printf("Enter number: ");
scanf("%d",&num);
printf("Enter n: ");
scanf("%d",&n);
printf("Enter pos: ");
scanf("%d",&pos);
toggle_bits_from_pos(num,n,pos);
printf("\n");
break;
case 6:
printf("Enter number: ");
scanf("%d",&num);
printf("Enter n: ");
scanf("%d",&n);
print_bits(num,n);
printf("\n");
break;
}
}
void get_nbits(int num, int n)
{
int bin_num[9];
int cnt = 0;
int bin_dig = 0;
int multiple = 1;
int decimal_num = 0, base = 1, rem;
while (num > 0) {
bin_num[cnt] = num % 2;
num = num / 2;
cnt ;
}
for(int i=0;i<8;i )
{
bin_num[i cnt] = 0;
}
printf("The binary form of given number: ");
for(int i=7;i>=0;i--)
{
printf("%d ",bin_num[i]);
}
for(int i=0;i<n;i )
{
bin_dig = bin_dig multiple*bin_num[i];
multiple*=10;
}
while ( bin_dig > 0)
{
rem = bin_dig % 10;
decimal_num = decimal_num rem * base;
bin_dig = bin_dig / 10;
base = base * 2;
}
printf("\nThe decimal number is: %d\n",decimal_num);
}
void replace_nbits(int num, int n, int val)
{
int bin_num1[9],bin_num2[9];
int cnt1 = 0,cnt2 = 0;
int bin_dig = 0,bin_dig2 = 0;
int multiple = 1;
int decimal_num = 0, base = 1, rem;
while (num > 0) {
bin_num1[cnt1] = num % 2;
num = num / 2;
cnt1 ;
}
for(int i=0;i<8;i )
{
bin_num1[i cnt1] = 0;
}
printf("\nThe binary form of given number: ");
for(int i=7;i>=0;i--)
{
printf("%d ",bin_num1[i]);
}
while (val > 0) {
bin_num2[cnt2] = val % 2;
val = val / 2;
cnt2 ;
}
for(int i=0;i<8;i )
{
bin_num2[i cnt2] = 0;
}
printf("\nThe binary form of given value: ");
for(int i=7;i>=0;i--)
{
printf("%d ",bin_num2[i]);
}
for(int i=0;i<n;i )
{
bin_dig = bin_dig multiple*bin_num2[i];
multiple*=10;
}
multiple = 1;
int temp = bin_dig;
for(int i=0;i<n;i )
{
bin_num1[i] = temp;
temp/=10;
}
printf("\nThe binary form of given number after replacing is: ");
for(int i=7;i>=0;i--)
{
printf("%d ",bin_num1[i]);
}
for(int i=0;i<cnt1;i )
{
bin_dig2 = bin_dig2 multiple*bin_num1[i];
multiple*=10;
}
while ( bin_dig2 > 0)
{
rem = bin_dig2 % 10;
decimal_num = decimal_num rem * base;
bin_dig2 = bin_dig2 / 10;
base = base * 2;
}
printf("\nThe decimal from given number after replacing is: %d\n",decimal_num);
}
void get_nbits_from_pos(int num, int n, int pos)
{
int bin_num[9];
int cnt = 0;
int bin_dig = 0;
int multiple = 1;
int decimal_num = 0, base = 1, rem;
while (num > 0) {
bin_num[cnt] = num % 2;
num = num / 2;
cnt ;
}
for(int i=0;i<8;i )
{
bin_num[i cnt] = 0;
}
printf("\nThe binary form of given number: ");
for(int i=7;i>=0;i--)
{
printf("%d ",bin_num[i]);
}
int from_num = 0;
for(int i = pos;from_num<n;i--,from_num )
{
bin_dig = bin_dig multiple*bin_num[i];
if(bin_dig==1) multiple*=10;
}
while ( bin_dig > 0)
{
rem = bin_dig % 10;
decimal_num = decimal_num rem * base;
bin_dig = bin_dig / 10;
base = base * 2;
}
printf("\nThe decimal number is: %d\n",decimal_num);
}
void replace_nbits_from_pos(int num, int n, int pos, int val)
{
int bin_num1[9],bin_num2[9];
int cnt1 = 0,cnt2 = 0;
int bin_dig = 0,bin_dig2 = 0;
int multiple = 1;
int decimal_num = 0, base = 1, rem;
while (num > 0) {
bin_num1[cnt1] = num % 2;
num = num / 2;
cnt1 ;
}
for(int i=0;i<8;i )
{
bin_num1[i cnt1] = 0;
}
printf("\nThe binary form of given number: ");
for(int i=7;i>=0;i--)
{
printf("%d ",bin_num1[i]);
}
while (val > 0) {
bin_num2[cnt2] = val % 2;
val = val / 2;
cnt2 ;
}
for(int i=0;i<8;i )
{
bin_num2[i cnt2] = 0;
}
printf("\nThe binary form of given value: ");
for(int i=7;i>=0;i--)
{
printf("%d ",bin_num2[i]);
}
for(int i=n;i>0;i--)
{
bin_dig = bin_dig multiple*bin_num2[i];
if(bin_dig==1) multiple*=10;
}
multiple = 1;
int temp = bin_dig;
printf("\n%d",bin_dig);
for(int i=pos;i>(pos-n);i--)
{
bin_num1[i] = temp;
temp/=10;
}
printf("\nThe binary form of given number after replacing is: ");
for(int i=7;i>=0;i--)
{
printf("%d ",bin_num1[i]);
}
for(int i=0;i<8;i )
{
bin_dig2 = bin_dig2 multiple*bin_num1[i];
multiple*=10;
}
while ( bin_dig2 > 0)
{
rem = bin_dig2 % 10;
decimal_num = decimal_num rem * base;
bin_dig2 = bin_dig2 / 10;
base = base * 2;
}
printf("\nThe decimal from given number after replacing is: %d\n",decimal_num);
}
void toggle_bits_from_pos(int num, int n, int pos)
{
int bin_num[9];
int cnt = 0;
int bin_dig = 0;
int multiple = 1;
int decimal_num = 0, base = 1, rem;
while (num > 0) {
bin_num[cnt] = num % 2;
num = num / 2;
cnt ;
}
for(int i=0;i<8;i )
{
bin_num[i cnt] = 0;
}
printf("The binary form of given number: ");
for(int i=7;i>=0;i--)
{
printf("%d ",bin_num[i]);
}
int from_num = 0;
for(int i = pos;from_num<n;i--,from_num )
{
bin_num[i] = bin_num[i]^1;
}
printf("\nThe binary form of given number after toggling: ");
for(int i=7;i>=0;i--)
{
printf("%d ",bin_num[i]);
}
for(int i=0;i<8;i )
{
bin_dig = bin_dig multiple*bin_num[i];
multiple*=10;
}
while ( bin_dig > 0)
{
rem = bin_dig % 10;
decimal_num = decimal_num rem * base;
bin_dig = bin_dig / 10;
base = base * 2;
}
printf("\nThe decimal number is: %d\n",decimal_num);
}
void print_bits(unsigned int num, int n)
{
int* bin_num = malloc(n*sizeof(int));
int cnt = 0;
int bin_dig = 0;
int multiple = 1;
int decimal_num = 0, base = 1, rem;
while (num > 0) {
bin_num[cnt] = num % 2;
num = num / 2;
cnt ;
}
if(n>num)
{
for(int i=0;i<n;i )
{
bin_num[i cnt] = 0;
}
}
if(cnt>n)
{
printf("The n value is lower than the orignal number of digits\n");
n = cnt;
}
printf("The binary form of given number: ");
for(int i=n-1;i>=0;i--)
{
printf("%d ",bin_num[i]);
}
free(bin_num);
}
I'm a beginner and working with Arrays switch cases and loops of arrays concept coding to do some operations on binary numbers using arrays Here I am able to get the output as expected, but I can't figure out the problem of *** stack smashing detected ***: terminated. This comes at the end of the output I don't know why; anyone can help me with it please? And please tell me what the error means.
CodePudding user response:
stack smashing occur when one exceeds the size of a specific array(buffer overflow). It a defense mechanism to prevent overwriting of data. Please check your for
loop in your functions the value of cnt
goes beyond 9 which the size of the array. You can also you refer to What is the "stack smashing detected" error?
CodePudding user response:
This answer is not related for the error, however, using this bit position arithmetic technique you would get rid of the main causes of that error. In this technique you don't have to use neither arrays nor number base conversions but bit arithmetics only.
Consider the number 105 which would be expressed as 01101001
in 8-bit binary right? If it is assigned to an int
there will be 24 more digits toward MSb (Most Significant bit). Using bit position arithmetic we can read and print the bit values and we can slice between any 2 positions within the type's bit count range.
Here I show how it could be done using your 2 functions called get_nbits
and get_nbits_from_msb_pos
(I changed the 2nd one's name to specify the direction operation). I modified their content for this purpose and also added a utility function called printBinary
to print binary values of a given int variable, within the desired range.
#include <stdio.h>
void printBinary(int val, int from, int to) {
int bit_count = sizeof(val) * 8;
if(from < to) {
printf("Argument error: from cannot be lesser than or equal to to\n");
return;
}
else if(from > bit_count || to < 0) {
printf("Argument error: Position values out of range\n");
return;
}
for(int i = from; i >= to; i--)
{
if((val & (1 << i))) {
// The ith digit is one
printf("%d",1);
}
else {
// The ith digit is zero
printf("%d",0);
}
}
}
void get_nbits(int num, int n)
{
if(n >= (sizeof(num) * 8)) {
printf("Argument error: The n must not exceed the bit count of num type which is: %lu\n", (sizeof(num) * 8));
return;
}
printf("The binary form of given number: ");
printBinary(num, n - 1, 0);
// No need to align since bits ranges to 0th bit
int decimal_num = num & ((1 << n) - 1);
printf("\nThe decimal number is: %d\n",decimal_num);
}
// Get bits from Most Significant Bit (from left to right)
void get_nbits_from_msb_pos(int num, int n, int pos)
{
if((pos - n) < 0) {
printf("Argument error: n from position should not underflow the bit position\n");
return;
}
int decimal_num = 0;
printf("The binary form of given number: ");
printBinary(num, pos, pos - (n - 1));
int mask = ((1 << (pos 1)) - 1); // Mask beyond the pos toward MSb
mask &= ~((1 << ((pos 1) - n)) - 1); // Mask below pos - n toward LSb
// Slice the num between the pos and n, and then align it to the right
// in order to get the correct value
decimal_num = ((num & mask) >> (pos - (n - 1)));
printf("\nThe decimal number is: %d\n",decimal_num);
}
int main(void) {
get_nbits(105, 4);
get_nbits_from_msb_pos(105, 4, 6);
return 0;
}