C. 诡 (below)

zhaozj2021-02-12  165

C. 诡 (below)

three. Identification of types.

Basic types of identification are very simple:

INT A; // a type is a

CHAR * P; // P type is char *

......

So please see the following:

INT * (* a [5]) (int, char *); // # 1

Void (* b [10]) (void (*) ()); // # 2

Doube (*) () (* pa) [9]; // # 3

If you are the first time I saw this type of declaration, I would definitely feel like my feelings, just like a sunny day, five thunders, dizziness, a monster of a teeth dance.

Don't close (Take It Easy! Let's take a pack of these faceable paper tigers!

1. The function declaration and array declaration in the C language.

Function declaration is generally this int fun (int, double); the corresponding function pointer declaration is true:

INT (* PF) (int, double), you have to habits. It can be used like this:

PF = & fun; // assignment (assignment) operation

(* PF) (5, 8.9); // Function call operation

Please also note that the C language itself provides a shorthand method as follows:

PF = fun; // assignment

PF (5, 8.9); // Function call operation

However, I don't really like this kind of book, it has brought more confusion for beginners.

The array declaration is generally this int a [5]; the statement for the array pointer is like this:

INT (* pa) [5]; you must also habits. It can be used like this:

PA = & a; // assignment (ASSIGNMENT)

INT i = (* pa) [2] // Assign a [2] to i;

2. With the above foundation, we can deal with the three paper tigers that start! :)

At this time you need to review the priority of various operators and the order of combination, by the way, it is enough to find this book.

# 1: int * (* a [5]) (int, char *);

First see the identifier A, "[]" priority is greater than "*", A and "[5]" first combined. So A is an array, this array has 5 elements, each element is a pointer, pointer pointing "(int, char *)", pair, pointing to a function, the function parameters are "int, char *", return value Yes "int *". After completing, we have done the first paper tiger. :)

# 2: Void (* b [10]) (void (*) ());

B is an array. There are 10 elements of this array. Each element is a pointer. The pointer points to a function, the function parameters are "void (*) ()" [Note 10], the return value is "void". complete!

Note 10: This parameter is another pointer, pointing to a function, the function parameter is empty, the return value is "void".

# 3. Doube (*) () (* pa) [9];

PA is a pointer, pointer points to an array, 9 elements of this array, each element is "Doube (*)" [is also a pointer, pointing to a function, the function parameter is empty, the return value is "Double" Double "]. Is it really like to know them now, and I will take advantage of it! After we are familiar with this expression, we can simplify this type of declaration with "typedef".

# 1: int * (* a [5]) (int, char *);

Typedef int * (* pf) (int, char *); // PF is a type alias [Note 11].

PF a [5]; // with int * (* a [5]) (int, char *); the effect is the same!

Note 11: Many beginners can only know typedef char * pchar; but other usage for TypedEf is not very understanding. Stephen Blaha has made a summary of TypeDef: "The method of establishing a type alias is very simple. In the traditional variable declaration expression, use the type name instead of the variable name, and then add the keyword typedef to the beginning of this statement." You can see "Programmer" magazine 2001.3 "C master skill 20 strokes".

# 2: Void (* b [10]) (void (*) ());

Typedef void (* pfv) ();

Typedef void (* pf_taking_pfv) (PFV);

PF_TAKING_PFV B [10]; // With VOID (* b [10]) (void (*)); the effect is the same!

# 3. Doube (*) () (* pa) [9];

Typedef double (* pf) ();

TypedEf Pf (* Pa) [9];

PA Pa; // Same as Doube (*) (* PA) [9];

3. Content and Volatile location in the type declaration

Here I only say const, volatile is the same [Note 12]!

Note 12: As the name, Volatile modification is very easy to change, unstable, it may be changed by other threads, operating systems, hardware, etc., so it is stored in memory, each time you use it When you only go to read in memory, it cannot be optimized by the compiler in the internal register.

Type declaration constant is used to modify a constant, we generally use this: const in front

const Int; // Int is Const

Const char *; // char is constant

CHAR * const; // * (pointer) is const

Const char * const; // char and * are constant

For beginners, const char *; and char * const; it is easy to confuse. This takes time experience to make you used to it.

The above statement has a right way of writing: const is behind

INT const; // int is const

CHAR const *; // charr is constant

CHAR * const; // * (pointer) is const

CHAR const * const; // char and * are all

The first time you may not happen, but if you are good, why should we refuse it? :) Const has two benefits behind:

