Corner of the C language (2) -- the features of the C language and corner

Source: Internet
Author: User
Tags domain list

Corner of the C language (2) -- the features of the C language and corner

Before I wrote a C language corner, introduced some C in some very useful features (, recently sorted out some corner knowledge, special open this article.

Case in the switch statement

(The case keyword 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 one struct in sequence. In C99, you can do this:
Struct Foo {
Int x;
Int y;
Int z;
Foo = {. z = 3,. x = 5 };

This code first initializes foo. z, and then initializes foo. x. foo. y. It 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 pointer (C99)

The keyword restrict is only useful for pointers. Modifying the pointer indicates that you can only modify the content of the data zone pointed to by the pointer, this keyword enables 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;}

Obviously, the return value of the function foo () is 0 unless the values of x and y are the same. As you can imagine, in 99% cases, this function returns 0 instead of 1. However, the correct 100% code must be generated after compilation. Therefore, 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 optimize the code safely. Since x is the only way to modify x, after compilation, you can confirm that the line "* y = 1;" does not modify the content of * x, so it can be safely optimized:

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

Many library functions use the restrict Keyword:

Void * memcpy (void * restrict dest, const void * restrict src, sizi_t n) is a useful memory replication function. Because both parameters have a restrict limit, therefore, the two regions cannot overlap, that is, the region indicated by the dest pointer. Other pointers cannot be modified, 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 10]){
You assure the compiler that the pointer you pass to f points to the first element of an array with at least 10 int elements.. I guess this is also for optimization; for example, the compiler will assume that a is not empty. The compiler will also issue a warning when you try to pass in a pointer that can be statically determined as null or an array is too small.

Void f (int a [const]) {
You cannot modify the pointer a., which is the same as the description int * const. However, when you use the static method mentioned in the previous section, for example, in int a [static const 10], you can get something that cannot be obtained 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, there is a low byte at the low level, DCBA is sequentially arranged from low byte to high byte.

This is just a cool-looking method, which is generally useless.


About EOF

EOF is a confusing thing for beginners. It is not uncommon knowledge, but it is easy to cause misunderstandings and errors. So here we will also summarize it.

EOF is the abbreviation of end of file, indicating the end of "stream. Here, the "Text Stream" can be a file or a standard input (stdin ).
For example, the following code indicates that, if it is not the end of the file, the content of the file will be copied to the screen.

int c;while ((c = fgetc(fp)) != EOF) {  putchar (c);}
Naturally, I thought that at the end of each file, there was a special character called EOF. After reading this character, the operating system thought the file was over.
However, I later 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 ends with an EOF (that is,-1), because the ASCII code corresponding to the text is positive, A negative value is not allowed. But what about binary files? How can I handle the-1 contained in the file?
It took me a long time to think about this problem. Later I checked the information and found out that in the Linux system, EOF is not a character at all, but a signal value returned when the system reads the end of the file.(That is,-1 ). As for how the system knows the end of the file, the document compares the length of the file. (The system records the file length in the file distribution table)

There is a problem with this writing. Fgetc () not only returns EOF at the end of a file, but also returns EOF when an error occurs.. Therefore, the C language provides the feof () function to ensure that the end of the file is indeed reached. The above code feof () is written as follows:
int c;while (!feof(fp)) {    c = fgetc(fp);    do something;}
However, there is also a problem with this writing. After fgetc () reads the last character of the file, the feof () function of C language returns 0, indicating that it does not reach the end of the file; only when fgetc () if you read another character (that is, the last character is crossed), feof () returns a non-zero value, indicating that it reaches the end of the file..

Therefore, according to the above statement, if a file contains n characters, the internal operation of the while loop will run n + 1 times. Therefore, the safest syntax 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 the end of the file, EOF can also represent the end of the standard input.
However, the standard input is different from the file, and the length of the input cannot be known in advance. You must manually enter a character to indicate that the input reaches the EOF.

In Linux, pressing Ctrl-D at the beginning of a new line represents the EOF (if Ctrl-D is pressed in the middle of a line, it indicates that the cache area of "standard input" is output, therefore, press Ctrl-D twice. In Windows, Ctrl-Z indicates EOF. (By The Way, in Linux, pressing Ctrl-Z indicates that the process is interrupted and suspended in the background. You can use the fg command to switch back to the foreground; press Ctrl-C to terminate the process .)
So what if I really want to enter Ctrl-D? In this case, you must press Ctrl-V first, and then you can enter Ctrl-D, the system will not think this is an EOF signal. Ctrl-V: Press "literal meaning" to interpret the next input. If you want to press "literal meaning", enter Ctrl-V, and enter it twice in a row.


Bit domain (bit segment)

Bit domains are not uncommon knowledge points, but there are still some small details about memory alignment.

The so-called "bit field" refers to dividing the binary bit in a byte into several different regions and showing the digits of each region. Each domain has a domain name, which allows operations by domain name in the program.

The format of the bit domain list is: type description Character Domain Name: Bit domain length;
A single-byte field must be stored in the same byte, and cannot span two bytes. If the remaining space of one byte is insufficient to store another domain, it should be stored from the next unit.

For example:

Struct A {char a: 6; char B: 5; char c: 5 ;}; // sizeof (struct A) is 3 instead of 2.

0-bit segment

A bit segment with a length of 0 is used to store the next bit segment from the next storage unit. (The size of the next storage unit is the size of its bit segment type)

For example:

Struct bs {unsigned a: 4; unsigned: 0; // airspace unsigned B: 4; // store unsigned c: 4 starting from the next storage unit ;}; // sizeof (struct bs) is 8. If there is no 0-bit segment, it is 4.

About memory Layout

Let's give a question:

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 sizeof size? Bit Memory arrangement, which has different implementations on different compilers. I use Xcode compiling in a UNIX environment, and the gcc compilation results are the same. The results of VC ++ may be different.

Bit compression storageRulesYes:

1. If the types of adjacent fields are the same, and the sum of the bit widths is smaller 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 types of adjacent bit fields are the same, but the sum of Bit Width is greater than the sizeof size of the type, the subsequent fields start from the new storage unit, its offset is an integer multiple of its type;
3. If the types of adjacent bit field are different, the implementations of each compiler are different. VC6 adopts the non-compression mode and Dev-C ++ adopts the compression mode;
4. Do not compress fields that are interspersed with non-bit fields;
5. The total size of the entire struct is an integer multiple of the size of the widest basic type.

Sizeof (struct foo) is 12

The following explains: char a occupies one byte, and B occupies 1 bit. gcc adopts the compression method, that is, compressing a and B in an int unit, followed by a 0-bit segment, therefore, the front is a storage unit, with a and B occupying 4 bytes.

Then it is int c, so first open a 4 byte, and then fill in the following bit segment, but the back is a complete char, this complete char cannot be placed in the bit segment, therefore, int c occupies 4 bytes, and char d occupies 1 byte.

The subsequent e, f, and g are bit segments. Note,Bit segments cannot span boundaries (based on the size of their data types), So e, f, and g each occupy 1 byte, rather than 2 bytes. Therefore, sizeof (struct foo) is 12.

Simple illustration:

| --- A (8) --- |-B (1)-| --------------------- (23) ---------------------- |

| --- C (7) --- | ------------------------- (25) -------------------------- |

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


It is recommended that the bit segments not be cross-byte. I have seen a warning in the C textbook: do not make the bit segments more than 8 characters, however, it is still feasible to define multi-bit segments (I have defined 64-bit segments for extracting double variables), which can be compiled and run, but after cross-byte, the smooth arrangement will be affected by the size of the end, so it is best not to let the bit segment exceed 8 bits.

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: 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.