Today, I went to see the legendary recruitment, but it didn't take long for me. I did a few pen questions and a computer question, and then I came back. It's no big deal, but this computer question is still a bright spot, haha.
The question looks very simple, that is, to give a string that requires replacing the space character with a comma.
AndProgramThe template has been set, the main content has been written, and the conversion function prototype has been defined. It is very simple and easy to understand. Soon write the program:
Run it. The problem arises. The program will be in this line.CodeException:
Memcpy (* poutputstring, pinputstring, linputstringlen );
The exception content is the access violation access NULL pointer. Check the variable values. The problem is that * the value of poutputstring is 0x00000000.
Why is this error? According to the input parameter, * the value of poutputstring should be the address of the array defined in Main. The array already exists in the stack, so this address cannot be 0x00000000.
Where is the problem? I thought for a while before I understood the Central Plains. That is to say, the compiler has done some special processing for the transmission and retrieval of the array variables. The array variables can be used as pointers, but they are not equivalent to pointers. When it is retrieved, the array variable returns to its original meaning. This results in the same effect as directly using array variables.
We first find some traces from the debugging output of the program and set a breakpoint in main. Then run the program and view the values of the three expressions in watch after the interruption:
Here we can see that the value of poutputstring and & poutputstring are the same, both of which are 0x0012ff0c. Whether the value '0x0012ff0c' is stored in address 0x0012ff0c. Obviously not. Let's look at the last expression. This expression outputs the memory of address 0x0012ff0c. You can see that, the value of the four bytes connected here is zero. In fact, 0x0012ff0c is the position of the first element in the array, and the element in the array has been set to zero. Why is the value of poutputstring the same as that of & poutputstring?
To make this problem more straightforward, Let's first look at the similarities and differences between arrays and other data structures. When the program defines an int, Char, strcut, or array:
Int itemp = 0;
Int itemps [10] = {0 };
In fact, the compiler does similar work on both of them. They both reserve a memory area from the stack and store an integer and a group of integers respectively. Note that itemp and itemps are only two symbols supported by the compiler for developers. during compilation, the compiler maps these two symbols to the memory address. In memory allocation, the compiler only retains the memory blocks that store just the right size of the data and does not allocate other space for the array. That is to say, although we all say that an array can be considered as a pointer to the first element of an array, this pointer is not a real variable, it is similar to the concept of literal or immediate number. We can try to compile the following code:
Char pinputstring [] = "Hello World ";
Char poutputstring [13] = {0 };
Poutputstring = pinputstring;
The last line of code will get the error: Error c2106: '=': left operand must be L-value.
We can try again:
1 = 1;
The same error is returned. The left value must be a volume that supports memory storage.
A real pointer variable requires additional memory storage of the target data. When we define a pointer variable as follows:
Int * ptemp = new int;
Compilation will retain two pieces of memory: one piece of memory is reserved in the heap to store an integer, keep a memory of the same size as the number of bus addresses in the stack to store the address of the target data in the stack.
When we use the ptemp symbol, We reference the address in the stack. When the * ptemp symbol is used, the integer in the heap is referenced.
For array variables, the target data is not supported by any memory. Even if the compiler is required to treat it as a pointer value, it can only be used as the right value, not the left value.
Therefore, we can imagine what problems will occur when we perform the address fetch operation on Array variables. It is a contradiction to retrieve the storage address for a value that does not exist in the memory. Therefore, the compiler needs to treat the array variable as a symbol like a common data variable at this time, and return the first address of the destination data storage location when addressing it, this is exactly the same as when we directly use array variables. This is why we observed from watch at the beginning.
Now you know the problem. We often say that arrays will degrade to pointers, but this is only a special case designed by the compiler to avoid Memory waste. It is still a variable. In the past, when I read books such as C and pointer, I made a special discussion on arrays, but I never thought of this. Many things can be deeply realized only when they are met in reality.
However, I still did not answer this question correctly. As the Real-Time implementer of the function, without changing the prototype of the function, I cannot find a solution to this problem. When the caller retrieves an array variable address and forcibly converts it to a (t **), it seems reasonable, I don't know whether it should be compatible with this situation (forcibly convert the input parameter char ** to char *), or detect this situation, or let it be abnormal.
Afterwards: Baidu searched for information about the address of the array variable and found this post, saying the following code:
Int A [3] [4];
Cout <& A <Endl;
Cout <A <Endl;
Cout <sizeof (& A) <Endl;
Cout <sizeof (a) <Endl;
The output is:
0012ff40
0012ff40
48
48
For the output of sizeof (& A), I personally think it should not be 48. In any case, the result of the variable's addressing is an address value, it should be 4 bytes in size (on 32-bit machines ).
It is also suggested that the result of other compilers (GCC 4.4.0, vc2008, ICL 11.1) is 4.
It seems that you should pay attention to it later.