A. The type modified by Const is the one just in front of it. If this benefit can't make you feel awkward, then look at the next!

B. We will use the type of typedef of type many times. For example, typedef char * pchar, if it is modified with const, when Const is in front, it is const pchar, you will think it is const char *, but you are wrong, its true meaning is char * const. Do you surprise you! But if you use const in the back of it, the meaning will not change, don't believe you try! However, naming consistency in real projects is more important. You should adapt in both cases, and you can call, company habits, business profits should be given priority! However, when starting a new project, you can consider preferring const in the latter habitual usage.

four. Parameter variable function

There is a very strange parameter "..." in the C language, which is mainly used in the argument, the most common is the Printf function.

Printf ("Enjoy YourSelf Everyday! / N");

Printf ("The Value IS% D! / N", Value);

......

Have you thought about it?

1. Why is PrintF called Printf?

Whether it is to see, I am always a person who likes the roots of the roots, there is a special kind of good, a paragraph, a idiom, a sentence, my favorite is to find its origin, and the mood at the time, a foreign language Translated terms, the minimum requirement I will try my best to find its original foreign language. Especially the name of the word, I have always been very intended, there is an old saying in China: "Name is not right, then the words are not smooth." F is format in the printf, ready to print [Note 13].

Note 13: There are still many functions, a lot of variables, many names are very particular in various languages, if you are careful, you must have a lot of fun and satisfaction, such as why Hashtable is HashTable, not called Hashlist? There is a function IoTa (not ITOA) specifically used in the C SGI STL implementation, why do you think of this strange name?

Look at the article I don't like it, I don't want to do it, I don't want to do it, I don't do it to people, so I tell you these two answers:

(1) TABLE and LIST are the difference:

TABLE:

------- | ---------------------------

Item1 | kadkglasgaldfgl | jkdsfh

------- | ---------------------------

Item2 | Kjdszhahlka | XCVZ

------- | ---------------------------

List:

****

***

*******

*****

That's the difference!

If you still don't understand, you can go see how the Hash is implemented!

(2) The name Iota Is Taken From The Programming Language APL.

The APL language is mainly mathematical, and many formulas in mathematics will borrow Greek letters.

There is such a letter in the Greek alphabet, the uppercase is ι, lower-written, its English spelling is IOTA, this letter is between θ (Theta) and κ (kappa)!

You can take a look at http://www.wikipedia.org/wiki/apl_programming_ilage

Here is a paragraph of this:

APL is renowned for using a set of non-ASCII symbols that are an extension of traditional arithmetic and algebraic notation. These cryptic symbols, some have joked, make it possible to construct an entire air traffic control system in two lines of code. Because of its condensed nature and non-standard characters, APL has sometimes been termed a "write-only language", and reading an APL program can feel like decoding an alien tongue. Because of the unusual character-set, many programmers used special APL keyboards in ................

There is a function overload in C , which can be used to distinguish between different function parameters, but it still does not represent any number of function parameters.

A header file is defined in the standard C language specifically to deal with the variable parameter list, which contains a set of macros, and a VA_LIST's TypeDef declaration. A typical implementation is as follows [Note 14]:

Typedef char * va_list;

#define va_start (list) list = (char *) & va_alist

#define va_end (list)

#define va_arg (List, Mode) /

((Mode *) (List = SizeOf (Mode))) [- 1]

Note 14: You can view the C99 Standard Section 7.15 to get detailed and authoritative instructions. You can also refer to Appendix A for Andrew Konig "C Trap and Defect".

ANSI C also provides a vprintf function, which is identical to the corresponding Printf function behavior, but only replaces the parameter sequence after the format string is replaced with VA_LIST. As for how it is implemented, you have read "The C Programming Language", I believe you can do it yourself!

