250 likes | 363 Vues
This document explains the fundamentals of integer and character constants in C programming, including how to designate their bases (hexadecimal, octal, decimal) based on their prefixes. It covers important signed and unsigned behavior when initializing variables, as well as one’s and two’s complement arithmetic for character manipulation. Additionally, it delves into bitwise operations, such as left and right shifts, and highlights the significance of sign bits and bit manipulation techniques in managing signed and unsigned values. Essential examples demonstrate these concepts in practice.
E N D
Homework • Turn in HW2 tonight • HW3 is on-line already • Questions?
Base for Integer Constants • Designating the base for an integer constant • If constant begins with either: 0x It is Hex with a-f as Hex digits 0X It is Hex with A-F as Hex digits • Otherwise, if constant begins with 0 It is Octal • Otherwise, it is decimal 23 Decimal 23
Base for Character Constants • Designating the base for a character constant • If constant begins with either: ‘\x It is Hex with a-f as Hex digits ‘\X It is Hex with A-F as Hex digits • Otherwise, if constant begins with ‘\0 It is Octal • Otherwise, it is the ASCII code for a character ‘a’ ASCII code for lower case character a
Signed/Unsigned Constants • Constants are Signed by default! • Important when converted to 32 bits of significance • When sign bit (MSB) is equal to 0: 0x55 as a 32 bit quantity 0000 … 01010101 ‘\x55’ as a 32 bit quantity 0000 … 01010101 When sign bit (MSB) is equal to 1: 0xaa as a 32 bit quantity 0000 … 10101010 ‘\xaa’ as a 32 bit quantity 1111 … 10101010
What we’d expect to see! • C Source Code int i = 0x55; /* int set = to int constant */ int j = '\x55'; /* int set = to char constant */ printf("i= %x, j= %x\n", i, j); • Executes and prints as i= 55, j= 55
What Happened? • C Source code int i = 0xaa; /* int set = to int constant */ int j = '\xaa'; /* int set = to char constant */ printf("i= %x, j= %x\n", i, j); • Executes and prints: i= aa, j= ffffffaa
Signed (Default) Behavior • Careful mixing modes when initializing variables! int i = 0xaa; (= 000000aa) probably as intended int j = ‘\xaa’; (= ff ff ff aa) sign bit extension! Sign Bit Extension char 0 int 00000000 00000000 00000000 0 Sign Bit Extension char 1 int 11111111 11111111 11111111 1
Signed (Default) Behavior • Careful mixing modes when initializing variables! c = 0x23456789; (= ‘\x89’) truncates MSBs + int 00100011 01000101 01100111 10001001 - char 10001001 NOTE: char value is negative even though int was positive
Unsigned Behavior • C Source Code unsigned int i = 0xaa; unsigned int j = '\xaa'; printf("i= %x, j= %x\n", i, j); • Executes and prints as: i= aa, j= aa
One’s ComplementTwo’s Complement • One’s Complement Character Arithmetic ~ is the one’s complement operator ~ flips the value of each bit in the data All zeroes become one, All ones become zero ~’\xaa’ == ‘\x55’ ~10101010 == 01010101
One’s ComplementTwo’s Complement • Two’s Complement Character Arithmetic - is the two’s complement operator • flips the value of each bit in the data and adds 1 It creates the negative of the data value - ‘\x55’ == ‘\xab’ - 01010101 == 10101011
Two Special Case Values • char 0 (or zero of any length) -00000000 = 11111111 + 1 = 00000000 • char -27 (or -2n-1 for any length = n) -10000000 = 01111111 + 1 = 10000000
Bit Manipulation • Bitwise Operators: ~ unary not & and | or ^ xor (exclusive or) << leftshift >> rightshift • Operate on pair of bits of the input data values!
Binary Logic Tables AND OR & 0 1 | 0 1 NOT 0 0 0 0 0 1 ~ 1 0 1 1 1 1 0 1 XOR ADD 1 0 ^ 0 1 + 0 1 0 0 1 0 0 1 0 Carry 1 1 1 0 1 1
Bit Manipulation unsigned char n = ‘\xa6’; n 10100110 ~n 01011001 (1s complement: flip bits) n | ‘\x65’ 10100110 turn on bit in result if | 01100101 on in either operand 11100111
Bit Manipulations n & ‘\x65’ 10100110 turn on bit in result if & 01100101 on in both operands 00100100 n ^ ‘\x65’ 10100110 turn on bit in result if ^ 01100101 on in exactly 1 operand 11000011
Bit Manipulations (Left Shift) char n = ‘\x18’; 00011000 n << 1 00110000 shift 1 to left (like * 2) n << 2 01100000 shift 2 to left (like * 4) (MSBs disappear off left end) n can be either signed or unsigned – no difference Significance can be lost if data shifted too far left Left Shift 0
Bit Manipulations (Right Shift) unsigned char n = ‘\x18’; 00011000 n >> 1 00001100 shift 1 to right (like / 2) n >> 2 00000110 shift 2 to right (like / 4) (LSBs disappear off right end) Integer truncation of divide by 2n just like with / Unsigned Right Shift 0
Bit Manipulations (Right Shift) signed char n = ‘\xa5’; 10100101 n >>1 11010010 (bring in a 1 from the left) n >>2 11101001 (bring in two 1’s from left) The rule is to bring in a copy of the sign bit! • Bringing in extra copies of the sign bit from the left end is another form of "sign extension" Signed Right Shift
Bit Manipulations (Right Shift) • For a signed variable, negative value shifted right by 2 is still a negative value • ‘\xa5’ == 10100101 • ‘\xa5’ >> 2 == 11101001 == ‘\xe9’ • Same result as divide by 4 (22 = 4)
Bit Manipulations (Right Shift) • When right shifting a signed value: Different rounding results for positive vs negative Result stays negative – does not become positive 1>>1 = 0 Rounds down -(1>>1) = 0 Rounds down then applies minus (-1)>>1 = -1 Applies minus then rounds down -1>>1 = -1 Applies minus then rounds down • Rounding behavior not exactly same as /2
Converting Decimal to Binary • From 11710 get binary by halving the number successively (rounding down) and writing down the digit 1 when have an odd result, 0 when result is even (consider number itself the first result): 117 1 LSB 58 0 29 1 14 0 7 1 3 1 1 1 0 0 MSB • Read UP and add any leading 0’s: 01110101 = ‘\x75’
Unsigned Binary to Decimal • Treat each bit position n that contains a one as adding 2n to the value. Ignore zeros because they can’t add anything to the value. Bit 0 LSB 1 1 (= 20) Bit 1 0 0 Bit 2 1 4 (= 22) Bit 3 1 8 (= 23) Bit 4 0 0 Bit 5 1 32 (= 25) Bit 6 0 0 Bit 7 MSB 1 128 (= 27) Total 173
Signed Binary to Decimal • Treat each bit position n that contains a one as adding 2n to the value except treat the MSB as subtracting 2n. (Ignore zeros as before) Bit 0 LSB 1 1 (= 20) Bit 1 0 0 Bit 2 1 4 (= 22) Bit 3 1 8 (= 23) Bit 4 0 0 Bit 5 1 32 (= 25) Bit 6 0 0 Bit 7 MSB 1 -128 (= -27) Total -83
Converting Hex to Decimal • Treat each digit n as adding 16n to the value. Ignore zeros because they can’t add anything to the value. Digit 0 LSBs 0 0 Digit 1 2 32 (= 2 * 161) Digit 2 b 2816 (= 11 * 162) Digit 3 0 0 Digit 4 0 0 Digit 5 1 1048576 (= 1 * 165) Digit 6 0 0 Digit 7 MSBs 0 0 Total 1051424