C is ulique (on)

zhaozj2021-02-12  165

C is ulique (on)

It is almost two years since the second year of graduate students, and there is a lot of gains all the way. There are many regrets. Now I have a leisure, I want to leave some footprints, memories. Everyone has their own different life. It is the labeling of the program, and the singer said in "Faust": "If you don't chew the bread in sorrow, you have not been waiting for tomorrow, such people I don't know how you - the power of the day. "So I want to keep some programs that bring me sad, bring me crying. In fact, the basic course of learning computers is very important, discrete mathematics, compilation principle, operating system, form language ... If you have passed these roads, you will find that your path will get wider, you will find your road. The previous efforts and sweat will constantly give you inspiration, give you support, give you the weapons and courage to advance. You will find a lot of achievements in the future, but you will pick it up!

For program language, I like C , it can bring you something unable to give you unpailed intelligence, and of course it will give you a language to give you the devil. In fact, Java, C #, Python language is also very good, I also like it. They are all very successful languages, I have never been willing to be a blind believers in a language, each language has its success, failed place, there is a place where it is suitable, it is not satisfactory. So every time I see the article of the evaluation language, I have a look, but I never speak.

C 's past life is C, and the mystery and streamline left by C is superficial in C and better than blue! The confusion and flexible flexibility in C, even a few years of high-segment C programmers are still able to turn over in small water ditch in the C language. However, in fact, C language is really difficult. Here I want to point out four places in the C language, they continue to be unpredictable in C languages.

Pointer, array, type identification, parameter variable functions.

One. pointer.

Its essence is the type of address. There is no such concept in many languages. But it is the reason why C is flexible, efficient, invincible in the process-oriented era. Because the memory model of C basically corresponds to the machine model of the current Von Neumann (von Nuiman) computer, it has achieved a mapping of the machine. However, some people seem to never understand the pointer [Note 1].

Note 1: Joel Spolsky is thinking, he believes that the understanding of the pointer is an APTITUDE, not through training. http://www.joelonsoftware.com/printerfriendly/articles/fog0000000073.html

The pointer can point to the value, array, function, of course, it can also be used as a value.

Look at the following examples:

INT * p; // p is a pointer, pointing to an integer

INT ** P; // P is a pointer, pointing to the second pointer, then pointing to an integer

INT (* pa) [3]; // PA is a pointer, pointing to an array with 3 integers

INT (* pf) (); // PF is a pointer to a function, this function returns an integer

I will detail the identification of the Identifier type.

1. What is the type of pointer itself?

First look at the example below: INT A; // a type?

Yes, you can remove A. Therefore, the pointer in the four declaration statements above is:

Int *

Int **

Int (*) [3] int (*) ()

They are all composite types, which is the type of type and type. The meaning is as follows:

Point to int (pointing to an integer)

Pointer to Pointer to int (pointing to a pointer to an integer)

Pointer to Array Of 3 INTS (pointing to a pointer with three integers)

Pointer to Function of Parameter Is Void and Return Value Is Int (pointing to a function of a function, this function parameter is empty, the return value is an integer)

2. What is the type of pointer?

Very simple, the type of pointer itself removes "*", as follows:

int

Int *

Int () [3]

Int () ()

3 and 4 are a bit blamed, isn't it? Please polish your eyes, in that, "*" "" () "is redundant, so:

Int () [3] is int [3] (an array with three integers)

int () () is int () (a function, the parameter is empty, the return value is an integer) [Note 2]

Note 2: A small reminder, the second "()" is an operator, a named function call operator (Function Call Operator).

3. Arithmetic operation of the pointer.

Remember again: The pointer is not a simple type, it is a type of composite with the type of pointer. Therefore, its arithmetic operation is closely related to it (the type of pointer refers).

INT A [8];

INT * P = a;

INT * Q = P 3;

P ;

The addition or decrease of the pointer is not the binary representation of the pointer itself, to remember, the pointer is an element of an element, and each of them, it points to the next element. and so:

INT * Q = P 3; // q points to the third integer starting from P.

P ; // P pointing down the next integer.

Double * Pd;

... // After some calculation

Double * Pother = PD - 2; // Pother points to the second Double number of pd counting.

