The corner of C language (ii)-You don't necessarily know C language features

Source: Internet
Author: User

Before writing a C language corner, introduced some C in some of the very features (http://blog.csdn.net/yang_yulei/article/details/34557625), recently collated some corner of the knowledge, particularly open this article.


Case in the switch statement

(case keywords can be placed in if-else or in a loop)

Switch (a) {case    1:;      // ...      if (b==2)      {case        2:;        // ...      }      Else Case 3:      {        //...        for (b=0;b<10;b++)        {case          5:;          // ...        }      }      break;     Case 4:}


Specify initialization (C99)

Before C99, you can only initialize a struct in order. In C99 you can do this:
struct Foo {
int x;
int y;
int z;
};
Foo foo = {. z = 3,. x = 5};


This code first initializes the FOO.Z, and then initializes the foo.x. The FOO.Y is not initialized, so it is set to 0.
This syntax can also be used in arrays. The following three lines of code are equivalent:
int a[5] = {[1] = 2, [4] = 5};
int a[] = {[1] = 2, [4] = 5};
int a[5] = {0, 2, 0, 0, 5};



restricted pointers (C99)  

The keyword restrict is only useful for pointers, and modifies the pointer to indicate that you want to modify the contents of the data area pointed to by this pointer, which is only possible through this pointer, which is what this keyword does to enable the compiler to optimize code and generate more efficient assembly code.

For example:

int foo (int* x, int* y) {    *x = 0;    *y = 1;    return *x;}

It is obvious that the return value of function foo () is 0 unless the values of parameter x and Y are the same. As you can imagine, 99% of the time the function will return 0 instead of 1. However, the compiler must ensure that 100% of the correct code is generated, so the compiler cannot replace the original code with the following better version:

int f (int* x, int* y) {    *x = 0;    *y = 1;    return 0;}

Now that we have the Restrict keyword, we can use it to help the compiler secure code optimization, since pointer x is the only way to modify *x, and compile to confirm "*y=1;" This line of code does not modify the contents of the *x, so it can be safely optimized:

int f (int *restrict x, int *restrict y) {    *x = 0;    *y = 1;    return 0;}

Many C library functions use the Restrict keyword:

void *memcpy (void * Restrict dest, const void * Restrict src,sizi_t N) This is a useful memory copy function, because the two parameters are restrict-qualified, so the two regions cannot overlap, that is, the de The area that the St pointer refers to cannot be modified by another pointer, that is, the SRC pointer cannot be modified. The corresponding function memmove (void *dest,const void * src,size_t) can overlap.


Static array index (C99)

void f (int a[static]) {
/* ... */
}
you assure the compiler that the pointer you pass to F points to the first element of an array with at least 10 elements of type int . I guess this is also for optimization; for example, the compiler will assume that a is not empty. The compiler also warns you when you try to pass in a pointer that can be statically determined to be null or if an array is too small.


void f (int a[const]) {
/* ... */
}
You cannot modify pointer a., which is the same as the descriptor int * Const A. However, when you combine the static use mentioned in the previous paragraph, for example in int a[static Const 10], you can get something that you can't get using the pointer style.


Multi-character constants

int x = ' ABCD ';
This will set the value of X to 0x41424344 (or 0x44434241, depending on the size of the end) on our general small-end machine, low-endian, DCBA in turn from low to high-byte arrangement.

It's just a pretty cool way of writing, and it's generally useless.

About EOF

EOF is a beginner is more confused about a thing, not uncommon knowledge points, but easy to cause misunderstanding, error, so here also summed up.


EOF is an abbreviation for the end of file that represents the end of a text stream (stream). The "text stream" here can be either a file or a standard input (stdin).
For example, the following code indicates that, if it is not the end of the file, the contents of the file are copied to the screen.

int C;while ((c = fgetc (FP))! = EOF) {Putchar (c);}
Naturally, I thought, at the end of each file, there is a special character called EOF, which reads to this character and the operating system thinks the file is over.
However, later I found that EOF is not a special character, but a constant defined in the header file stdio.h, which is generally equal to-1.

If EOF is a special character, it can be assumed that each text file has an EOF (that is, 1) at the end, because the ASCII code corresponding to the text is positive and cannot have negative values. But what about binary files? What do you do with the 1 inside the file?
This question let me think for a long time, later looked up the data to know, in the Linux system, EOF is not a character at all, but a signal value returned when the system reads to the end of the file(i.e.-1). As for how the system knows the end of the file, it says by comparing the length of the file. (file length recorded in the system's file allocation table)

There is a problem with this writing. fgetc () returns EOF not only when the end of the file is encountered, but also when an error occurs。 Therefore, the C language also provides the feof () function, which is used to ensure that the end of the file is indeed. The Code feof () version above is written as follows:
int C;while (!feof (FP)) {    c = fgetc (FP);    Do something;}
However, there are also problems with this writing. fgetc () after reading the last character of the file, the C feof () function still returns 0, indicating that the end of the file is not reached; only if FGETC () reads a character backwards (that is, over the last character), feof () returns a non-0 value indicating the end of the file

So, in this way, if a file contains n characters, then the internal operation of the while loop runs n+1 times. So the safest way to do this is as follows:
int C; while ((c = fgetc (FP))! = EOF) {do    something;} if (feof (FP)) {    printf ("\ n End of file reached."),} else {printf ("\ n Something went wrong.");}

In addition to representing the end of a file, EOF can also represent the end of a standard input.
However, the standard input is not the same as the file, the length of the input cannot be known beforehand, and a character must be entered manually to indicate that EOF is reached.

Linux, at the beginning of a new line, press ctrl-d, which represents EOF (if you press ctrl-d in the middle of a row, the output "standard input" buffer, so you must press two times ctrl-d); In Windows, Ctrl-z represents EOF. (Incidentally, by pressing Ctrl-z in Linux, the process is interrupted, suspended in the background, the FG command can be re-cut back to the foreground, and the process is terminated by pressing CTRL-C.) )
So, what if you really want to enter ctrl-d? At this point you must press CTRL-V, then you can enter the ctrl-d, the system will not think this is the EOF signal. Ctrl-v said that by "literal meaning" to interpret the next input, if you want to press "literal meaning" input ctrl-v, input two consecutive times on the line.


Bit field (bit segment)


Bit fields are not a very obscure point of knowledge, but there are some small details to note about their memory alignment.

The so-called "bit field" is to divide the bits in one byte into several different regions and describe the number of bits per region. Each domain has a domain name that allows operations to be performed by domain name in the program.

The list of bit fields is in the form: type specifier bit domain name: bit field length;
A bit field must be stored in the same byte and cannot span two bytes. If one byte has enough space left to hold another domain, the bit field should be stored from the next cell.

For example:

struct a{    char a:6;    char B:5;    char C:5;};/ /sizeof (struct A) is 3, not 2.

0-bit segment

A bit segment of length 0, whose purpose is to keep the next bit segment starting from the next storage unit. (The size of the next storage cell is the size of its bit segment type)

For example:

struct bs{    unsigned a:4;    unsigned  : 0;   Airspace    unsigned b:4;   Start storing unsigned c:4;};/from the next storage unit    /sizeof (struct BS) is 8, if no 0-bit segment is 4

About Memory layout

Give me a chestnut first:

struct Foo {    char A;    int  b:1;    int   : 0;    int  c:7;    Char D;    char E:4;    char F:6;    char G:6;} ;

What is the size of sizeof? The memory arrangement of bit segments, which have different implementations on different compilers. I use the UNIX environment, Xcode compiled, and the results of GCC compilation are the same. VC + + may result in different results.

The compression storage rules for bit segments are:

1. If the adjacent bit field fields are of the same type and their bit width is less than the sizeof size of the type, the subsequent fields will be stored next to the previous field until they cannot be accommodated;
2. If the adjacent bit field field is of the same type, but its bit width is greater than the type sizeof size, then the subsequent field will start from the new storage unit, and its offset is an integer multiple of its type size;
3. If the type of the adjacent bit field is different, the specific implementation of the compiler differs, VC6 take the non-compression method, dev-c++ take compression method;
4. If the bit field fields are interspersed with non-bit field fields, no compression is performed;
5. The total size of the entire structure is an integer multiple of the size of the widest base type member.

sizeof (struct foo) is 12

The following slowly explained: Char a accounted for a byte, b accounted for 1BIT,GCC compression, that is, A and b compression in an int unit, followed by a 0-bit segment, it is preceded by a storage unit, a and B accounted for 4 bytes.

Then another int c, so first open a 4 bytes, and then fill in the back of the bit, but the next is a complete char, the complete char is not placed in the paragraph, so int c accounted for 4 bytes, char d accounted for 1 bytes.

The subsequent e,f,g are bit segments, noting that the bit segments cannot cross the boundary (with the size of their data type being the boundary ), so the e,f,g each account for 1 bytes instead of 2 bytes. So sizeof (struct foo) is 12.

Simple illustrations:

|---A (8)---|-b (1)-|---------------------(23°c)----------------------|

|---c (7)---|-------------------------(+)--------------------------|

|---d (8)---|---e (4)---|--(4)--|---f (6)---| | (2)-|---g (6)---| | (2)-|


Attention:

Bit paragraph is best not to cross-byte, I have seen in the C textbook warning: Do not make the bit segment more than 8 bits, but the definition of a bit segment (I have defined 64 bits of bits, used to extract the double variable) is still feasible, can compile and run, but after the cross-byte, its arrangement will be affected by the size side, Therefore, it is best not to give way over 8 bits.







The corner of C language (ii)-You don't necessarily know C language features

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.