C language questions

Source: Internet
Author: User

I saw it a long time ago. I think it's good. I think it's okay today. I found it and backed it up.

Int x = 35;
Char STR [10];

// Q: What are the values of strlen (STR) and sizeof (STR?
// The strlen (STR) value is unknown. strlen determines whether the string ends Based on '/0.
// Sizeof (STR) = 10 sizeof an array is the length of the array.

Strcpy (STR, "www.it315.org"/* A total of 13 letters */);
// Q: What are the values of x and strlen (STR?
// The value of X is 35.
// Strcpy (char * DEST, const char * SRC)
// Copy DEST Based on SRC. The length of the replication is determined based on the '/0' value of SRC, And the Dest must provide sufficient length. This will cause overflow. strlen returns 13, however, the external data of the array has been damaged.

// (The author's note: I have provided a more accurate answer below)

STR = "it315.org"; // can I compile it?
// Arrays cannot be assigned values and can only be initialized. Char STR [10] = "it315.org ";
// During initialization, the compiler checks whether the array length matches the initialization String Length.

Char * pstr;
Strcpy (pstr, "http://www.it315.org ");
// Can the above sentence be compiled? Is there a problem when running?
// It can be compiled, but pstr points to the constant zone. It is recommended that you only perform read operations during the runtime, and write operations are not safe.
// (I have provided a more accurate answer below) const char * P1;
Char * const P2;
// What is the difference between the above two statements?
// Const char * and char const * Both indicate character pointers to constants.
// Char * const indicates the constant pointer to a character

P1 = (const char *) STR;
// If it is p1 = STR; can the compilation be passed? Why type conversion? What is the essence of type conversion?
// You can compile it. The relationship between constants and constants is as follows:
// The const pointer can point to the const or non-const region without any problems.
// Non-const pointer cannot point to the const region, which may cause an error.

Strcpy (P1, "ABC"); // can the compilation be passed?
// Cannot pass, strcpy (char *, const char *); char * cannot point to const char *

Printf ("% d", STR); // is there a problem?
// No problem. The STR address is output.

Pstr = 3000; // can it be compiled? If not, how can I modify it to ensure the compilation is successful?
// It cannot pass. char * pstr indicates that pstr is a character pointer and cannot point to an integer variable of 3000.
// If you modify the value, you can: pstr = (char *) 3000 and point pstr to the address 3000;

Long y = (long) pstr; // can this be done?
// Yes. The value of Y is the address indicated by pstr. However, if it is purely an address, it is best to use unsigned long.

Int * P = STR;
* P = 0x00313200;
Printf ("% s", STR); // What is the result? The following message is displayed: 0x31 corresponds to '1' and 0x32 corresponds to '2 '.
// Compilation may not pass first. Some compilers may not allow int * to direct to char *. It is best to change it to int * P = (int *) STR;
// If the pass is successful, nothing is found. Int * P = STR; P indicates the address indicated by STR, and * P indicates modifying the memory pointed by Str.
// Because sizeof (INT) is on a 32-bit machine, int has four bytes (in fact, it depends on the compiler configuration file, as if it was limit. h, usually 4 bytes) So STR [0]-str [3] is modified.
// Because 0x00313200 starts with 0, the string starts with '/0' and cannot print anything. Here is a question about big-endin and little-endin. Take 0x31323334 as an Example
// On the little-endin machine, 0x31323334 is arranged in the memory in the order of 34 33 32 31, and the output is 4321, such as the Intel chip pc
// The Big-endin host is 31 32 33 34 and the output is 1234, for example, IBM powerpc

P = 3000; // What is the result of p + 1?
// 3000 + sizeof (INT); pointer + 1 is the original address plus sizeof (the data type indicated by the pointer)

Char * Pc = new char [100]; // The preceding statement occupies several memory blocks in the memory. What is the layout?
// The PC itself occupies a 4-byte pointer length of the function stack (whether it is 4 bytes depends on the machine and compiler ).
// New will apply for a continuous space of 100 bytes of sizeof (char) on the stack.

Void test (char ** P)
{
* P = new char [100];
} // Is there a problem with this compilation function? How do I pass parameters to call this function?
// No problem with the program. The address indicated by the pointer must be changed in the function.
// The reason is as follows: if the passed pointer is itself, when the function is called, the real parameter will be copied to an instance, so it is not the original pointer, any changes made to the pointer itself cannot be passed back.
// It can be understood that if the input parameter is int, the change to the int value will not be passed back, and the addition of * is the same.

