¿Cuánto sabes sobre sizeof y strlen?

 

1. La diferencia entre sizeof () y strlen ()

1. sizeof () es un operador monocular, no una función. Calcula el tamaño del espacio ocupado por el parámetro , es decir, el número de bytes (nota: la cadena suele terminar con '\ 0', por lo que el espacio ocupado por la cadena se calcula cuando el tamaño de, también incluye '\ 0')

2.strlen () es una función para calcular una cadena de caracteres de la longitud real (la longitud real de la cadena no contiene el '\ 0' calculado, si la definición de una matriz de caracteres char arr [] = "helloworld" , '\ 0' Es el último elemento de la matriz. Aunque no podemos verlo, también es parte de la cadena, pero lo que realmente vemos es "helloword", por lo que la longitud real significa la longitud de la cadena que realmente vemos. . Contiene '\ 0')

2. Otros conceptos

1. La diferencia entre punteros y matrices

Para facilitar el cálculo de los siguientes ejercicios, en primer lugar, también debemos averiguar la diferencia entre punteros y matrices

De hecho, los punteros y las matrices son conceptos completamente no relacionados, por lo que no es científico decir cuál es la diferencia entre los dos.

Las razones que nos confunden son:

       La matriz en sí solo tiene operaciones de eliminación de subíndices, pero en algunos casos se convertirá implícitamente en punteros (en lenguaje C):

     ① Transferencia de parámetros de función

     ② Suma y resta

     ③ Desreferencia

     ④Operación de comparación

     Sin embargo, el puntero puede estar subindicado por [], que es muy similar a una matriz en su comportamiento.

2. La diferencia entre int * const p y const int * p

①int * const p es equivalente a const * int p, donde el contenido de p no se puede modificar , es decir, la dirección guardada en p no se puede modificar, por lo que el siguiente resultado de la operación es incorrecto (para la conveniencia de la memoria, aparecí con una forma apropiada de entender, * no sigue p inmediatamente, por lo que significa que la variable puntero p en sí, es decir, el contenido de la variable p no se puede cambiar)

int a = 5;
int b = 10;
int* const p = &a; //p保存的地址不能被修改
p = &b;
printf("%d\n", *p);

②const int * p, donde el contenido apuntado por p no se puede modificar , por lo que el siguiente resultado de la operación es incorrecto (para la conveniencia de la memoria, se me ocurrió un método que puede no ser apropiado de entender, * después de p es equivalente a puntero p Desreferencia, es decir, el contenido apuntado por p no se puede cambiar)

int a = 5;
int b = 10;
const int* p = &a; //p中保存的地址所指向的内容不能被修改,即a的值不能被修改
*p = 20;
printf("%d\n", *p);

Tres, practica

1. Ejercicios para matrices de enteros unidimensionales

int arr[] = { 1, 2, 3, 4 };

arr es una matriz de enteros con una longitud de 4. En un sistema de 32 bits, un int ocupa 4 bytes y un tipo de puntero ocupa 4 bytes. Sigamos el sistema de 32 bits para practicar ~ (en el sistema operativo de 16 bits, un int ocupa 2 bytes y el tipo de puntero ocupa 2 bytes; en el sistema de 64 bits, int ocupa 4 bytes y el tipo de puntero ocupa 8 bytes)

①tamaño de ()

printf("%d\n", sizeof(arr));//数组名表示首元素的地址,因为数组中的元素在内存中是连续存放的,所以我们可以通过首元素的地址访问整个数组,即要求整个数组所占的空间大小,即sizeof(arr)=4*4=16
printf("%d\n", sizeof(arr + 0));//前面提到数组名+操作会触发隐式转换,arr表示首元素的地址,隐式转换成为指向首元素的指针,即sizeof(int*)=4
printf("%d\n", sizeof(*arr));//数组名表示首元素的地址,*使其隐式转化成为指针int*,对其解引用就是sizeof(int)=4
printf("%d\n", sizeof(arr + 1));//32位系统下,指针类型一律占4个字节,sizeof(int *)=4
printf("%d\n", sizeof(arr[1]));//数组的第二个元素所占空间的大小即sizeof(int)=4
printf("%d\n", sizeof(&arr));//对数组的首元素的地址取地址得到一个数组指针即sizeof(int(*)[4])=4
printf("%d\n",sizeof(*&arr));//根据操作符的优先级和结合性,&arr得到数组指针int(*)[4],再对其解引用得到int[4],即sizeof(int[4])=16
printf("%d\n", sizeof(&*arr));//首先触发隐式转换得到int*,解引用得到int,再对其取地址得到int*,即sizeof(int*)=4
printf("%d\n", sizeof(&arr + 1));//sizeof(int(*)[4]+1)=4,指针类型~
printf("%d\n", sizeof(&arr[0]));//sizeof(int *)=4,指针类型~
printf("%d\n", sizeof(&arr[0] + 1));//sizeof(int *)=4	指针类型~

