0

Below is a program in which I am trying to reset a particular bit of a hexadecimal number. The bit location, number of bits to reset, and hexadecimal value all are user inputs.

Header file

#pragma once

int bit0(int i,unsigned int RegA,unsigned int RegB,int s[]);

C file

#include "stdafx.h"
#include "stdio.h"
#include "conio.h"
#include "iostream"
#include "targetver.h"
#include "bit.h"

int bit0(int i,unsigned int RegA,unsigned int RegB,int s[])
{
    unsigned int j=0;
    unsigned int K=0;
    unsigned int L=0;

    printf("\nThe bit is at s[0] is %x\n", s[0]);   

    for (j=0; j<i; j++)
    {
        K = (1 << s[j]);
        L = ~K;
        RegB = RegA & ~L;
        printf("\nThe bit is %x\n", RegB);

        if (RegB | 0)
        {
            RegB = RegB & ~ (1 << s[j]);
        }
        else
        {
            RegB;
        }
    }

    printf("\nThe new reset bit is %x\n", RegB);

    _getch();
    return 0;
}

main file

#include "stdafx.h"
#include "stdio.h"
#include "conio.h"
#include "iostream"
#include "targetver.h"
#include "bit.h"

int main()
{
    int i=0;
    int j=0;
    int s[35]={0};
    unsigned int RegA = 0;
    unsigned int RegB = 0;

    printf("Enter the hexa decimal value to be reset ");
    scanf_s("%x", &RegA);
    printf("Entered hexa decimal value is %x ", RegA);

    printf("\nHow many decimal places needs to be reset (0-31) ?");
    scanf_s("%d", &i);

    printf("Enter the decimal places that needs to be reset ");

    for (j=0; j<i; j++)
    {
        scanf_s("%d", &s[j]);
    }

    ///// check the entered hex value on those decimals places as bit 0 or bit 1

    bit0(i,RegA,RegB,s);

    _getch();
    return 0;
} 

I am compiling and running executing the above code using Visual Studio.

The problem is in the C file, on the RegB = RegA & ~L; line. The AND operation seems not to be taking place because I am getting 0 as the RegB value.

Program input:

Enter the hexadecimal value to be reset : 0100 1111

Entered hexadecimal value is : 0100 1111

How many decimal places needs to be reset (0-31): 1

Enter the decimal places that needs to be reset : 1

John Bollinger
  • 160,171
  • 8
  • 81
  • 157
vikash23
  • 3
  • 2
  • 1
    Facetiously, 01001111 is an *octal* literal. – Bathsheba May 16 '17 at 14:57
  • 1
    @Bathsheba Which looks like binary, which is supposed to be hexadecimal. I call it a *total mess*. – Eugene Sh. May 16 '17 at 14:58
  • What's with `#include`ing `"iostream"`? This appears to be an attempt to include a C++ header into a C program. The program already includes `stdio.h`, as it should, so I don't see any point at all. – John Bollinger May 16 '17 at 15:06
  • There are no decimal places in a hex number. – stark May 16 '17 at 15:07
  • Anyway, I think VS has an integrated debugger. Have you considered using it? – John Bollinger May 16 '17 at 15:08
  • And clarification: "hexadecimal" is one word. My edit fixes that (among other things) in your prose, but on principle I have not modified anything about your code except insignificant whitespace. – John Bollinger May 16 '17 at 15:11
  • Check the values of RegA and ~L to be sure. Here's a quickie(gives me RegA=0x4F and ~L=0x2): L = ~K; printf("RegA: %X, ~L: %X", RegA, ~L); RegB = RegA & ~L; – kundrata May 16 '17 at 15:13
  • @kundrata I checked for the register values by having a break point in most of the places. i = 0x00000001 j = 0x00000000 k = 0x00000002 L = 0xfffffffd RegA = 0x01001111 RegB = 0x00000000 s = 0x00effa94 what I dont understand is why is the value of L is 0x00000002 and not 0x00000010. – vikash23 May 16 '17 at 15:16
  • 0x0002 = 0b0010. It's the same value: 2 in hexa means 10 in binary. – kundrata May 16 '17 at 15:21
  • @kundrata I am aware that 0x0002 is 0b0010. But why are that other values are represented in hexadecimal like for example L = 0xfffffffd but not the value of K. why I dont see K as 0X00000010 – vikash23 May 16 '17 at 15:23
  • When you shift(<<) the computer always shifts bits. It works in binary, not hexa. We just use hexa representation to make numbers easier to read. That's why they're called bitwise operations: shift, and/or etc. – kundrata May 16 '17 at 15:26
  • When you shift to the left, it's equivalent to multiplying by 2(to the power of how many places you shift). 0x01 << 1 = 0x02(1 * 2). And 0x01 << 4 = 0x10(1 * 16, 16 is 2 to the power 4). Hope you get it now. – kundrata May 16 '17 at 15:37

1 Answers1

0

Well of course you get 0, but that's because the & operations you have written are (all) being performed. Here's the relevant section of your code:

    K = (1 << s[j]);
    L = ~K;
    RegB = RegA & ~L;
    printf("\nThe bit is %x\n", RegB);

    if (RegB | 0)
    {
        RegB = RegB & ~ (1 << s[j]);
    }
    else
    {
        RegB;
    }

Before we continue, though, there are quite a few opportunities to simplify:

  • variable L just complicates things for me; I'd rather just see ~K
  • RegB | 0 is eqivalent to simply RegB
  • the else block does nothing
  • the if block can safely be executed unconditionally, in the sense that nothing will change if it is executed when the given condition is false.
  • Although you have set K = (1 << s[j]) and do not afterward change it, you later repeat yourself by using the expression (1 << s[j]) instead of just saying K.
  • the printf() may have some utility for debugging, but it slightly obscures the details of the computation

This equivalent code will be easier to reason about:

    K = (1 << s[j]);
    RegB = RegA & K;
    RegB = RegB & ~K;

And at that point the problem should be crystal clear: no matter what the value of RegA is, as long as s[j] is between 0 and 30,* you compute RegB by first masking off some of RegA's bits, and then masking off the remaining ones. Naturally, the result is always 0.

*Because 1 is a signed integer constant, if the implementation's ints are 32 bits wide, left-shifting by 31 places produces an out-of-range result. As far as the standard is concerned, the resulting behavior is undefined. It would be better to avoid this issue by using an unsigned constant, i.e. 1U.

John Bollinger
  • 160,171
  • 8
  • 81
  • 157
  • I performed your equivalent code. Still the execution of RegB = RegA & K; and RegB = RegB & ~K; not taking place. I set a breakpoint and verified it. When the breakpoint is currently at if (RegB | 0) the register values are as follows i = 0x00000001 J = 0x00000000 K = 0x00000002 L = 0x00000000 RegA = 0x01001111 RegB = 0x00000000 S = 0x006ff700{0x00000001} – vikash23 May 17 '17 at 08:48
  • @vikash23, it's unclear what you think you've determined from running your code or my equivalent alternative in a debugger, but if you're running mine at all then it seems you've misunderstood my entire point. I'm trying to tell you that **the result of the computation you have implemented is *always* zero**. That the program in fact computes that result shows that the operations involved *are* being performed. You have implemented a different computation than the one you were tasked with, and the computer is flawlessly executing what you told it to do. – John Bollinger May 17 '17 at 12:53