4. The size of the pointer itself.

In a modern typical 32-bit machine [Note 3], the machine's memory model is probably like this, imagine, the memory space is like a continuous room group. The size of each room is a byte (typically a binary 8). Some things are one byte (such as char), and a room is placed; but some things are a few bytes (such as Double is 8 bytes, INT is 4 bytes, I am talking about Typical 32-bit), so it takes several rooms to be placed.

Note 3: What is 32-bit? It is the data width of the machine CPU processing is 32 bits. The machine's register capacity is 32-bit, the machine's data, and the memory address bus is 32 bits. Of course there are some details, but roughly this. 16-bit, 64-bit, 128 bits can be pushed in this class.

These rooms should have numbered (iii), and 32-bit machine memory address space is of course 32, so each number of the room is encoded with 32-bit binary numbers. [Note 4]. Keep in mind that the pointer can also be used as a value. When it is value, it must be placed in the room (stored in memory), then pointing to a value of a value requires an address size to store, ie 32 bits, 4 words Section, 4 rooms are stored. Note 4: On the 32-bit machine we usually used, there are many complete use of 32 real memory address spaces (232 = 4g), even if the server is no exception. Modern operating systems generally achieve 32-bit virtual address space, which makes it easy to apply programming. Regarding the difference between the virtual address (linear address) and the real address, you can refer to the second chapter of the Linux Source Code Analysis "storage management, on the Internet About this topic of the art, you can google.

However, please note that the size of the pointer to the target member in C is not necessarily 4 bytes. To this end, I specifically prepared some programs, discovered on my two compilers (VC7.1.3088 and DEV-C 4.9.7.0), pointing to the size of the pointer to the object, but all of the four times . Different compilers have different values. For general common classes (CLASS), the pointer to the object is generally 4, but when introducing multiple virtual inherits and virtual functions, pointing to the pointer to the object will increase, whether pointing to member data, or a member function. [Note 5].

Note 5: In the 5.13 section 104 of Andrei Alexandrescu, the member function pointer is actually a tagged unions, which can deal with multiple virtual inheritance and virtual functions, books that member function pointers The size is 16, but my practice tells me that this result is wrong, and the specific compiler is also different. I have always wanted to see the source code of GCC, but because there are too many next to, and the heart is not quiet, it is difficult to have a relatively difficulty (this is not afraid ^ _ ^), only after it is left.

Another point, for a class Static Member, pointing to its pointer is just a normal function pointer, not the Pointer to Class Member, so its size is 4.

5. Pointer operator & and *

They are a pair of opposite operations, and the address of a thing (that is, the pointer), * get something in an address. This thing can be a value (object), function, array, class member (CLASS MEMBER).

In fact, it is very simple, living alone in the room, & operation can only target the room number;

* Operation can only target people in the room.

The type of reference to the pointer itself and the type of pointer refer to it are very understandable.

Summary: In fact, you just understand 1, 2, it is equivalent to mastering the pointed nose. The following is not difficult, and the various changes in the pointer and other common types of common types in the C language are almost almost (such as various transformations).

two. Array.

In C language, you only need to understand three things for arrays.

1. There is only one-dimensional array in C language.

The so-called N-dimensional array is just a name, a convenient note, is used to use a one-dimensional array simulation. The element in the C language array can be any type of thing, especially the array can be used as an element. So Int a [3] [4] [5] should be understood: A is an array of 3 elements, each of which is an array of 4 elements, further each element has 5 integers An array of elements.

Is not it simple! The memory model of array A should be easy, isn't it? :)

2. The number of elements of arrays must be asked as an integer constant to come out in the compilation phase.

INT I;

INT A [i]; // is not legal, compiling will not pass.

Maybe some people will be strange char str [] = "test"; why not specify the number of elements can pass, because the compiler can ask in the compilation phase according to the initialized string of the following.

Don't believe you try this: int A [];

The compiler cannot be inferred, so it will be sentenced to information such as "Array Size Missing In A". However, in the latest C99 standard, it realizes the growth array [Note 6]

Note 6: If you are a very strong person, just like me, you can check the C99 standard 6.7.5.2.