2. La práctica de la matriz de enteros bidimensionales

int arr[3][4] = { 0 };

①tamaño de ()

printf("%d\n", sizeof(arr)); //sizeof(int[3][4]))=12*4=48
printf("%d\n", sizeof(arr[0]));//sizeof(int[4])=4*4=16
printf("%d\n", sizeof(arr[0]+1));//sizeof(int*[4])=4
printf("%d\n", sizeof(&arr[0]+1));//sizeof(int**[4])=4
printf("%d\n", sizeof(arr[0][0]));//sizeof(int)=4
printf("%d\n", sizeof(*arr[0]));//sizeof(int)=4
printf("%d\n", sizeof(*arr));//sizeof(int[4])=4*4=16
printf("%d\n", sizeof(*(arr + 1)));//sizeof(int[4])=16
printf("%d\n", sizeof(&arr[0] + 1));//sizeof(int*[4])=4
printf("%d\n", sizeof(*(arr[0]) + 1));//sizeof(int)=4

3. Práctica de la matriz de caracteres (1)

char arr[] = { 'a', 'b', 'c', 'd', 'e', 'f' };

Nota: la matriz de caracteres de arriba, no hay '\ 0' al inicializar

            Solo cuando se inicialice char arr [] = "abcdef", se agregará '\ 0' automáticamente

①tamaño de ()

printf("%d\n", sizeof(arr));//sizeof(char[6])=6
printf("%d\n", sizeof(arr + 0));//sizeof(char*)=4
printf("%d\n", sizeof(*arr));//sizeof(char)=1
printf("%d\n", sizeof(arr+1));//sizeof(char*)=4
printf("%d\n", sizeof(arr[1]));//sizeof(char)=1
printf("%d\n", sizeof(&arr));//sizeof(char(*)[6])=4
printf("%d\n", sizeof(*&arr)); //sizeof(char[6])=6
printf("%d\n", sizeof(&*arr)); //sizeof(char*)=4
printf("%d\n", sizeof(&arr[1]+1));//sizeof(char*)=4
printf("%d\n", sizeof(&arr + 1));//sizeof(char(*)[6])=4

②strlen ()

Nota: strlen () calcula la longitud real de la cadena

printf("%d\n", strlen(arr));//???未定义行为
printf("%d\n", strlen(arr+0));//strlen(char*)???未定义行为
printf("%d\n", strlen(*arr));//strlen(arr[0])???
printf("%d\n", strlen(arr[1]));//???
printf("%d\n", strlen(&arr));//???
printf("%d\n", strlen(&arr + 1));//???
printf("%d\n", strlen(&arr[0]) + 1);//???

4. Práctica de la matriz de caracteres (2)

char arr[] = "abcdef";

Nota: En este momento, almacenamos una cadena en la matriz, que termina con '\ 0'

①tamaño de ()

printf("%d\n", sizeof(arr));//sizeof(char[7])=7
printf("%d\n", sizeof(arr+0));//sizeof(char*)=4
printf("%d\n", sizeof(*arr));//sizeof(char)=1
printf("%d\n", sizeof(arr[1]));//sizeof(char)=1
printf("%d\n", sizeof(&arr[0]+1));//sizeof(char*)=4
printf("%d\n", sizeof(&arr));//sizeof(char(*)[7])=4
printf("%d\n", sizeof(*&arr));//sizeof(char[7])=7
printf("%d\n", sizeof(&*arr));//sizeof(char*)=4
printf("%d\n", sizeof(&arr+1));//sizeof(char(*)[4])=4