// Do you understand the functions of typedef int (* pfun) (int x, int y?
// Defines a macro of the function pointer type. In this way, pfun indicates the function pointer type that points to the return value as int and has two int parameters at the same time.
// This variable can be defined:
// For example, a function is int fun (int x, int Y );
// Pfun P = fun; // (the author's note: I have provided a more accurate answer). below is my supplement:
Question 2: int x = 35;
Char STR [10]; strcpy (STR, "www.it315.org"/* 13 letters in total */);
// Q: What are the values of x and strlen (STR? A: The strlen value is 13. In the VC ++ environment, the value of X must be changed (other compilers did not try it ,). although it seems that the value of X has not been modified in the program, the actual running result is that the value of X has been modified. This is because after strcpy, copy the excess data to the STR neighbor (X of the int type), so the data of x changes. this is an unforgettable problem that I encountered when I first debuted. Although I solved this problem with the help of my friends, I have never understood why the value of X has changed, only when I finally took the post of Training Instructors did I start to sort out my previous puzzles and summarize my previous experiences for reference. I think the value of this question is very great. It can attract students to pay enough attention to the cross-border copying of strings, and through this question, they can better understand how the string is handled, better understanding of the relationship between a string and a character array: A string is a character array, but this character array is used in the processing of string functions, these functions do not consider the length of the array, just remember the first address of the array, start processing from the first address, and end processing when 0 is encountered. Question 4: char * pstr;
Strcpy (pstr, "http://www.it315.org ");
// Can the above sentence be compiled? Is there a problem when running?
A: The compilation is successful, but pstr is not effectively initialized. It points to an uncertain memory zone, and a non-writable memory error will occur during runtime! Last question: // do you understand the functions of typedef int (* pfun) (int x, int y? A: The biggest use of a function pointer is that it can be called by a template method, which I learned when learning the Java design pattern. for example, two functions have the same process structure, but the specific functions called internally are different, as shown in the following figure: void func1 () {// a piece of Process Code and an object-oriented proxy, int sum = add (x, y), for example, security check and log record; // a piece of Process Code and an object-oriented proxy, such as security check and log record} void func2 () {// Process Code and Aspect-Oriented proxy identical to func1, such as security check and logging int Difference = sub (x, y ); // a piece of Process Code exactly the same as func1 and an aspect-oriented proxy, such as security check and logging} can define only one function, as shown below void func (pfunc P) {// Process Code and Aspect-Oriented proxy identical to func1, such as security check and logging int Difference = p (x, Y); // a piece of Process Code exactly the same as func1 and an object-oriented proxy, such as security check and logging} when calling a program, let the parameter P point to the ADD and sub functions respectively. my current focus on writing and work is no longer in the C language, and I have no time to answer them one by one. I will use the answers released by jackie214 to respond to you. I remember reading an article and posting them together. I will discuss one of the questions in Zhang Xiaoxiang's C language questions. When "several questions about the ability to test your C language skills" first appeared on the csdn homepage, I went to Miss Zhang's blog. Objectively speaking, the question is more basic, but it is not very easy to say why each question comes. After a few days, I posted "explanation and analysis of language test questions". I checked in with curiosity. I found that there are also some praises and slander. Han Yu's "Shi Shuo" said: Wen Dao has successively specialized in the industry. Teacher Zhang naturally has his merits and knowledge points that he does not know.
OK. Now we will discuss the second question in the question. The questions are as follows:

Int x = 35;

Char STR [10];

Strcpy (STR, "www.it315.org"/* A total of 13 letters */);

// Q: What are the values of x and strlen (STR?

We will not discuss the answer first, but I think it is related to the compiler. Teacher Zhang's answer is not without reason, and Qin Shihuang's answer also makes sense. Someone is beginning to doubt what you are talking about? That's right, that's right. What is right. Okay. Now let's start the analysis.
I. Stack
Before specific explanations, let's clarify several stack concepts: Full stack and empty stack, ascending stack and descending stack.
Full stack refers to the stack pointer pointing to the last data unit written last time, while the empty stack Stack pointer pointing to the first idle unit. A Descending stack is a reverse growth in the memory (that is, the reverse growth starts from the end of the application space), and the ascending stack is growing in the memory.
The traditional full descending stack (FD full descending) is used on the server ). If you use a x86 compliant compiler, it usually sets your stack pointer at the end of the application space and then uses a full descending stack. Stack regions used to store local variables, parameters, return addresses, and other temporary variables of a function are called Stack frames ). (For more information about this part, see my other article "viewing the past and present of function calls through Linux kernel source code".) 1:

