C gives rise to all things | Understanding pointers from the shallower to the deeper [the last part]
Article directory
Preface
-
We have learned four parts before. If you haven’t read the previous suggestions, you can read the previous ones~~
-
C generates all things | Understanding pointers from the simple to the deep [Part 1]
-
C generates all things | Understanding pointers from the simple to the deep [Part 2]
- Next we start the last part of our pointers to deepen our impression of pointers~~
Comparison of sizeof and strlen
sizeof
-
When learning operators, we learned
sizeof
andsizeof
to calculate the size of the memory space occupied by variables. The unit is bytes. If If the operand is a type, the size of the memory space occupied by the variable created using the type is calculated. -
Let’s start learning about sizeof~~
- Among them
size_t
is actually specially designed forsizeof
, indicating the return value type ofsizeof
sizeof
cannot calculate a negative number, sosize_t
is designed forsizeof
~~
For example:
int main()
{
int a = 10;
printf("%d\n", sizeof(a));
printf("%d\n", sizeof(int));
return 0;
}
- If this is a variable, the parentheses can be omitted
- If it is a type, it cannot be omitted
- The 4 calculated here means that it occupies 4 bytes.
sizeof
We only focus on the size of the memory space occupied and don’t care what data is stored in the memory. We will look at it in detail in a moment~~
strlen
strlen is a C language library function whose function is to find the length of a string. The function prototype is as follows:
size_t strlen ( const char * str );
It counts the string starting from the address in the parameters of strlen
functionstr
backward, and before \0
The number of characters in. The
strlen
function will keep looking for the \0
character backwards until it is found, so there may be an out-of-bounds search.
Let’s look at the following code
int main()
{
char arr2[] = "abc";
printf("%d\n", strlen(arr2));
return 0;
}
- What is the calculated value of strlen here?
3
- We can also see how it is stored through the debugging window~~
- You can see that 61 in the memory monitoring window here is 97, 0 is
\0
,strlen
is the statistics before\0
The number of strings, the result is3
- Then if I manually add one
\0
in the middle of the string, what will it be?
char arr2[] = "ab\0c";
printf("%d\n", strlen(arr2));
- You can see that the result is
3
- Then the string does not have
\0
What is its result?
char arr1[] = {
'a', 'b', 'c' };
printf("%d\n", strlen(arr1));
- We can see that the result is 15, which is actually a random value. I don’t know how often we will encounter it
\0
.
- Let’s compare
strlen
andsizeof
strlen:
- sizeof is the operator
- sizeof calculates the size of the memory occupied by the operand, the unit is bytes
- Don’t pay attention to what data is stored in memory
sizeof:
- strlen is a library function. To use it, you need to include the header file.
string.h
- srtlen is used to find the length of a string, counting the number of characters before
\0
- Pay attention to whether there is
\0
in the memory. If not\0
, it will continue to search later and may cross the boundary
- When sizeof calculates the size, it actually calculates it based on the type.
- So what is printed below?
short s = 10;
int i = 2;
int n = sizeof(s = i + 4);
printf("%d\n", n);
printf("%d\n", s);
- Let’s see the results~~
-
Why 2 and 10? Let’s analyze it~~
-
A short integer s is created, occupying two bytes, i is an integer, occupying four bytes
-
I want to put the result of i+4 here into the s type. I put 4 integers into the space of two integers. This needs to be truncated. After truncation, s has the final say, so it is 2 bytes.
-
Then the second one, the expression placed inside sizeof will not be actually calculated and will not participate in the calculation! ! ! So the original value will print what value~~
- Then some students may ask, if the expression does not participate in the calculation, then why is the one above 2? In fact, sizeof is inferred based on the type. s = i + 4 will not be executed. The calculation of i + 4 is the integer type. The result of the integer type must be put into the shot type, so it is the short type, which is 2 words. Festival, do you understand~~
If you still don’t understand, let’s take a look at some written test questions to deepen your impression~~
Analysis of array and pointer written test questions
one-dimensional array
- Let’s take a look here first. What is printed below? You can analyze it yourself first, and then we will analyze it one by one~~
int main()
{
int a[] = {
1,2,3,4 };
printf("%d\n", sizeof(a));
printf("%d\n", sizeof(a + 0));
printf("%d\n", sizeof(*a));
printf("%d\n", sizeof(a + 1));
printf("%d\n", sizeof(a[1]));
printf("%d\n", sizeof(&a));
printf("%d\n", sizeof(*&a));
printf("%d\n", sizeof(&a + 1));
printf("%d\n", sizeof(&a[0]));
printf("%d\n", sizeof(&a[0] + 1));
return 0;
}
- What you need to know is that the array name is the address of the first element, but there are two exceptions:
- sizeof (array name) - the array name represents the entire array, and the size of the entire array is calculated, in bytes
- &Array name - array name means that the array name means the entire array, and what is taken out is the address of the entire array.
sizeof
There is a separate array name inside. The array name indicates the size of the entire array. There are 4 elements in the array, and each element is 4 bytes, so it is16
printf("%d\n", sizeof(a));
- The a in the array name here is not placed inside sizeof, nor is it
&
, so a is the address of the first element, the address, and the size is4/8
bytes
printf("%d\n", sizeof(a + 0));
- a is the address of the first element of the array, a==&a[0], *a is actually the first element, that is,
a[0]
, and the size is4
bytes
printf("%d\n", sizeof(*a));
- a is the address of the first element of the array (&a[0] -->int*), a+1–> &a[1], a+1 is the address of the second element, so the result is
4/8
printf("%d\n", sizeof(a + 1));
- Calculate the size of the second element in bytes. The result is
4
printf("%zd\n", sizeof(a[1]));
&a
takes out the address of the array, but the address of the array is also an address, and the size of the address is4 / 8
bytes
printf("%zd\n", sizeof(&a));
- Here &a is to take out the address of the array and then dereference it, which is equivalent to offset. &a is an array pointer, that is
int(*p)[4] = &a
, *p access The size of an array, p+1 is the size of an array to skip, the result is16
printf("%d\n", sizeof(*&a));
- &a+1 is the address after skipping the entire array. The address size is 4/8 bytes. The result is
4/8
printf("%zd\n", sizeof(&a + 1));
- Here is the address of the first element, and the result is
4/8
printf("%zd\n", sizeof(&a[0]));
- Here is the address of the second element, and the result is
4/8
printf("%zd\n", sizeof(&a[0] + 1));
- Let's verify it on vs. This is printed on a 32-bit platform~~
- This is running under 64 bit~~
character array
- Next let's look at character arrays
int main()
{
char arr[] = {
'a','b','c','d','e','f' };
printf("%d\n", sizeof(arr));
printf("%d\n", sizeof(arr + 0));
printf("%d\n", sizeof(*arr));
printf("%d\n", sizeof(arr[1]));
printf("%d\n", sizeof(&arr));
printf("%d\n", sizeof(&arr + 1));
printf("%d\n", sizeof(&arr[0] + 1));
return 0;
}
- The array name is placed separately inside sizeof. The size of the entire array is calculated. There are 6 characters, so the result is
6
printf("%d\n", sizeof(arr));
- arr is the address of the first element of the array, arr+0 is still the address of the first element. The address size is
4/8
bytes
printf("%d\n", sizeof(arr + 0));
- arr is the address of the first element of the array, *arr is the first element, and the size of one character is
1
bytes
printf("%d\n", sizeof(*arr));
- arr[1] is the second element of the array, the size is 1 byte
printf("%d\n", sizeof(arr[1]));
- &arr is the address of the array. The address of the array is also the address. The size is
4/8
printf("%d\n", sizeof(&arr));
- &arr+1 skips the entire array and points to the back of f
4/8
printf("%d\n", sizeof(&arr + 1));
- &arr[0] is the address of the first element, &arr[0]+1 is the address of the second element
4/8
printf("%d\n", sizeof(&arr[0] + 1));
- Let’s take a look at the 32 platform
- Let’s look at the 64-bit platform
- Let's move on to the second one
char arr[] = {
'a','b','c','d','e','f' };
printf("%d\n", strlen(arr));
printf("%d\n", strlen(arr+0));
printf("%d\n", strlen(*arr));
printf("%d\n", strlen(arr[1]));
printf("%d\n", strlen(&arr));
printf("%d\n", strlen(&arr+1));
printf("%d\n", strlen(&arr[0]+1));
- This array does not have \0, strlen is to calculate the number of elements before
\0
, so it is随机值
printf("%d\n", strlen(arr));
- This array name is also the address of the first element. +0 means no addition. The result is
随机值
~~
printf("%d\n", strlen(arr+0));
- Here arr is the address of the first element, and *arr dereference is the character
a
. The ASCLL code value is 97. If 97 is passed to strlen, 97 will be regarded as an address, which is illegal. Visit, the result will报错
printf("%d\n", strlen(*arr));
- This code is similar to the previous code. It accesses the ASCLL code value of the second element, which will be passed as the address.
报错
printf("%d\n", strlen(arr[1]));
- &arr is to take out the address of this array, that is, counting backward from the starting position, and the result is also
随机值
printf("%d\n", strlen(&arr));
- This &arr is the address of the first element, and then +1, skipping the address of the entire array, and not knowing what is stored in it. The result is
随机值
printf("%d\n", strlen(&arr+1));
- &arr[0] is the address of the first element, +1 is the address of the second element, and then counting backward, the result is also
随机值
printf("%d\n", strlen(&arr[0]+1));
- Here we initialize
abcdef\0
, there are \0~~
char arr[] = "abcdef";
printf("%d\n", sizeof(arr));
printf("%d\n", sizeof(arr+0));
printf("%d\n", sizeof(*arr));
printf("%d\n", sizeof(arr[1]));
printf("%d\n", sizeof(&arr));
printf("%d\n", sizeof(&arr+1));
printf("%d\n", sizeof(&arr[0]+1));
- What is calculated here is the size of the arr element, and the result is
7
printf("%d\n", sizeof(arr));
- arr represents the address of the first element of the array, arr + 0 is still the address of the first element, and the size is
4/8
bytes
printf("%d\n", sizeof(arr+0));
- arr represents the address of the first element of the array, *arr is the first element, and the size is
1
bytes
printf("%d\n", sizeof(*arr));
- arr[1] is the second element, the size is also
1
bytes
printf("%d\n", sizeof(arr[1]));
- &arr is the address of the array, but it is also an address. The size of the address is
4/8
bytes
printf("%d\n", sizeof(&arr));
- &arr is the address of the array, &arr+1 is the address where the entire array is skipped. The result is
4/8
bytes
printf("%d\n", sizeof(&arr+1));
- The address of the second element, size
4/8
bytes
printf("%d\n", sizeof(&arr[0]+1));
- Let’s change sizeof to strlen~~
char arr[] = "abcdef";
printf("%d\n", strlen(arr));
printf("%d\n", strlen(arr+0));
printf("%d\n", strlen(*arr));
printf("%d\n", strlen(arr[1]));
printf("%d\n", strlen(&arr));
printf("%d\n", strlen(&arr+1));
printf("%d\n", strlen(&arr[0]+1));
- arr is the address of the first element. It calculates the number of elements before strlen encounters \0. The result is
6
printf("%d\n", strlen(arr));
- arr+1 is also the address of the first element, and the result is
6
printf("%d\n", strlen(arr+0));
- The result here is
报错
, which will be illegal access
printf("%d\n", strlen(*arr));
- Koriya-kai formation
非法访问
~~
printf("%d\n", strlen(arr[1]));
- &arr is the address of the array, but this address also points to the starting position of the array. strlen starts from the starting position and searches backward for \0. The result is
6
printf("%d\n", strlen(&arr));
- &arr+1 is the address after skipping the entire array, starting from here and looking backward for \0, that is
随机值
printf("%d\n", strlen(&arr+1));
- arr[0] + 1 is the address of the second element, the length is
5
printf("%d\n", strlen(&arr[0]+1));
- Let’s take a look at the results~~
- Our pointer variable here
p
stores the address of this string a
char *p = "abcdef";
printf("%d\n", sizeof(p));
printf("%d\n", sizeof(p+1));
printf("%d\n", sizeof(*p));
printf("%d\n", sizeof(p[0]));
printf("%d\n", sizeof(&p));
printf("%d\n", sizeof(&p+1));
printf("%d\n", sizeof(&p[0]+1));
- p is a pointer variable, the size is
4/8
bytes
printf("%d\n", sizeof(p));
- p+1 is the address of ‘b’, which is
4/8
bytes
printf("%d\n", sizeof(p+1));
*p
Is the first character, the size is 1 byte
printf("%d\n", sizeof(*p));
- p[0] === *(p+0), which is actually the first character in the string, and the size is 1 byte
printf("%d\n", sizeof(p[0]));
- &p is the address of p, which is also the address. The address size is 4/8 bytes.
printf("%d\n", sizeof(&p));
- &p + 1 is also an address, &p1+1 is the address after skipping the p variable
printf("%d\n", sizeof(&p+1));
- 4/8 – &p[0] + 1 is the address of b
printf("%d\n", sizeof(&p[0]+1));
Under 32 bits
Under 64-bit
char *p = "abcdef";
printf("%d\n", strlen(p));
printf("%d\n", strlen(p+1));
printf("%d\n", strlen(*p));
printf("%d\n", strlen(p[0]));
printf("%d\n", strlen(&p));
printf("%d\n", strlen(&p+1));
printf("%d\n", strlen(&p[0]+1));
- p points to the address of the first element of this string. There is \0 in the string. Starting from the address of a, accessing backwards, the result is
6
printf("%d\n", strlen(p));
- The type of p is
char*
, and+1
skips a char type data, so we come to the character'b'
printf("%d\n", strlen(p+1));
*p
gets the character'a'
, strlen will pass the ascll code value of character a as the address, which will cause illegal access, and the result iserr
printf("%d\n", strlen(*p));
- This is the same as the previous one, and will also cause illegal access, which is equivalent to
*p == *(p+0) == p[0]
printf("%d\n", strlen(p[0]));
- This result is a random value, &p is the address of p, and the type is
char*
It searches from the starting position of the space occupied by p. It does not know when it will encounter to\0
, so it will be a random value
printf("%d\n", strlen(&p));
- After fetching the address, the type of this code becomes
char**
,+1
will skip onechar*
type data, it points to the position at the end of the string. From here, search backwards\0
. You don’t know when you will encounter it, so the final result is still随机值
printf("%d\n", strlen(&p+1));
- This is very similar to the second one, & and [] are equivalent to canceling, +1 points to
'b'
, and the result is5
printf("%d\n", strlen(&p[0]+1));
Finally, let’s look at the two-dimensional array, which is also the more difficult part.
Two-dimensional array
int a[3][4] = {
0};
printf("%d\n",sizeof(a));
printf("%d\n",sizeof(a[0][0]));
printf("%d\n",sizeof(a[0]));
printf("%d\n",sizeof(a[0]+1));
printf("%d\n",sizeof(*(a[0]+1)));
printf("%d\n",sizeof(a+1));
printf("%d\n",sizeof(*(a+1)));
printf("%d\n",sizeof(&a[0]+1));
printf("%d\n",sizeof(*(&a[0]+1)));
printf("%d\n",sizeof(*a));
printf("%d\n",sizeof(a[3]));
- sizeof (array name), calculates the size of the entire array. This is a two-dimensional array. The array has three rows and four columns, with a total of twelve elements. The type of each element is int, which is 4 bytes. Then The total size is
48
printf("%d\n", sizeof(a));
- a[0][0] represents the element in the first row and column of the array, so each element is
4
bytes
printf("%d\n", sizeof(a[0][0]));
a[0]
is the array name of the first line, and it is placed separately inside sizeof(). The size of the entire first line is calculated. There are 4 elements in it, and each element is 4 bytes. Then The result is16
printf("%d\n", sizeof(a[0]));
- a[0] is the array name of the array in the first line, but the array name is not placed inside sizeof alone, so the array name represents the address of the first element of the array, which is the address of a[0][0] , a[0]+1 is the address of the second element in the first row
a[0][1]
, and the size of the address is4/8
bytes
printf("%d\n", sizeof(a[0] + 1));
a[0] + 1
is the address of the second element in the first rowa[0][1]
,*(a[0] + 1)
is the second element in the first row, and the size is < a i=3>bytes4
printf("%d\n", sizeof(*(a[0] + 1)));
a
is not placed inside sizeof alone. There is no &. The array name a is the address of the first element of the array, which is the address of the first row.a+1
is the address of the second row. , which is equivalent toa -- int(*)[4]
---->a+1 -- int(*)[4]
printf("%d\n", sizeof(a + 1));
- The following is to dereference this line, and then the entire second line is obtained. At this time, the calculation is the size of the entire line, and the result is
16
printf("%d\n", sizeof(*(a + 1)));
- This is the same as the previous one, except that it is written in a different way, which is equivalent to
*(a + 1)
. It calculates the element size of the second row, and the result is16
printf("%d\n", sizeof(a[1]));
- a[0] is the array name of the first row. If you get the address of it, you can get the address of the entire row. Its type is also an array pointer int (*)[4], then < If /span>bytes
+1
, the entire array will also be skipped. At this time, we have reached the second row, and the address of the second row is obtained. The size of the address is4/8
printf("%d\n", sizeof(&a[0] + 1));
- This is similar to the one above. The second line of dereference calculates the size of the element in the second line. The result is
16
printf("%d\n", sizeof(*(&a[0] + 1)));
- The array name a is the address of the first element of the array, which is the address of the first row.
*a
is one row, which is equivalent to*(a+0) == a[0]
printf("%d\n", sizeof(*a));
-
Doesn’t this two-dimensional array only have three rows? The array in the third row is named a[2]. Isn’t a[3] out of bounds?
-
You need to know that for any expression, there are two attributes, one is [value attribute] and the other is [type attribute]
-
For example, 3 + 5 = 8, its value attribute is the number 8, and its type attribute is int. But for [sizeof()], it only needs to know the [type attribute] when calculating, similar to what we wrote before Sizeof(int), sizeof(char), etc. can be calculated for these built-in types without actually creating space.
-
So for the following a[3], although it seems to be out of bounds, sizeof() does not care whether you have gone out of bounds, but only needs to know your type. Then a[3] is the first element of the two-dimensional array. Four lines, although there is no fourth line, but the type is determined, then the size is determined. Calculating sizeof (array name) calculates the size of the entire array, and the result is
16
printf("%d\n", sizeof(a[3]));
- Let’s take a look at the running results~~