3. For arrays, an address (ie, a subscriber 0) element can be obtained (i.e., the pointer) is obtained from an array name.

For example, INT A [5]; INT * P = a; here P gives the address of array element a [0].

The rest for the various operations of the array are actually the corresponding operations of the pointer. For example, a [3] is actually a simple writing method of * (A 3), because * (A 3) == * (3 a), you will see similar 3 in some programs, you will see similar 3 [A] This strange expression, now you know, it is an alias of A [3]. There is also a strange expression like a [-1], now you understand, it is * (a-1) [Note 7].

Note 7: You are definitely a very responsible person, and you know what you are doing. Don't you? :) So you must also know that one thing is to pay, of course, more costs should be obtained.

I like economics, a foundation of economics is what is going to spend cost, even if you don't do anything. Time cost, money cost, opportunity cost, healthy cost ... It can be said that the fundamental purpose of economics is the largest return with the smallest cost.

So we best avoid this evil writing in your own procedure, don't let your own intelligence over, you will have a long pain in your life and others. In a word of Wai Xiaobao: "The business of the business is not dry!"

But understanding the evil understanding is very necessary, so when we really encounter evil, we can prevent it from it to the soul!

For pointers pointing to different elements of the same array, they can subtract, such as INT * P = Q I; P-Q's result is the number of elements between the two pointers. i can be a negative number. But keep in mind: pointers pointing to different array elements, such practices are useless and evil!

For so-called N-dimensional arrays, such as int A [2] [3]; you can get the address A of the array of first elements and its size. * (A 0) (i.e., A [0] or * a) is the first element, it is an array int [3], continue to get the first element, * (* (* (A 0) 0) (i.e., A [0] [0] or * (* a)), that is, the first integer (the first integer of the first column of the first row). If this expression is used, it is very awkward, so a [0] [0] is very useful! easy to understand! For arrays, you can only use the elements and elements addresses within the array valid range, but the address of the next element of the last element is an exception. It can be used to facilitate the various calculations of the array, especially comparative operations. But obviously, what it points to, can not be used and changed!

About the array itself is probably so much, and the following is briefly stating the relationship between arrays and pointers. Their relationship is very embarrassing, sometimes it can be used alternate.

For example, int Main (int Args, char * argv []), the char * Argv [] in the list of parameters is another way of writing of char ** argv. Because in the C language, an array cannot be directly transmitted as a function 引 (Note 8). Because it is very losses, this is in violation of the basic idea of ​​C language design - as an efficient system design language.

Note 8: Here I didn't use the function of the mainland, but used Taiwan terminology, they all translated this English term, but in many local Chinese, the unsuitable, very reluctant, and The number of quotes represent the number of references, very image, and very well understood. Soon you can adapt the quotes as I am instead of arguments.

DEREFERANCE, that is, * operator operation. I also use the probably, not a solution.

I think you must be wisdom and do: there is a good wisdom, and there is also the courage to face new things! Are you not willing to admit it? :)

So the parameter declaration in the form of the argument list in the parameter list, just to facilitate the reading of the programmer! For example, Char * Argv [] can easily think of an array of CHAR * strings, which is the address of the first element of the CHAR * string array. Other elements can of course be able to be obtained by DEREFERANCE (Reference Note 8] by this pointer! Therefore, the entire array is also available indirectly.

But array and pointers are still different, such as the definition below in a file:

Char myname [] = "wuaihua";

And there is the following statement in another file:

EXTERN CHAR * MyName;

They don't know each other, although your book is so hope.

They differ in the use of memory spaces [Note 9].

For char myname [] = "wuaihua" as follows

MyName

w

U

a

i

hide

U

a

/ 0

For char * myname, as follows

MyName

/ | /

w

U

a

i

hide

U

a

/ 0

Note 9: You can refer to Andrew Konig's "C Trap and Defect" 4.5.

The way to change is to make them consistent.

Char myname [] = "wuaihua";

EXTERN CHAR MyName [];

or

Char * myname = "wuaihua"; // C is best replaced with const char * myname = "wuaihua". EXTERN CHAR * MyName;

(To be contract!)

Wu Tong wrote in 2003.5.26

Recently modified 2003.6.16

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

New Post(0)