Figure 1 stack frame Layout

Ii. Target File Format
The target file formats vary between systems. The first UNIX system born from Bell's laboratory uses the. Out format. Earlier versions of System v unix use coff (common object file format is generally the target file format ). Windows uses a coff variant called the PE format (portable executable can be transplanted and executable ). Modern Unix-such as Linux, various BSD, and Sun Solaris-uses UNIX elf (executable and linkable format, executable and connectable formats ). Although the following discussions focus on elf, the basic concepts are similar in either format.
If the variables X and STR are local variables, they must be placed in the stack. If both of them are global variables, place X in. data Segment (. data: stores initialized global variables. BSS segment (. BSS: stores uninitialized global variables ).
The information layout of a typical elf executable target file is shown in Figure 2:

Figure 2 Typical elf Executable File Format

Each program has a runtime memory image, as shown in Figure 3:

Figure 3 memory image during Linux Runtime

In Linux, code segments always start at 0x08048000. The data segment is located at the next 4 kb aligned address. The runtime heap is located at the first 4 kb alignment address after the next read/write segment, and increases through the malloc library. The segments starting at 0x40000000 are reserved for the shared library. The user stack always starts from the address 0xbfffffff and grows down (to the low address direction ). The segments starting from the top of the stack at address 0xc0000000 are reserved for the code and data of the part of the memory where the Operating System resides. After the explanation, you should thoroughly understand the meaning of full descending stack.
Iii. Addressing and byte sequence
On almost all machines, multibyte objects are stored in a continuous byte sequence. The object address is the smallest address in the byte sequence used. For example, if the address of an int variable X is 0x100, that is, & x = 0x100, the four bytes of X will be stored in the memory 0x101, 0 X, 0x102 and 0x103.
Some machines choose to store objects in the sequence from the lowest valid byte to the highest valid byte in the memory.
Other machines store objects in the order of maximum valid bytes to minimum valid bytes. The former is called Little-Endian. For example, Intel's machines use this rule. The latter is called Big-Endian, such as IBM and Motorola.
Assume that the X type is int, the address is at 0x100, and there is a hexadecimal value of 0x12345678. The storage methods for the large tail end and small tail end are as follows:
Big tail end:
0x103 0x102 0x101 0x100

......

78

56

34

12

......

Small Tail end:
0x103 0x102 0x101 0x100

......

12

34

56

78

......

Note: In 0x12345678, The hexadecimal value of the high byte is 0x12, while that of the low byte is 0x78. Whether in a large tail machine or a small tail machine, the output x value is 0x12345678.

Iv. Variable storage layout through Assembly Code
In terms of local variables and global variables, we will discuss this question in VC ++ 6.0 in windows and GCC in Linux.
Assume that the program is as follows:

1 # include <stdio. h>
2 # include <string. h>
3
4 int main ()
5 {
6 int x = 35;
7 char STR [10];
8 strcpy (STR, "www.it315.org"/* 13 letters in total */);
9 printf ("% d/N", X );
10 return 0;
11}

The disassembly code of this program in VC ++ 6.0 is as follows:

1: # include <stdio. h>
2: # include <string. h>
3:
4: int main ()
5 :{
00401010 push EBP
00401011 mov EBP, ESP
00401013 sub ESP, 50 h
00401016 push EBX

Stack frame layout high address

Previous stack frame

EBP

(X = 35)

......

......

(STR)
......

Low address

00401017 push ESI
00401018 push EDI
00401019 Lea EDI, [ebp-50h]
0040101c mov ECx, 14 h
00401021 mov eax, 0 cccccccch
00401026 rep STOs dword ptr [EDI]
6: int x = 35;
00401028 mov dword ptr [ebp-4], 23 h/* press 35 into Stack */(1 place)
7: Char STR [10];
8: strcpy (STR, "www.it315.org"/* 13 letters in total */);
0040102f push offset string "www.it315.org" (00420020)
00401034 Lea eax, [ebp-10h] (2)
00401037 push eax
00401038 call strcpy (00401100)
0040103d add ESP, 8
9: printf ("% d/N", X );
00401040 mov ECx, dword ptr [ebp-4] (3)
00401043 push ECx
00401044 push offset string "% d/N" (0042001c)
00401049 call printf (00401080)
0040104e add ESP, 8
10: Return 0;
00401051 XOR eax, eax
11 :}

From the code above, we can find that at 1, the value of x 35 is pushed into the ebp-4, before running at 2, the value of the string has been pushed into the stack, then get the STR address in the stack, that is, the ebp-10h, that is, the ebp-16, the red arrow in the text pointed to the other side. Load it into the eax register, and then press it into the stack. As we all know, on the X86 platform, parameter transmission is implemented through stack frames. At this time, the strcpy function is called to copy the string value to the STR address. How to store strings at this time? Is the key to the problem. You may know the address of the STR string. To obtain the value of its next string, it is * (STR + 1). Then the answer is displayed. On the X86 platform, the stack grows down, and the higher the stack is, the higher the address is. When the string is copied, the string address goes up along the Blue Line. Because the string is 13 characters in length, it overwrites the value in the stack where X is located, and the last character G is assigned to X, because in Intel machines, the storage method of the small tail end is used, so the layout of the value in stack 4 is shown as follows:

Stack frame layout high address

Previous stack frame

EBP

(X) g

Ro.5

31ti

. Www
......

Low address

Figure 4 Layout of strings in the stack

When running at 3, the program presses the value at the ebp-4, that is, the value of X into the stack, calls printf, so the printed value is 103 (that is, the value of G ).
In Linux, the GCC compiler seems to be superior in performance and the answer is 35. Next let's look at the code after disassembly:

. File "sttest. c"
. Section. rodata
. Align 32
. Lc0:
. String "www.it315.org"
. String ""
. LC1:
. String "% d/N"
. Text
. Globl main
. Type main, @ Function
Main:
Pushl % EBP
Movl % ESP, % EBP
Subl $56, % ESP
Andl $-16, % ESP
Movl $0, % eax
Subl % eax, % ESP
Movl $35,-12 (% EBP)/* put 35 to the stack, that is, place x */(Place 1)

Stack frame layout high address

Previous stack frame

EBP

......

......

(X = 35)

......
......
......
......
......
......
(STR)
......

Low address

Movl $. lc0, 4 (% ESP)
Leal-40 (% EBP), % eax (2 places)
Movl % eax, (% ESP)
Call strcpy
Movl-12 (% EBP), % eax (3 places)
Movl % eax, 4 (% ESP)
Movl $. LC1, (% ESP)
Call printf
Movl $0, % eax
Leave
RET
. Size main,.-Main
. Section. Note. GNU-stack, "", @ progbits
. Ident "GCC: (GNU) 3.3.5 (Debian. 3.5-13 )"

We can find from 2, STR position in the ebp-40, get the STR address in the stack, and then put it in the stack pointer, call strcpy, in this case, it is not difficult to find that the difference between the address of X and the address of STR is 40-12 = 28, which is far greater than the length of the string, so it is impossible to overwrite the value of X. If you change the string length to 29 characters, the value of X will be overwritten.
Next, we will discuss the situation where X and STR are global variables, that is, to mention lines 6 and 7 to lines 3rd.
In section 2, we have discussed that X is placed in the. Data Segment and STR is placed in the. BSS segment. We can see from Figure 3 that the read/write segment (. Data,. BSS) is located at the low address. For elf files, the total length of the code segment is generally specified. data Segment, because. data is fixed, while. the BSS segment is assigned a value at runtime, so the rest of the code segment is. BSS size. Pay attention to this. the BSS segment address is greater. the address of the Data Segment. when values are assigned to variables in BSS, they cannot be overwritten. the value of the data segment. Let's look at Figure 2. Therefore, if X and STR are global variables, the STR value will never overwrite the value of X.
V. Summary
In fact, there is a lot of knowledge hidden behind each question. We can't just look at the surface, it's almost enough. As long as we study it further, we can obtain more knowledge points than the question itself.
Vi. Appendix
In Windows, there is a small amount of storage image information when a program is running. So far, I have mentioned this in programming excellence: a deep understanding of computers. So I drew this image with my impression:

Figure 5 memory image of a program running in Windows

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.