②strlen ()

printf("%d\n", strlen(arr));//6
printf("%d\n", strlen(arr+1));//5
printf("%d\n", strlen(&arr+1));//类型不匹配
printf("%p\n", strlen(&arr));//6  类型不匹配  strlen(char(*)[7])=6
printf("%d\n", strlen(&arr[0]));//strlen(char*arr[7])=6
printf("%d\n", strlen(*&arr));//char(*)[7]->char[7]  strlen(char[7])=6
printf("%d\n", strlen(&*arr));//char*arr[0]->char arr[0]->char *arr[0] strlen(char *arr[0])=6
printf("%d\n", strlen(&arr[1]+1));//char* arr[1]->char* arr[2] strlen(char* arr[2])=4 

5. El ejercicio del puntero al primer elemento de la cadena.

char* p = "abcdef";

Nota: En este momento, p es una variable de puntero que apunta al primer elemento de la cadena y su contenido es la dirección del primer elemento de la cadena.

①tamaño de ()

printf("%d\n", sizeof(p));//sizeof(char*)=4
printf("%d\n", sizeof(p + 1));//sizeof(char*)=4
printf("%d\n", sizeof(*p));//sizeof(char)=1
printf("%d\n", sizeof(p[0]));//sizeof(char)=1
printf("%d\n", sizeof(&p));//sizeof(char**)=4
printf("%d\n", sizeof(&p[1]+1));//sizeof(char*)=4
printf("%d\n", sizeof(*&p));//sizeof(char*)=4
printf("%d\n", sizeof(&*p));//sizeof(char**)=4

②strlen ()

printf("%d\n",strlen(p));//strlen(char*[0])=6	
printf("%d\n", strlen(p + 1));//strlen(char*[1])=5
printf("%d\n", strlen(*p));//strlen(char[0]) 类型不匹配
printf("%d\n", strlen(p[1]));//类型不匹配
printf("%d\n", strlen(&p));//类型不匹配
printf("%d\n", strlen(&p[1] + 1));//strlen(char *p[2])=4
printf("%d\n", strlen(*&p));//strlen(char*)=6
printf("%d\n", strlen(&*p));//strlen(char*)=6

6. Otros temas

Encuentra el resultado de salida del siguiente código

#include<stdio.h>
#include<windows.h>

int main()
{ 
   int a[4] = { 1, 2, 3, 4 };
   int* ptr1 = (int*)(&a + 1);
   int* ptr2 = (int*)((int)a + 1);
   printf("%x,%x", ptr1[-1], *ptr2);
   system("pause");
   return 0;
}

Acerca de ptr1 [-1]: Después de muchos ejercicios anteriores, podemos saber que & a es un puntero de matriz int (* a) [4], y luego +1 significa omitir toda la matriz, ptr1 apunta al último elemento de la matriz Position también es una posición especial, por lo que ptr [-1] es en realidad el último elemento de la matriz, que es 4

Acerca de * ptr2: El nombre de la matriz a representa la dirección del primer elemento de la matriz, (int) a significa que esta dirección está obligada a convertirse a tipo int, asumiendo que la dirección del primer elemento de la matriz es 0x100, entonces el resultado de (int) a es 0x100, y +1 el resultado es 0x101, y finalmente el puntero de ptr2 apunta a 0x101, que se imprime, porque se coacciona al tipo (int *), que ocupa 4 bytes, por lo que cuatro las palabras se leen al revés La sección se muestra en la siguiente figura:

 

Finalmente consiga 00 00 00 02

Según el orden de bytes little-endian (el orden superior está en la dirección superior), el resultado de salida es  2000000

 

Lo anterior es parte de mi comprensión de sizeof () y strlen (), la descripción es un poco aproximada, puede señalar lo que está mal ~~

 

 

Supongo que te gusta

Origin blog.csdn.net/weixin_43939602/article/details/109704098
Recomendado
Clasificación