C puzzles [9-12]

Source: Internet
Author: User

Question 9

#include <stdio.h>int main(){        float f=0.0f;        int i;        for(i=0;i<10;i++)                f = f + 0.1f;        if(f == 1.0f)                printf("f is 1.0 \n");        else                printf("f is NOT 1.0\n");        return 0;}

Knowledge points:

  • Floating point register

Floating-point registers are part of FPU. The number and digits of floating point registers vary depending on the hardware architecture. The floating-point registers in the X86 architecture include:

1) Eight 80-bit data registers: fpr0 ~ Fpr7: the number of data registers determines the computer's computing accuracy. The more digits, the higher the computing accuracy;

2) Three 16-bit registers: one mark register, one control register, and one Status Register;

3) Two 48-bit registers: one instruction pointer and one Data Pointer.

FPU has its own set of commands for floating-point register operations. For data registers, the names of these eight registers cannot be directly used. These eight data registers are designed as the first and last stacks, ST (0) points to the top of the fprx stack.

  • Binary representation of floating point numbers in registers

References:

Http://www.ruanyifeng.com/blog/2010/06/ieee_floating-point_representation.html

Http://floating-point-gui.de/

Http://en.wikipedia.org/wiki/IEEE_754

Http://en.wikipedia.org/wiki/Floating_point

According to the International Standard IEEE 754, any binary floating point V can be expressed in the following form:

V = (-1) S x m x 2e

The following table lists the digits of S, M, and E:

Type

Total BITs

S

E

M

Exponent bias

Bits precision

Single

32

1

8

23

127

24

Double

64

1

11

52

1023

53

Double Extended

80

1

15

64

16383

64

M: 1 ≤ m ≤ 2, that is, m can always be expressed as 1. in the format of XXX, because the first digit of M is always 1, when m is expressed in the register, the first digit 1 is removed and only the fractional part is saved, thus saving one valid digit. Taking a 32-bit floating point number as an example, M occupies 23 digits, but the number of valid digits is 24.

E: Add a fixed value to e when storing the edata. For 32-bit floating point numbers, the fixed value is 127. For 64-bit floating point numbers, the fixed value is 1023. For more information about E, see the first reference link.

Example:

float x = 0.15625;

0.15625 in binary format: 0.00101

S = 0, E =-3, M = 1.01

The part in the register that stores e should be-3 + 127;

The M part in the register should be stored 01

Therefore, 0.15625 is represented in the register:

0 01111100 01000000000000000000000

Description:

Floating point numbers cannot be accurately expressed in the computer, indicating a tiny error between the value and the actual value. This error will be superimposed with addition and subtraction. Do not simply use ">" "<" "=" "! =.

For more information about how to compare floating point numbers, see

Http://www.cygnus-software.com/papers/comparingfloats/comparingfloats.htm

 

Question 10

#include <stdio.h>int main(){        int a = 1,2;        printf("a : %d\n",a);        return 0;}

Knowledge points:

  • Comma expression

The form of a comma expression is as follows:

(Expression 1, expression 2, expression 3 ,......, Expression N)

(1) The comma expression is calculated one by one from left to right;

(2) The comma expression acts as a whole, and its value is the value of the last expression;

(3) The comma operator has the lowest priority among all operators.

Questions

Because the comma operator has the lowest priority

int a = 1,2;

Equivalent

int (a = 1),2

The compilation is incorrect.

Should be changed:

int a = (1,2);

 

11th questions

#include <stdio.h>int main(){        int i=43;        printf("%d\n",printf("%d",printf("%d",i)));        return 0;}

Description:

The return value of printf is the number of printed characters. The description in Man 3 printf is as follows:

Upon successful return, these functions return the number of characters printed (not including the trailing “\0”used to end output to strings).

Therefore, the output of this program is: 4321

 

12th questions

  void duff(register char *to, register char *from, register int count)  {      register int n=(count+7)/8;      switch(count%8){      case 0: do{ *to++ = *from++;      case 7:  *to++ = *from++;      case 6: *to++ = *from++;      case 5: *to++ = *from++;      case 4: *to++ = *from++;      case 3: *to++ = *from++;      case 2: *to++ = *from++;      case 1: *to++ = *from++;              }while( --n >0);      }  }

