Details easily overlooked in C Language (part 3)

Source: Internet
Author: User

Details easily overlooked in C Language (part 3)

Preface:The purpose of this article is to record the details that are easy to ignore in the C language. I plan to take some time every day to read books and stick to it. Today is the first article, maybe next month's today is the second article, and next year's today is the first article ?...... I firmly believe that good memory is not as bad as writing. Article 3, fight ~...


Article 1: details easily overlooked in C language (article 1)

Link to article 2: details easily overlooked in C language (article 2)


1,_ Attribute _ (noreturn ))

_ Attribute _ function attributes, variable attributes, and type attributes can be set. _ Attribute _ (noreturn) sets the function attribute. noreturn notifies the compiler function to never return a value. When a function needs to return a value but has not yet run it to the return value, it is returned, this attribute can avoid errors. For example:
void Test ();
int main (void)
{
    int x;
    scanf ("% d", & x);

    if (x> 0)
        Test ();
    else
        return 0;
}
The above code prompts a warning during the compilation phase: warning: control reaches end of non-voidfunction. The reason for the warning is that the Test () function has no return value, so the main () function may have no return value, and the program does not know how to deal with it.
void Test () __attribute __ ((noreturn));
If you modify the declaration of Test () to the above, it is equivalent to telling the compiler that the Test () function never returns a value, and no warning is generated.
Note: (1) The underscore input method before and after attribute is: Shift + minus sign (enter twice); (2) The __attribute__ mechanism has many other uses, which is a feature of GNU C. It is recommended to summarize and do when you read the relevant content. To be targeted.

2. If the compiler allocates memory to variables in a decreasing memory address, what is wrong with the following code?
int i, a [10];
    for (i = 0; i <= 10; i ++)
        a [i] = 0;
Analysis: The array crosses the boundary, and the program falls into an infinite loop. The four bytes after the array a in the memory are actually allocated to the integer variable i. Assigning 0 to a [10] actually sets the value of the counter i to 0.


3. In the if / else structure, try to put the condition judgment with a higher probability of TRUE as the front, so that the performance of the program can be improved. The efficiency of switch is higher than if / else structure, even if the program really does not require default processing, the statement default: break should be retained;


4. The correct way to compare with zero value
(1) Comparison of Boolean variable and zero value
The if statement determines whether the conditional expression is true or not by converting its calculation result into a Boolean temporary variable, but directly comparing its result with 0. If it is not equal to 0, it means true, otherwise it is false . Do not directly compare Boolean variables with true, 1, -1, 0, etc.

bool flag;
if (flag) // Indicates that the flag is true
if (! flag) // The flag is false
(2) Comparison of integer variable and zero value
int value;
if (value == 0)
if (value! = 0)
(3) Comparison of floating-point variables and zero values

Computers indicate that floating-point numbers (float or double) have a precision limit. For floating-point numbers that exceed the precision limit, the computer truncates the fractional part beyond their precision. Therefore, two floating-point numbers that were originally unequal may become equal in the computer. For example: float a = 10.222222225, b = 10.222222229; mathematically a and b are not equal, but they are equal in 32-bit computers. (Note: float can guarantee 6 significant digits, double and long double can guarantee 10 significant digits) When programming for the actual application environment, there is always a precision requirement, and directly compare a floating point number with another value (floating point number Or integer) whether they are equal (==) or unequal (! =) May not get the results that meet the actual needs, because the precision of the == and! = Comparison operations is often higher than the precision required in practical applications.

">" And "<" can be used directly for comparison between floating point numbers and comparison between floating point numbers and integers. ! (a> b) &&! (a <b) is equivalent to a == b, so it is not recommended for judging whether floating-point numbers are equal or not.

#define EPSILON 1e-6
if (abs (x-y) <= EPSILON) // x is equal to y
if (abs (x-y)> EPSILON) // x is not equal to y
  
if (abs (x) <= EPSILON) // x is equal to 0
if (abs (x)> EPSILON) // x is not equal to 0
(4) Comparison of pointer variable and zero value

The zero value of the pointer variable is "null value" (denoted as NULL), that is, it does not point to any object. Although the value of NULL is the same as 0, the two have different meanings (different types).

if (p == NULL)
if (p! = NULL)
Note: It is better to use if (NULL == p), if (100 == i), because if you mistakenly write == as =, because the compiler does not allow assignment of constants, you can check for errors.


5, va_list, va_start (), va_arg () and va_end ()

The stdarg.h header file of the C standard function library defines macros used by variable parameter functions. The variable parameter function must define a va_list variable, and then use the macro va_start, va_arg and va_end to read. The relevant definitions are as follows:

typedef char * va_list;
void va_start (va_list ap, prev_param); / * ANSI version * /
type va_arg (va_list ap, type);
void va_end (va_list ap);
A simple example is as follows:

#include
#include

double average (int count, ...)
{
    va_list ap;
    int j;
    double tot = 0;
    va_start (ap, count); // Make va_list point to the starting parameter
    for (j = 0; j
The variable parameter function in C language does not have length check and type check, and may overflow when there are too few parameters or inconsistent types.






6. Evaluation order


There are only 4 operators (&&, ||,?: And,) in the C language with a prescribed evaluation order. && and || first evaluate the left operand, only evaluate the right operand when needed; for a? B: c, the operand a is evaluated first, then the operand b is evaluated according to the value of a Or the value of c; for the comma operator, the left operand is evaluated first, then the value is "discarded", and then the right operand is evaluated. E.g:



i = 0;
while (i <n)
    y [i] = x [i ++];


The above code to copy the first n elements from array x to array y is incorrect. Because the assignment operator does not guarantee any order of evaluation. It is uncertain whether the address of y [i] will be evaluated before i's increment operation or after it is evaluated.


Note: Operator precedence and evaluation order are completely different concepts.




7. For the next element after the end of the array, it is legal to take its address. The result of reading the value of this element is undefined, and few C compilers can detect this error.



8. The character array is not necessarily a string


A character array is an array whose elements are character variables, and a character string is a character array whose ‘\ 0’ (ASCII code value is 0x00) ends.


(1) For a character array, it does not care whether there is a ‘\ 0’ end character in the middle or at the end, because the array knows how many elements it has, and ‘\ 0’ is a legal element for it.



(2) If there is no "\ 0" end mark in the character array, but it is used as a character string, it may cause "memory access conflict" or tampering with other memory units, and the result of the strlen function is abnormal. To give a simple example:


#include

int main (void)
{
    char arr1 [] = {'a', 'b', '\ 0', 'c', 'd'};
    char arr2 [] = "Hello";
    char * p = "Hello";

    printf ("% d% d \ n", sizeof (arr1), strlen (arr1)); // Result 5 2
    printf ("% d% d \ n", sizeof (arr2), strlen (arr2)); // Result 6 5
    printf ("% d% d \ n", sizeof (p), strlen (p)); // Result 4 5
    return 0;
}


9. Don't use literal constants to initialize references


const int & a = 0;

The above semantics is not to initialize the reference to NULL, but to create a temporary int object and initialize it with 0, and then use it to initialize the reference a, and the temporary object will be retained until a is destroyed.






10. The creation and destruction of references does not call the class constructor and destructor. At the binary level, quoting is generally achieved through pointers, but the compiler has done the conversion for us.

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.