The easy-to-ignore details in C language (third article)

Source: Internet
Author: User
Tags variadic

Foreword: The purpose of this article is to record the easy-to-ignore details in C language. I plan to take a little time every day to read and tidy, persist, today is the first, perhaps next month's today is the second one, next year's Today is the third? ...... I firmly believe that a good memory is inferior to bad writing. The third article, fight~ ...


First link: Easy to ignore in C language details (first article)

Second Link: Easy to ignore in C language Details (second article)


1,__attribute__ ((noreturn))

__ATTRIBUTE__ can set function properties, variable properties, and type properties. __attribute__ ((noreturn)) Sets the Function property, Noreturn notifies the compiler that the function never returns a value, and when it encounters a function that needs a return value but has not yet run to the return value, the property avoids the error message. For example:

void Test (); int main (void) {    int x;    scanf ("%d", &x);    if (x > 0)        Test ();    else        return 0;}
The above code prompts for warning during the compile phase: Warning:control reaches end of non-voidfunction. The warning is generated because the Test () function has no return value, so the main () function may not have a return value and the program does not know how to handle it.

void Test () __attribute__ ((noreturn));
Modifying the Declaration of test () to the above is equivalent to informing the compiler that the test () function never returns a value, and no warning is generated.

Note: (1)before and after the attribute underline input method is: shift+ minus (input two times),(2)__attribute__ Mechanism has many other uses, is the GNU C characteristic, proposed reads the relevant content time to summarize again, To achieve targeted.

2 . What is the problem with the following code if the compiler allocates memory to the variable in a way that decrements the memory address?

int i, a[10];    for (i = 0; I <=; i++)        a[i] = 0;

Parse: Array out of bounds, the program into a dead loop. The four bytes after the array A in memory are actually assigned to the reshape variable I, and the value for A[10] is 0, which actually sets the value of counter I to 0.


3, in the if/else structure, we should try to put the higher probability of true condition judgment in front, so as to improve the performance of the program. Switch efficiency is higher than if/else structure, even if the program does not need default processing, it should keep the statement default:break;


4, the correct method compared with the 0 value
(1) Comparison of Boolean variables and 0 values

The IF statement determines whether the conditional expression is true or false by converting its result to a temporary variable of type Boolean, instead of comparing its result directly to 0, or false if not equal to 0. Do not compare Boolean variables directly with True, 1,-1, 0, and so on.

BOOL Flag;  if (flag)  //indicates that flag is true  if (!flag)//indicates flag is false  
(2) Comparison of integer variables with 0 values
int value;  if (value = = 0)  if (value! = 0)  

(3) comparison of floating-point variables with 0 values

A computer represents a floating-point number (float or double) that has a precision limit. For floating-point numbers that exceed the precision limit, the computer truncates the number of decimal parts beyond their precision. Therefore, two floating-point numbers that are not equal may become equal in the computer. For example: float a = 10.222222225, B = 10.222222229, mathematically A and B are unequal, but they are equal in 32-bit computers. (Note: Float guarantees 6-bit valid digits, double and long double guarantees 10-bit significant digits) when programming against a real-world application, there is always a precision requirement, and a direct comparison of whether one floating-point number and another value (floating-point or integer) are equal (= =) or unequal (! = may not be able to meet the actual needs of the results, because the = = and! = Compare the accuracy of the operation is often higher than the accuracy required in the actual application.

You can use ">" and "<" directly for comparison between floating-point numbers and for comparison of floating-point numbers and integers. (A > B) &&! (A < b) is equivalent to the semantics of a = = B, so it is not recommended to judge whether floating-point numbers are equal or not.

#define EPSILON 1e-6  if (ABS (x-y) <= EPSILON)//x equals y  if (abs (x-y) > EPSILON)  //x not equal to Y    if (ABS (x) <= EPSILON)      //x equals 0  if (ABS (x) > EPSILON)       //x not equal to 0  

(4) comparison of pointer variables with 0 values

The 0 value of a pointer variable is a NULL value (NULL), which means that no object is pointed to. Although the value of NULL is the same as 0, the two have different meanings (different types).

if (p = = NULL)  

Note: The use of if (NULL = = p), if (= = i) This is better, because if you mistakenly write = =, because the compiler does not allow to assign a value to the constant, you can check the error.


5,va_list, Va_start (), Va_arg () and Va_end ()

The stdarg.h header file of the C standard function library defines the macros used by the Variadic function. Within a variadic function, you 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:

Here is a simple example:

#include <stdarg.h> #include <stdio.h>double average (int count, ...) {    va_list ap;    Int J;    Double tot = 0;    Va_start (AP, count);                The parameter for va_list points to the starting for    (j=0; j<count; j + +)        Tot+=va_arg (AP, double);        To retrieve the parameters, the type    va_end (AP) must be specified as required;                         Release va_list    return tot/count;} int main (void) {    double a[5] = {1, 0, 0, 0, 0};    printf ("%lf\n", average (5, a[0], a[1], a[2], a[3], a[4]));    return 0;}

Variable-parameter functions in C are not subject to length checking and type checking, and may overflow when passing too few parameters or inconsistent types.


6. Order of evaluation

There are only 4 operators (&&,| |,?: and,) in C that have a defined order of evaluation. && | | The left operand is evaluated first, and the right-hand operand is evaluated only when needed; for a? B:C, operand A is evaluated first, and then the value of the operand B or C is evaluated according to the value of A; for the comma operator, the left operand is evaluated first, then the value is "discarded", and the right operand is evaluated. For example:

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

The code above copying the first n elements from the array x to the array y is incorrect. Because the assignment operator does not guarantee any order of evaluation. The address of Y[i] will be evaluated before the self-increment of I is executed or after the evaluation is indeterminate.

Note: The precedence of operators is a completely different concept from the order of evaluation.


7, for the next element after the end of the array, take its address is legal, read the value of this element is undefined, and rarely C compiler can detect this error.

8, character array is not necessarily a string

An array of characters is an array of character variables, and the string is an array of characters with the ending character of ' \ S ' (ASCII value 0x00).

(1) for a character array, it does not care whether the middle or the end has a ' plus ' end character, because the array knows how many elements it has, and ' it ' is a legitimate element for it.

(2) if the character array does not have a ' \ s ' End flag, it may cause "memory access violation" or tamper with other memory units, strlen function results exception, etc. when used as a string. To give a simple example:

#include <stdio.h>int main (void) {    char arr1[] = {' A ', ' B ', ' n ', ' C ', ' d '};    Char arr2[] = "Hello";    Char *p = "Hello";    printf ("%d%d\n", sizeof (ARR1), strlen (arr1));      Results 5 2    printf ("%d%d\n", sizeof (ARR2), strlen (ARR2));      Results 6 5    printf ("%d%d\n", sizeof (p), strlen (p));            Results 4 5    return 0;}

9, do not use literal constants to initialize the reference

const int &a = 0;

Instead of initializing a reference to NULL, the above semantics creates a temporary int object and initializes it with the use of the order, and then initializes the reference a with it, and the temporary object will persist until the A is destroyed before it is destroyed.


10 . The creation and destruction of references does not invoke the constructors and destructors of the class. At the binary level, the reference is usually done by pointers, except that the compiler helped us with the conversion.

Easy-to-ignore details in the C language (third 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.