With these tools, we can implement your own variable parameter function, such as implementing a systematic error handler error. It is similar to the use of the Printf function. Just realligate the stream to stderr. Here I borrowed an example of Appendix A of "C Trap and Defect".

The implementation is as follows:

#include

#include

void error (char * format, ...)

{

VA_LIST AP;

VA_Start (AP, FORMAT);

FPRINTF (stderr, "error:");

Vfprintf (stderr, format, AP);

VA_END (AP); FPRINTF (stderr, "/ n");

Exit (1);

}

You can also implement Printf yourself:

#include

INT Printf (char * format, ...)

{

VA_LIST AP;

VA_Start (AP, FORMAT);

INT n = vprintf (Format, AP);

VA_END (AP);

Return n;

}

I also launched the header file of VC7.1, I found that the specific implementation of each macro is still different, and it is related to a lot of preducess. Where VA_LIST is not necessarily the alias of char *.

Typedef struct {

Char * a0; / * pointer to first homed integer argument * /

Int offset; / * byte offset of next parameter * /

} va_list;

Other definitions are similar.

People who often program system programming in Windows must know that there are several different forms, such as __stdcall, __ pascal, __ cdecl. In Windows _stdcall, __ pascal is the same, so I just say the difference between __stdcall and __cdecl.

(1) __ stdcall indicates the stack and out of the stack and out of the called end. The number of functions of the function parameters is a form of call.

For example: int Fun (CHAR C, DOUBLE D), we use it in the main function, this function is only the operation of its own correspondence, how to come, how to go, it is an injection. Naturally there is main responsibility. However, the implementation of different compilers may put the parameters from the right to left, or it may be stack from left to right. In this order, we cannot add [Note 15].

Note 15: You can find relevant detail discussion in the terms of Herb Sutter's "More Exceptional C ": An UnmanageTer Evaluation.

(2) __ cdecl indicates that the call end is responsible for the stack and out of the call. The parameter variable function uses this call form.

Why should this function use different from the previous call form? That is because __stdcall call form does not work, it is not possible to know the number of quotes of the call end, how can it work correctly? So this way of calling is necessary, but because the variable function of the parameter parameters is not much, it is relatively small.

For these two ways, you can prepare some simple programs, then disassemble, you can see the actual difference below in assembly code, very well understood!

The overload function has a lot of matching (Match) rule calls. The function of the parameter "..." is the lowest match. This is useful in the "Modern C Design" in the amazing of Andrei Alexandrescu. .

postscript:

The details of the C language will not only have so much, but these few appearances are more frequent, and there is also a very important language feature in the C language. If you completely figure out these details, the mystery of the C language itself will not be too much.

The C language itself is like an exceptional sharp scissors, you can use it to make very delicate and elegant art, you can cut out some messy waste tabs. It takes time to use a weapon to enter the godification. How long does it take? Not much, please take 10,000 hours, Professor Mike Hou Wei, a professor of Psychology, England, Mike Houwei specializing in the gods and genius. His conclusion is very interesting: "The average person thinks that the genius is natural and fluent, smooth and unplanned Liangqing, in fact, genius must also spend at least ten years of light Yin to learn their special skills. There is no exception. To become an expert, you need to have stubborn personality and persistence of the ability ... Every line of professionals bet a lot of heart blood, Cultivate your own professional skills. "[Note 16] Note 16: Taiwan female writer, TV show host Wu La," take up 10,000 hours ". "Reader" 2003.1. "Don't worry too much, just continue. I want to have a long life or interest, just like a person running the marathon, the most important thing is to run, not how fast it runs in front."

Recommend two books:

K & R's "The C Programming Language", Second Edition.

Andrew Konig's "C traps and defects". This article quoted several examples, and the experience of a high segment programmer.

But for pure beginners are not suitable, if you have a basic knowledge of programming, spend a month, look at these two books, the C language itself doesn't have to spend more energy.

Wu Tong wrote in 2003.5.26

Recently modified 2003.6.19

转载请注明原文地址:https://www.9cbs.com/read-6162.html

New Post(0)