Download presentation
Presentation is loading. Please wait.
Published byCuthbert Ferguson Modified over 9 years ago
1
סיביות קרן כליף
2
© Keren Kalif 2 ביחידה זו נלמד: מוטיבציה אופרטורים לעבודה עם סיביות: & | ^ ~ >> <<
3
© Keren Kalif 3 מוטיבציה כל משתנה בזכרון מיוצג ע"י כמה תאים, ובפרט ע"י אוסף של סיביות עד היום עבדנו עם משתנים, ללא יכולת לפנות לסיביות המרכיבות אותם מוטיבציה: דחיסה: אם רוצים לשמור טקסט באנגלית, יספיקו לנו רק כ- 30 תווים: האותיות וסימני הפיסוק. בפועל עבור כל תו נשמור 8 סיביות (255 קומבינציות). ע"י דחיסה נוכל לשמור עבור כל תו רק 5 סיביות. חסכון של כ- 35%! הצפנה: ניתן להחליט על החלפה כלשהי בסדר הסיביות, שתהייה ידועה רק לנו או למי שאמור לפענח את המידע
4
© Keren Kalif 4 פעולות על סיביות נסתכל על התוכנית הבאה, וכיצד יראה ה- byte שיכיל את הנתון: void main() { char ch = ‘a'; { פעולות שניתן לבצע עם סיביות: & AND | OR ^ XOR ~ NOT >> Left Shift << Rigtt Shift פעולות על סיביות ניתן לבצע על משתנים מטיפוסים המכילים שלמים בלבד (char, int, short, long) 0 1 1 0 0 0 0 1
5
© Keren Kalif 5 הפעולה & (AND) 1. void printCharAsBinary(char ch) {…} 2. 3. void main() 4. { 5. char ch1 = 'a', ch2 = 'b', ch3 = ch1&ch2; 6. 7. printf("ch1=%c: ", ch1); 8. printCharAsBinary(ch1); 9. 10. printf("\nch2=%c: ", ch2); 11. printCharAsBinary(ch2); 12. 13. printf("\nch3=%c: ", ch3); 14. printCharAsBinary(ch3); 15. printf("\n"); 16. } הפעולה & בין שני משתנים עושה את הפעולה & על כל זוג סיביות במשתנים. אם שניהם 1, גם התוצאה תהיה 1, אחרת 0. & עם 0 "מכבה" ביט מסוים & עם 1 משאיר את הביט ללא שינוי
6
© Keren Kalif 6 הפעולה | (OR) 1. void printCharAsBinary(char ch) {…} 2. 3. void main() 4. { 5. char ch1 = 'a', ch2 = 'b', ch3 = ch1|ch2; 6. 7. printf("ch1=%c: ", ch1); 8. printCharAsBinary(ch1); 9. 10. printf("\nch2=%c: ", ch2); 11. printCharAsBinary(ch2); 12. 13. printf("\nch3=%c: ", ch3); 14. printCharAsBinary(ch3); 15. printf("\n"); 16. } הפעולה | בין שני משתנים עושה את הפעולה | על כל זוג סיביות במשתנים. אם לפחות אחד מהם 1, גם התוצאה תהיה 1, אחרת 0. | עם 1 "מדליק" ביט מסוים | עם 0 משאיר את הביט ללא שינוי
7
© Keren Kalif 7 הפעולה ^ (XOR) 1. void printCharAsBinary(char ch) {…} 2. 3. void main() 4. { 5. char ch1 = 'a', ch2 = 'b', ch3 = ch1^ch2; 6. 7. printf("ch1=%c: ", ch1); 8. printCharAsBinary(ch1); 9. 10. printf("\nch2=%c: ", ch2); 11. printCharAsBinary(ch2); 12. 13. printf("\nch3=%c: ", ch3); 14. printCharAsBinary(ch3); 15. printf("\n"); 16. } הפעולה ^ בין שני משתנים עושה את הפעולה ^ על כל זוג סיביות במשתנים. אם בדיוק אחד מהם 1, גם התוצאה תהיה 1, אחרת 0. ^ עם 1 הופך את הביט ^ עם 0 משאיר את הביט ללא שינוי ^ עם עצמו מאפס את המשתנה
8
© Keren Kalif 8 הפעולה >> (Shift Left) 1. void printCharAsBinary(char ch) {…} 2. 3. void main() 4. { 5. char ch1 = 'a', ch2 = ch1 << 1; 6. 7. printf("ch1=%c: ", ch1); 8. printCharAsBinary(ch1); 9. 10. printf("\nch2=%c: ", ch2); 11. printCharAsBinary(ch2); 12. 13. printf("\n"); 14. } הפעולה >> מזיזה את הסיביות במשתנה n פעמים שמאלה, ומוסיפה n אפסים מימין
9
© Keren Kalif 9 הפעולה << (Shift Right) על משתנים שהם signed 1. void printCharAsBinary(char ch) {…} 2. void main() 3. { 4. char ch1 = 'a', ch2 = ch1 >> 1; 5. char ch3 = 128, ch4 = ch3 >> 2; 6. 7. printf("ch1=%c: ", ch1); 8. printCharAsBinary(ch1); 9. 10. printf("\nch2=%c: ", ch2); 11. printCharAsBinary(ch2); 12. 13. printf("\nch3=%c: ", ch3); 14. printCharAsBinary(ch3); 15. 16. printf("\nch4=%c: ", ch4); 17. printCharAsBinary(ch4); 18. printf("\n"); 19. } הפעולה << מזיזה את הסיביות במשתנה n פעמים ימינה, ומוסיפה n פעמים את הביט הכי שמאלי (כאשר המשתנה signed)
10
© Keren Kalif 10 הפעולה << (Shift Right) על משתנים שהם unsigned 1. void printCharAsBinary(char ch) {…} 2. void main() 3. { 4. char ch1 = 'a', ch2 = ch1 >> 1; 5. unsigned char ch3 = 128, ch4 = ch3 >> 2; 6. 7. printf("ch1=%c: ", ch1); 8. printCharAsBinary(ch1); 9. 10. printf("\nch2=%c: ", ch2); 11. printCharAsBinary(ch2); 12. 13. printf("\nch3=%c: ", ch3); 14. printCharAsBinary(ch3); 15. 16. printf("\nch4=%c: ", ch4); 17. printCharAsBinary(ch4); 18. printf("\n"); 19. } הפעולה << מזיזה את הסיביות במשתנה n פעמים ימינה, ומוסיפה n פעמים 0'ים מימין (כאשר המשתנה unsigned)
11
© Keren Kalif 11 שימושים לפעולות בסיסיות עם סיביות הכפלת מספר פי 2: shift left פעם אחת חילוק מספר פי 2: shift rightפעם אחת void main() } char num1 = 17, num2 = num1 > 1; printf("num1 in binary: "); printCharAsBinary(num1); printf(“\nnum2 in binary: "); printCharAsBinary(num2); printf(“\nnum3 in binary: "); printCharAsBinary(num3); printf(“\nnum1=%d, num2=%d, num3=%d\n", num1, num2, num3); {
12
© Keren Kalif 12 void printCharAsBinary(char ch) { int i; unsigned char temp; for ( ; ; ) } temp = ch << i; temp = temp >> 7; printf("%d", temp); { { 0 1 1 0 0 0 0 1 מימוש הפונקציה printCharAsBinary בכל איטרציה מבודדים את הביט ה- i שמשמאל i=0i < 8i++ ch = ‘a’ 97 0 1 1 0 0 0 0 1 temp 0 0 0 0 0 0 0 0 i = 0 printed to screen: 0 i = 1 1 1 0 0 0 0 1 00 0 0 0 0 0 0 1 1 i = 2 1 0 0 0 0 1 0 00 0 0 0 0 0 0 1 1 i = 3 0 0 0 0 1 0 0 0 0 0 0 0 0
13
© Keren Kalif 13 קבלת הביט במיקום ה- i (משמאל) 1. int getBitFromLeft(unsigned char ch, int index) 2. { 3. unsigned char temp = ch << index; 4. temp >>= 7; 5. return temp; 6. { 7. 8. void main() 9. } 10. char ch1 = 'a'; 11. int i; 12. 13. printf("ch1=%c: ", ch1); 14. printCharAsBinary(ch1); 15. 16. printf("\n"); 17. for (i=0 ; i < 8 ; i++) 18. printf("the %d bit: %d\n", i, getBitFromLeft(ch1, i)); 19. { ch = ‘a’ 97 0 1 1 0 0 0 0 1 temp 1 0 0 0 0 1 0 0 index = 2 0 0 0 0 0 0 0 1
14
© Keren Kalif 14 קבלת הביט במיקום ה- i (מימין) בעזרת מסיכה int getBitFromRight(unsigned char ch, int index) { unsigned char mask = 1; // 00000001 mask = mask << index; if (ch & mask == 0) return 0; else return 1; { ch = ‘a’ 97 0 1 1 0 0 0 0 1 mask index = 5 0 0 0 0 0 0 0 10 0 1 0 0 0 0 0
15
© Keren Kalif 15 השמת ערך בביט ה- i (מימין) char setBitFromRight(unsigned char ch, int index, int value) { unsigned char mask = 1; // 00000001 unsigned char result; mask <<= index; if (value == 1) result = ch | mask; else } mask = ~mask; result = ch & mask; { return result ; { ch = ‘a’ 97 0 1 1 0 0 0 0 1 mask index = 5 0 0 0 0 0 0 0 1 0 1 0 0 0 0 0 1 value = 0 0 0 1 0 0 0 0 01 1 0 1 1 1 1 1 result
16
© Keren Kalif 16 השמת ערך בביט ה- i (מימין) char setBitFromRight(unsigned char ch, int index, int value) { unsigned char mask = 1; // 00000001 unsigned char result; mask <<= index; if (value == 1) result = ch | mask; else } mask = ~mask; result = ch & mask; { return result ; { ch = ‘a’ 97 0 1 1 0 0 0 0 1 mask index = 4 0 0 0 0 0 0 0 1 0 1 1 1 0 0 0 1 value = 1 0 0 0 1 0 0 0 0 result
17
© Keren Kalif 17 מימוש הפונקציה swap void swap(int* x, int* y) } *x = *x ^ *y; *y = *x ^ *y; *x = *x ^ *y; { void main() } int x = 3, y = 5; printf("Before swap: x=%d, y=%d\n", x, y); swap(&x, &y); printf("After swap: x=%d, y=%d\n", x, y); { x 0 0 0 0 0 0 1 1 y 0 0 0 0 0 1 0 1 0 0 0 0 0 1 1 0 0 0 0 0 0 0 1 1 0 0 0 0 0 1 0 1
18
© Keren Kalif 18 הוכחה לפונקציה swap void swap(int* x, int* y) } *x = *x ^ *y; *y = *x ^ *y; *x = *x ^ *y; { הערך החדשהפעולההמשתנה המקורי YXYX YX ^ YX = X ^ YYX Y = (X ^ Y) ^ Y = X ^ (Y ^ Y) = X ^ 0 = X X ^ YY = X ^ YYX ^ Y XX = (X ^ Y)s ^ X) = Y ^ X ^ X = Y ^ 0 = Y X = X ^ YXX ^ Y
19
© Keren Kalif 19 מימוש גנרי לפונקציה swap 1. void swap(void* a, void* b, int typeSize) 2. { 3. int i; 4. char* first = (char*)a; 5. char* second = (char*)b; 6. for (i=0 ; i < typeSize ; i++) 7. } 8. *(first+i) = *(first+i) ^ *(second+i); 9. *(second+i) = *(first+i) ^ *(second+i); 10. *(first+i) = *(first+i) ^ *(second+i); 11. { 12. { 13. void main() 14. } 15. int x = 331, y = 54295; 16. char str1[4]="hi", str2[4]="bye"; 17. 18. printf("Before: x=%d, y=%d\n", x, y); 19. swap(&x, &y, sizeof(int)); 20. printf("After: x=%d, y=%d\n", x, y); 21. printf("\nBefore: str1=%s, str2=%s\n", str1, str2); 22. swap(str1, str2, sizeof(str1)); 23. printf(“After: str1=%s, str2=%s\n", str1, str2); 24. {
20
© Keren Kalif 20 דוגמא פשוטה להצפנת ופיענוח טקסט 1. void encryptDecrypt(char str[]) 2. { 3. while (*str != '\0') 4. } 5. *str ^= 255; 6. str++; 7. { 8. { 9. 10. void main() 11. } 12. char str[] = "ma katoov po?"; 13. 14. printf("Text before encryption: |%s|\n", str); 15. encryptDecrypt(str); 16. printf("Text after encryption: |%s|\n", str); 17. encryptDecrypt(str); 18. printf("Text after decryption: |%s|\n", str); 19. { תזכורת: XOR עם 1 הופכת את סיביות המשתנה
21
© Keren Kalif 21 דוגמא כתוב פונקציה המקבלת שם של קובץ בינארי וכמות כלשהי של מספרים, שנתון שסכומם הוא 8 (המספר האחרון יהיה 0, ליצוג סיום הפרמטרים) כל מספר מייצג כמות סיביות המייצגות מספר. יש לקרוא את הקובץ הבינארי ולהציג את המספרים המקודדים בתוכו. למשל, עבור המספרים 4,1,3 והבתים הבאים שנקראו מהזכרון (abc): 0 1 1 0 0 0 0 1 0 1 1 0 0 0 1 0 0 1 1 0 0 0 1 1 יודפסו למסך המספרים הבאים:
22
© Keren Kalif 22 זכרו! http://funny-stuff.audio4fun.com/download/funnypixstore/10796.jpg
23
© Keren Kalif 23 1. #include 2. #include 3. #include 4. #include 5. 6. unsigned char createMask(int high, int low); 7. int getSubNumber(char ch, unsigned char mask, int high, int low); 8. void readNumbers(const char* fileName,...); 9. 10. void main() 11. { 12. char str[] = "abc"; // a: 01100001 b: 01100010 c: 01100011 13. FILE* f = fopen("test.bin", "wb"); 14. fwrite(str, sizeof(char), strlen(str), f); 15. fclose(f); 16. 17. readNumbers("test.bin", 4, 1, 3, 0); 18. {
24
© Keren Kalif /* This function receives higher and lower bounds of bit indexes, and creates a mask with 1 in this range, and 0 in all other places. I.E: high=5, low=3, the mask char would be: 00111000 */ 19. unsigned char createMask(int high, int low) 20. { 21. return ( 1 << ( high + 1 ) ) - ( 1 << low ); 22. { © Keren Kalif 24 6 >> 1 1000000 64 3 >> 1 1000 8 56=64-8 00111000 מוזמנים לקרוא את ההסבר לפונקציה זו בדפים שבאתר!
25
© Keren Kalif 25 28. void readNumbers(const char* fileName,...) 29. { 30. FILE* f; 31. va_list numbers; 32. int highBit, lowBit, i, numOfNumbers=0, arr[8]; 33. unsigned char ch; 34. unsigned char* masks; 35. 36. f = fopen(fileName, "rb"); 37. if (f == NULL) 38. exit(1); 39. 40. // get the numbers 41. va_start(numbers, fileName); 42. arr[numOfNumbers] = va_arg(numbers, int); 43. while (arr[numOfNumbers] != 0) 44. } 45. numOfNumbers++; 46. arr[numOfNumbers] = va_arg(numbers, int); 47. { 48. 49. // allocate the masks array 50. masks = (char*)malloc(numOfNumbers*sizeof(unsigned char));
26
© Keren Kalif 26 51. // creates the masks 52. highBit=7; 53. for (i=0 ; i < numOfNumbers ; i++) 54. } 55. lowBit = highBit - arr[i] + 1; 56. masks[i] = createMask(highBit, lowBit); 57. highBit = lowBit - 1; 58. } 59. while (1) 60. } 61. fread(&ch, sizeof(char), 1, f); 62. if (feof(f))break; 63. printf("From char '%c' --> ", ch); 64. highBit=7; 65. for (i=0 ; i < numOfNumbers ; i++) 66. { 67. lowBit = highBit - arr[i] + 1; 68. printf("%d ", ((ch & masks[i]) >> lowBit)); 69. highBit = lowBit - 1; 70. } 71. printf("\n"); 72. { 73. fclose(f); 74. free(masks); 75. {
27
© Keren Kalif 27 דוגמא 1: יצירת קובץ בינארי המכיל קידוד תמונה יש לייצר קובץ בינארי המכיל יצוג של תמונה. תמונה מורכבת מ- M*N פיקסלים, כך שלכל פיקסל יש צבע (יש 16 צבעים אפשריים). יש לכתוב לקובץ את מימדי התמונה ואח"כ את כל הפיקסלים לפי הסדר: הפיקסלים מהשורה הראשונה, השניה וכו'. על מנת לשמור כל צבע, ניתן להסתפק ב- 4 סיביות בכל byte ניתן לשמור נתונים עבור 2 פיקסלים תמונה עם M*N פיקסלים תשמר ב- N*M/2 + 2 בתים 2 בתים בהתחלה לשמירת מימדי התמונה
28
© Keren Kalif 28 דוגמא 2: שינוי צבע לפיקסל מסוים בתמונה יש לתת קאורדינטת x,y וצבע, ובגישה ישירה לעדכן את הפיקסל. יש לשים לב האם הצבע עבור הקאורדינטה המבוקשת נמצא בצד הימני אא בצד השמאלי של ה- byte בו הוא נשמר
29
© Keren Kalif 29 ביחידה זו למדנו: מוטיבציה אופרטורים לעבודה עם סיביות: & | ^ ~ >> <<
30
© Keren Kalif 30 תרגיל
Similar presentations
© 2025 SlidePlayer.com. Inc.
All rights reserved.