Good. Then go deep into the C + + journey. When I was translating the first article. I have learned a lot of things, so I intend to translate this whole PPT to complete.
Take a look at the following code snippet:
[CPP]
- #include <stdio.h>
- void foo (void)
- {
- int A;
- printf ("%d\n", a);
- }
- void Bar (void)
- {
- int a = 42;
- }
- int Main (void)
- {
- Bar ();
- Foo ();
- }
#include <stdio.h>void foo (void) { int A; printf ("%d\n", a);} void bar (void) { int a = 42;} int main (void) { bar (); Foo ();}
Compile execution, what do you expect to output?
[CPP]View Plaincopyprint?
- $ cc foo.c &&./a.out
- 42
$ cc foo.c && ./a.out42
Can you explain why this is so?
First candidate: Hmm? Perhaps the compiler has a pool of variable names in order to reuse. Say. In the bar function. Use and release the variable a when the Foo function needs an integer variable a. It will get the same memory area as a in the bar function. Suppose you name the variable a again in the bar function, I don't think you'll get 42 output.
You: Uh.
Are you sure.
。
。
Second candidate: Yes, I like it.
Do you want me to explain about running the stack or the active frame (activation frames, the way the operation code is stored in memory). For example, on some systems, a function exists in memory in such a way that:
Esp
Form parameters
Local variables
Eip
)?
You: I think you have proved that you understand the key to the problem.
However, suppose we compile with optimized parameters. Or use a different compiler to compile, what do you think will happen?
Candidate: Assume that the compilation optimization measures are involved. Very many things can happen. For example, the bar function may be ignored. Because it does not produce whatever effect. At the same time. Assuming that the Foo function will be inline so there is no function call, I am not surprised.
However, because the Foo function must be visible to the compiler, the Foo function's target file is created. So that other target file link stages need to link foo function. In short, if I use compile optimization, I should get different values.
[CPP]View Plaincopyprint
"Href=" http://blog.csdn.net/rockics/article/details/7018490# ";?"
- $ cc-o foo.c &&./a.out
- 1606415608
$ cc-o foo.c && ./a.out1606415608
Candidate: Garbage value.
So, what does this code output?
[CPP]View Plaincopyprint?
- #include <stdio.h>
-
- void foo ( void )
- {
- int a = 41;
- a= a++;
- printf ( "%d\n" , a);
- }
-
- int Main ( void )
- {
- foo ();
- }
#include <stdio.h> void foo (void) { int a = in. A= a++; printf ("%d\n", a);} int main (void) { foo ();}
First candidate: I have not written this code.
You: Yes, good habit.
Candidate: But I'm pushing the answer to 42.
You: Why?
Candidate: Because there is no other possibility.
You: Indeed, execute on my machine. Did get the 42.
Candidate: Yes, hey.
You: But this piece of code, in fact, belongs to no definition.
Candidate: Yes, I told you, I didn't write code like that.
The second candidate comes in: A will get a value that is undefined.
You: I don't get any warning messages. And I got 42.
Candidate: Then you need to raise your warning level. After assignment and self-increment, the value of a is indeed undefined. Since you violate one of the fundamental principles of the C + + language, this rule is primarily for the run order (sequencing).
C + + rules, in a sequence operation. For each variable, you can only update it once.
Over here. A = a++. Updated two times, which causes a to be a value that is undefined.
You: You mean, I'm going to get a random value? But I did get 42.
Candidate: Yes. A can be a 42,41,43,0,1099, or a random value. Your machine gets 42. I'm not surprised at all, what else can I get here? or select 42 as an undefined value before compiling:) hehe:)
So, what about the following code?
[CPP]View Plaincopyprint?
- #include <stdio.h>
- int B (void)
- {
- Puts ("3");
- return 3;
- }
- int C (void)
- {
- Puts ("4");
- return 4;
- }
- int Main (void)
- {
- int a = B () + C ();
- printf ("%d\n", a);
- }
#include <stdio.h> int B (void) { puts ("3"); return 3;} int C (void) { puts ("4"); return 4;} int main (void) { int a = B () + C (); printf ("%d\n", a);}
First candidate: simple, 3,4,7 will be printed in turn.
You: indeed.
But it could be 4,3,7.
Candidate: Ah? is the order of operations also undefined?
You: To be precise, this is not undefined. But not specified.
Candidate: anyway. Nasty compiler.
I think he should give us a warning message.
What are you warning about?
Second candidate: The Order of operations is unspecified for the detailed platform in C/s + +. Because of the need for optimization. The compiler is able to determine the order of operations, which is related to the order of operation.
This code is in accordance with the C standard.
This code is either output 3,4,7 or output 4,3,7. This depends on the compiler.
In your heart: if most of my colleagues understand the language they use, like you do. How good Life would be:)
This time. We would consider the second candidate to have a C-language understanding. Significantly deeper than the first candidate. Suppose you answer the above question, what stage do you stay at? :)
So. Trying to see the potential of a second candidate? And see how much he knows C + +
Be able to examine the relevant knowledge:
Declaration and definition;
Calling conventions and active frames;
Sequence point;
memory model;
Optimization
Differences between the different C standards.
Over here. Let's start by sharing knowledge about the difference between the order points and the different C standards.
Consider the following code, what output will you get?
[CPP]View Plaincopyprint?
- 1.
- int a = 41;
- a++;
- printf ("%d\n", a);
- Answer: 42
- 2.
- int a = 41;
- a++ & printf ("%d\n", a);
- Answer: no definition
- 3.
- int a = 41;
- a++ && printf ("%d\n", a);
- Answer: 42
- 4. int a = 41;
- if (a++ <) printf ("%d\n", a);
- Answer: 42
- 5.
- int a = 41;
- A = a++;
- printf ("%d\n", a);
- Answer: no definition
1.int a = 41;a++;p rintf ("%d\n", a); Answer: 2.int a = 41;a++ & printf ("%d\n", a); Answer: Not defined 3.int a = 41;a++ && prin TF ("%d\n", a); Answer: 42 4. int a = 41;if (a++ <) printf ("%d\n", a); Answer: 5.int a = 41;a = a++;p rintf ("%d\n", a); Answer: no definition
When will the C/C + + language have side effects?
Order Point:
What is a sequence point?
In short, the order point is such a position. All the side effects before it have occurred, and all the side effects after it have not yet started. The entire expression between the two order points or the order in which the code is run is undefined.
Order Point Rule 1:
A value can only be written once before the previous order point and the next order point, or between two order points;
Here, between the two order points. A was written two times, so that such behavior belonged to no definition.
Order Point Rule 2:
Further, the previous value should be read-only. To determine what value to store.
A lot of developers think that C language has very many order points. In fact, the C language has very few order points.
This gives the compiler a greater amount of space to optimize.
Next look. The difference between the various C standards:
Now let's go back to the two candidates we started.
What does the following code output?
[CPP]View Plaincopyprint?
- #include <stdio.h>
- struct X
- {
- int A;
- Char b;
- int C;
- };
- int Main (void)
- {
- printf ("%d\n", sizeof(int));
- printf ("%d\n", sizeof(char));
- printf ("%d\n", sizeof(struct X));
- }
#include <stdio.h> struct x{ int A; Char b; int C;}; int main (void) { printf ("%d\n", sizeof (int)); printf ("%d\n", sizeof (char)); printf ("%d\n", sizeof (struct X));}
First candidate: It will print out the 4,1,12.
You: Indeed, I got this result on my machine.
Candidate: Of course.
Because sizeof returns the number of bytes. On a 32-bit machine, the C language of type int is 32 bits, or 4 bytes. The char type is a byte length.
In a struct, this meeting is aligned with 4 bytes.
You: OK.
Your heart meditation: Do you want another ice cream? (don't know what special emotions)
Second candidate: Uh. First of all. Get the code intact first. sizeof's return value type is site_t and is not always the same as the int type.
Therefore, the output format%d in printf is not a very good specifier.
You: OK.
So, what format specifiers should I use?
Candidate: It's a little complicated. The site_t is an unsigned integer number on a 32-bit machine. It is generally a number of unsigned int types. On a 64-bit machine, however, it is generally a number of unsigned long types.
However, in the C99. A new descriptor is specified for the site_t type, so. %zu will be a very few choice.
You: OK. Well, let's get this descriptor bug in good condition. You go on to answer the question.
[CPP]View Plaincopyprint?
- #include <stdio.h>
- struct X
- {
- int A;
- Char b;
- int C;
- };
- int Main (void)
- {
- printf ("%zu\n", sizeof(int));
- printf ("%zu\n", sizeof(char));
- printf ("%zu\n", sizeof(struct X));
- }
#include <stdio.h> struct x{ int A; Char b; int C;}; int main (void) { printf ("%zu\n", sizeof (int)); printf ("%zu\n", sizeof (char));
Candidate: This depends on the platform, as well as the compile-time options. The only thing that can be determined is that sizeof (char) is 1. Do you want to do it on a 64-bit machine?
You: Yes. I have a 64-bit machine that executes in 32-bit compatibility mode.
Candidate: Then because of the byte alignment reason. I think the answer should be 4,1,12. This, of course, depends on your compilation options, which may be 4,1,9. Let's say you compile with GCC and add-fpack-struct to understand that the compiler is required to compress the struct.
You: I did get 4,1,12 on my machine. Why is it 12?
Candidate: Work in case of incorrect byte alignment. The price is very expensive. So the compiler optimizes the storage of the data so that each data domain is stored at the word boundary. The storage of the struct also takes into account the case of byte alignment.
You: Why is it expensive to work in a situation where the bytes are not properly aligned?
Candidate: Most processor instruction sets are optimized to copy a word-length data from memory to CPU. Suppose you need to change a value across a word boundary, you need to read two characters, block out the other values, and then change and write back.
It's probably 10 slower than that.
Remember, the C language takes great care of execution speed.
You: Suppose I had to add a char D to the struct. What will happen?
Candidate: Suppose you add char d behind a struct. I estimate that sizeof (struct X) would be 16. Because, suppose you get a structure with a length of 13 bytes, seemingly not a very effective length. However, if you add char D to the back of Char B, then 12 will be a more reasonable answer.
You: Why does the compiler not rearrange the order of the data in the struct. In order to better optimize memory usage and execution speed?
Candidate: There are some languages that have done this, but C + + has not done so.
You: Suppose I add char *d to the back of the struct. What will happen?
Candidate: You just said that your execution environment is 64-bit. So the length of a pointer is 8 bytes. Perhaps the length of the struct is 20? But another possibility is that the 64-bit pointers need to be aligned efficiently, so the code might output 4,1,24?
You: good. I don't care what the results will be on my machine. But I like your point of view and insight, J.
(not to be continued)
In-depth understanding of C + + [deep C (and C + +)] (2)