Knowledge Point explanation

  • RegisterKeywords

The notification compiler puts the register variable "as much as possible" into the Register to speed up access to the variable. When common variables are stored in the memory, the access speed is equivalent to the memory speed. The register variables are stored in registers, and the access speed is equivalent to the CPU speed. Defining variables that require frequent cyclic access as the register type can improve the program running efficiency.

  • A ++Difference from ++

A ++: Get the address of a, load its value into the Register, and then increase the value of A in the memory;

++ A: Get the address of a, increase the value of A in memory, and load the value of a into the register.

  • CLanguage operator priority

For the C language computing priority, refer:

Http://www.slyar.com/blog/c-operator-priority.html

For * To ++, * and ++ operators of the same level, the combination direction is from right to left, so * To ++ = * (to ++ ), the procedure is as follows:

1. Get the value of to the Register;

2. Add 1 to the to value;

3. Take the value pointed to by the address in the register in step 1.

"* To ++ = * From ++;" means to copy a byte from the source address to the destination address, and move the original address and destination address to a byte.

  • Duff's device

For more information about Dafu devices, see:

Http://www.drdobbs.com/a-reusable-duff-device/184406208

The Duff device is an optimized Implementation of serial replication, which increases the program execution efficiency by reducing the number of cycles.

What method do you use to copy a piece of data from the source address to the target address?

Realm 1:

void my_copy_1(register char *to, register char *from, register int count){    while(count-- > 0)    {        *to++ = *from++;    }}

Comment: This code is concise and easy to understand, but the execution efficiency is not high. After each byte is copied, three additional actions are performed: 1. Jump to the starting point of the loop; 2. Change the value of count; 3. Compare the value of count with 0. The time consumed by these three additional actions is much longer than the time consumed by the copy action, and the code is a little too heavy.

Think about it. If you are a CPU, every time you copy a byte, you will check whether the value of count exceeded once. It would be nice if the CPU could be smoothly copied without interrupting ......

Realm 2:

void my_copy_2(register char *to, register char *from, register int count){    register int n_block = count/8;    register int n_left = count%8;            while (n_block-- > 0)        {        *to++ = *from++;        *to++ = *from++;        *to++ = *from++;        *to++ = *from++;        *to++ = *from++;        *to++ = *from++;        *to++ = *from++;        *to++ = *from++;    }    while (n_left-- > 0)    {        *to++ = *from;    }}

Comment: When copying a large data segment, it is the fastest way for the CPU to copy it all the time, but we have to check whether the copied data volume has exceeded the set value. It is obviously unnecessary to go back one step by one. You can still consider it when you look back at N branch. In the preceding procedure, set N to 8. Of course, you can set N to another value as needed.

The process of "fragmented data" in the above program is still using the old method of "One step by one". Is there a simpler way to process this data?

Realm 3:

void my_copy_3(register char *to, register char *from, register int count){    register int n_block = (count+7)/8;    int n_left = count%8;    switch (n_left)    {        case 0: do{*to++ = *from++;        case 7: *to++ = *from++;        case 6: *to++ = *from++;        case 5: *to++ = *from++;        case 4: *to++ = *from++;        case 3: *to++ = *from++;        case 2: *to++ = *from++;        case 1: *to++ = *from++;            } while(--n_block > 0);    }}

Comment: The above code first processes fragmented data, and then processes block data. Use the switch statement to jump to the corresponding case number based on the amount of fragmented data. If the number of fragmented data is 7, perform the assignment seven times one way, and assign the assignment six times one way, and so on ...... This method has the least number of comparative operations. The above serial replication method is called "Da fu device ".

Of course, we can also use macros to implement dual devices. The macros are defined as follows:

#define DUFF_DEVICE_8(aCount, aAction) do { int count_ = (aCount); int times_ = (count_ + 7) >> 3; switch (count_ & 7) { case 0: do{aAction; case 7: aAction; case 6: aAction; case 5: aAction; case 4: aAction; case 3: aAction; case 2: aAction; case 1: aAction;     } while(--times_ > 0); } }while (0)

Comment: num divided by 8 and num has two ways to get the remainder of 8: one is num/8, num % 8; the other is num> 3, num & 7. The latter method is more efficient.

C puzzles [9-12]

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.