C gives rise to all things | Understanding pointers from the shallower to the deeper [the last part]

C gives rise to all things | Understanding pointers from the shallower to the deeper [the last part]

Preface


  • 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 and sizeof 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 themsize_t is actually specially designed for sizeof, indicating the return value type of sizeof
  • sizeof cannot calculate a negative number, so size_t is designed for sizeof~~

For example:

int main()
{
    
    
	int a = 10;
	printf("%d\n", sizeof(a));
	printf("%d\n", sizeof(int));
	return 0;
}

Insert image description here

  • If this is a variable, the parentheses can be omitted
  • If it is a type, it cannot be omitted

Insert image description here

  • The 4 calculated here means that it occupies 4 bytes.

  • sizeofWe 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~~

Insert image description here

  • 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

Insert image description here

  • 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 is3

Insert image description here

  • Then the string does not have\0What 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.

Insert image description here

Insert image description here

  • Let’s comparestrlen 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~~

Insert image description here

  • 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.

  • sizeofThere 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/8bytes
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 is 4bytes
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 is4/8
printf("%d\n", sizeof(a + 1));
  • Calculate the size of the second element in bytes. The result is4
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 is 4 / 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 isint(*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 is4/8
printf("%zd\n", sizeof(&a + 1));
  • Here is the address of the first element, and the result is4/8
printf("%zd\n", sizeof(&a[0]));
  • Here is the address of the second element, and the result is4/8
printf("%zd\n", sizeof(&a[0] + 1));
  • Let's verify it on vs. This is printed on a 32-bit platform~~

Insert image description here

  • This is running under 64 bit~~

Insert image description here


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 is6
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 is4/8
printf("%d\n", sizeof(&arr));
  • &arr+1 skips the entire array and points to the back of f4/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 element4/8
printf("%d\n", sizeof(&arr[0] + 1));
  • Let’s take a look at the 32 platform

Insert image description here

  • Let’s look at the 64-bit platform

Insert image description here


  • 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 charactera. 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报错

Insert image description here

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));

Insert image description here


  • Here we initializeabcdef\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 is7
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 is1bytes
printf("%d\n", sizeof(*arr));
  • arr[1] is the second element, the size is also1bytes
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 is4/8 bytes
printf("%d\n", sizeof(&arr+1));
  • The address of the second element, size4/8 bytes
printf("%d\n", sizeof(&arr[0]+1));

Insert image description here


  • 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 is6
printf("%d\n", strlen(arr));
  • arr+1 is also the address of the first element, and the result is6
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 is6
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 is5
printf("%d\n", strlen(&arr[0]+1));
  • Let’s take a look at the results~~

Insert image description here


  • Our pointer variable herep 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 is4/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));
  • *pIs 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

Insert image description here

Under 64-bit

Insert image description here

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 is6
printf("%d\n", strlen(p));
  • The type of p ischar*, 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 ischar*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 becomeschar**, +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));

Insert image description here


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 is48
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 rowa[0][1], and the size of the address is 4/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 to a -- 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 is16
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 is 4/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 is16
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 is16

printf("%d\n", sizeof(a[3]));
  • Let’s take a look at the running results~~

Insert image description here

Guess you like

Origin blog.csdn.net/2201_76004325/article/details/134263008