Red de conocimiento informático - Conocimiento del nombre de dominio - Urgente. . ¿Puedo preguntar si un puntero a una función tiene alguna función especial? ¿Por qué necesitamos punteros a funciones?

Urgente. . ¿Puedo preguntar si un puntero a una función tiene alguna función especial? ¿Por qué necesitamos punteros a funciones?

Un puntero es una variable especial y el valor almacenado en ella se interpreta como una dirección en la memoria. Para comprender un puntero, debe comprender cuatro aspectos del puntero: el tipo de puntero, el tipo apuntado por el puntero, el valor del puntero o el área de memoria apuntada por el puntero y el área de memoria ocupada por el puntero. sí mismo. Expliquemos cada uno.

Primero declare algunos consejos como ejemplo:

Ejemplo 1:

(1)int*ptr;

(2 ) char*ptr;

(3)int**ptr;

(4)int(*ptr)[3]; (*ptr)[4];

Si no comprende los últimos ejemplos, consulte el artículo que publiqué hace algún tiempo<;lt;Cómo entender c y la declaración de tipos complejos de c> t;gt;.

Tipo de puntero

Desde un punto de vista sintáctico, solo necesita eliminar el nombre del puntero en la declaración de declaración del puntero, y la parte restante es el tipo del puntero. Este es el tipo de puntero en sí. Echemos un vistazo a los tipos de cada puntero en el Ejemplo 1:

(1)int*ptr; //El tipo de puntero es int*

(2)char*ptr; // El tipo de puntero es char*

(3)int**ptr; //El tipo de puntero es int**

(4)int(*ptr)[ 3];/ /El tipo del puntero es int(*)[3]

(5)int*(*ptr)[4] //El tipo del puntero es int*(* )[4]

¿Qué te parece? ¿No es una forma sencilla de averiguar el tipo de puntero?

El tipo señalado por el puntero

Cuando accede al área de memoria señalada por el puntero, el tipo señalado por el puntero determina qué hará el compilador en esa área de memoria. el contenido como debe ser.

Desde un punto de vista sintáctico, solo necesita eliminar el nombre del puntero en la declaración de declaración del puntero y el declarador del puntero * a la izquierda del nombre, y lo que queda es el tipo señalado por el puntero. . Por ejemplo:

(1)int*ptr; //El tipo señalado por el puntero es int

(2)char*ptr; //El tipo señalado por el puntero es char

(3)int**ptr; //El tipo al que apunta el puntero es int*

(4)int(*ptr)[3]; tipo señalado por el puntero El tipo es int()[3]

(5)int*(*ptr)[4] //El tipo señalado por el puntero es int*()[4] ]

En operaciones aritméticas de punteros, el tipo al que apunta el puntero juega un papel importante.

El tipo de puntero (es decir, el tipo del puntero en sí) y el tipo al que apunta el puntero son dos conceptos. A medida que se familiarice cada vez más con C, descubrirá que dividir el concepto de "tipo" mezclado con punteros en dos conceptos: "tipo de puntero" y "tipo al que apunta el puntero" es el punto clave para dominar punteros uno. Leí muchos libros y descubrí que algunos libros mal escritos mezclaban los dos conceptos de punteros, por lo que los libros parecían inconsistentes y cuanto más leía, más confusos se volvían.

El valor del puntero, o el área de memoria o dirección apuntada por el puntero

El valor del puntero es el valor almacenado en el propio puntero. Este valor será tratado como. una dirección del compilador y no es un valor general. En programas de 32 bits, el valor de todos los tipos de punteros es un entero de 32 bits, porque las direcciones de memoria en programas de 32 bits tienen 32 bits de longitud. El área de memoria a la que apunta el puntero es un área de memoria que comienza desde la dirección de memoria representada por el valor del puntero y tiene una longitud de tamaño de (el tipo al que apunta el puntero).

De ahora en adelante cuando decimos que el valor de un puntero es XX, equivale a decir que el puntero apunta a un área de memoria con la dirección encabezada por XX; cuando decimos que un puntero apunta a una determinada área de memoria, es; Equivale a decir que el valor del puntero es esta La primera dirección del área de memoria.

El área de memoria señalada por el puntero y el tipo señalado por el puntero son dos conceptos completamente diferentes. En el Ejemplo 1, el tipo al que apunta el puntero ya existe, pero como el puntero no se ha inicializado, el área de memoria a la que apunta no existe o no tiene sentido.

En el futuro, cada vez que encuentres un puntero, deberías preguntar: ¿Cuál es el tipo de este puntero? ¿A qué tipo apunta el puntero? ¿A dónde apunta este indicador?

El área de memoria ocupada por el puntero.

¿Cuánta memoria ocupa el puntero? Sólo necesitas usar la función sizeof (tipo de puntero) para probarlo y lo sabrás. En plataformas de 32 bits, el puntero ocupa 4 bytes de longitud.

El concepto de memoria ocupada por el puntero en sí es útil para determinar si una expresión de puntero es un valor l.

Operaciones aritméticas sobre punteros

Los punteros pueden sumar o restar un número entero. El significado de esta operación de punteros es diferente del significado de las operaciones numéricas ordinarias de suma y resta. Por ejemplo:

Ejemplo 2:

1.chara[20];

2. .

...

3. ptr;

En el ejemplo anterior, el tipo de puntero ptr es int* y el tipo al que apunta. to es int. Se inicializa para apuntar a la variable entera a. En la siguiente tercera oración, el puntero ptr aumenta en 1. El compilador lo maneja así: agrega sizeof(int) al valor del puntero ptr. En un programa de 32 bits, se agrega 4. Dado que la dirección está en bytes, la dirección señalada por ptr aumenta en 4 bytes desde la dirección original de la variable a hasta la dirección de dirección superior.

Dado que la longitud del tipo char es un byte, resulta que ptr apunta a los cuatro bytes comenzando desde la unidad 0 de la matriz a, y ahora apunta a la unidad 4 de la matriz a. de cuatro bytes.

Podemos usar un puntero y un bucle para recorrer una matriz, ver ejemplo:

Ejemplo 3:

intarray[20]; p>int*ptr=array;

...

//Aquí se omite el código para asignar valores a la matriz de enteros.

...

for(i=0;ilt;20;i)

{

(*ptr) <; /p>

ptr;

}

Este ejemplo suma 1 al valor de cada celda en la matriz de enteros. Dado que el puntero ptr se incrementa en 1 cada vez que se repite, se puede acceder a la siguiente unidad de la matriz cada vez que se repite.

Mira el ejemplo nuevamente:

Ejemplo 4:

1.chara[20]; a;

...

...

3. ptr =5

En este ejemplo, se agrega ptr 5; El compilador lo maneja así: suma 5 veces sizeof(int) al valor del puntero ptr. En un programa de 32 bits, se suma 5 veces 4 = 20. Dado que la unidad de dirección es el byte, la dirección señalada por el ptr actual se mueve 20 bytes hacia la dirección más alta que la dirección señalada por el ptr después de sumar 5. En este ejemplo, ptr antes de agregar 5 puntos a los cuatro bytes a partir de la unidad 0 de la matriz a. Después de agregar 5, ptr ya apunta fuera del rango legal de la matriz a. Aunque esta situación causará problemas en la aplicación, gramaticalmente está bien. Esto también refleja la flexibilidad de los punteros.

Si en el ejemplo anterior, ptr se resta por 5, entonces el proceso de procesamiento es similar, excepto que el valor de ptr se resta por 5 veces sizeof(int) y la dirección a la que apunta el nuevo ptr será mayor que la original. La dirección señalada por ptr se mueve 20 bytes hacia la dirección inferior.

Para resumir, después de agregar un número entero n a un puntero ptrold, el resultado es un nuevo puntero ptrnew. El tipo de ptrnew es el mismo que el tipo de ptrold. como el tipo señalado por ptrold. El valor de ptrnew será n multiplicado por sizeof (el tipo señalado por ptrold) bytes mayores que el valor de ptrold. Es decir, el área de memoria señalada por ptrnew se moverá n veces sizeof (el tipo señalado por ptrold) bytes a una dirección más alta que el área de memoria señalada por ptrold.

Después de restar un número entero n de un puntero ptrold, el resultado es un nuevo puntero ptrnew. El tipo de ptrnew es el mismo que el tipo de ptrold. El tipo señalado por ptrnew también es el mismo que el tipo. señalado por ptrold. El valor de ptrnew se reducirá n veces el tamaño de bytes (el tipo señalado por ptrold) en comparación con el valor de ptrold. Es decir, el área de memoria señalada por ptrnew se moverá a una dirección más baja que el área de memoria. señalado por ptrold por n veces sizeof (el tipo señalado por ptrold) bytes.

Operadores amp; y *

Aquí amp; es el operador de dirección, * se llama "operador indirecto" en el libro.

amp; El resultado de la operación de a es un puntero. El tipo del puntero es el tipo de más *. El tipo señalado por el puntero es el tipo de a. la dirección de un.

Los resultados de la operación de *p son variados. En resumen, el resultado de *p es lo que p apunta. Esta cosa tiene estas características: su tipo es el tipo señalado por p y la dirección que ocupa es la dirección señalada por p.

Ejemplo 5:

inta=12;

intb;

int*p; *ptr;

p=amp;a;

//El resultado de a es un puntero, el tipo es int*, el tipo puntiagudo es int y la dirección puntiaguda es una dirección.

*p=24;

// El resultado de *p, su tipo aquí es int y la dirección que ocupa es la dirección a la que apunta p. Es variable a.

ptr=amp;p;

//El resultado de amp;p es un puntero y el tipo de puntero es el tipo de p más un *, aquí está int**. El tipo al que apunta este puntero es el tipo de p, aquí es int*. La dirección señalada por este puntero es la dirección del propio puntero p.

*ptr=amp;b;

//*ptr es un puntero y el resultado de amp;b también es un puntero, y los tipos de estos dos punteros y el los tipos a los que apuntan son los mismos, por lo que no hay problema al usar amp;b para asignar un valor a *ptr.

**ptr=34;

//El resultado de *ptr es lo que apunta ptr, aquí es un puntero, haga otra * operación en este puntero y obtendrá el resultado. es una variable de tipo int.

Expresión de puntero

Si el resultado final de una expresión es un puntero, entonces la expresión se denomina expresión de puntero.

Los siguientes son algunos ejemplos de expresiones de puntero:

Ejemplo 6:

inta, b;

intarray[10]; /p>

int*pa;

pa=amp;a; //amp;a es una expresión de puntero.

int**ptr=amp;pa; //amp;pa también es una expresión de puntero.

*ptr=&b;//*ptr y &b son expresiones de puntero.

pa=array;

pa; //Esta también es una expresión de puntero.

Ejemplo 7:

char*arr[20];

char**parr=arr;//Si arr se considera un puntero, también lo es arr Expresión de puntero

char*str;

str=*parr; //*parr es una expresión de puntero

str=*(parr 1);/ /*(parr 1) es una expresión de puntero

str=*(parr 2); //*(parr 2) es una expresión de puntero

Dado el resultado de la expresión de puntero es un puntero, por lo que la expresión del puntero también tiene los cuatro elementos que tiene un puntero: el tipo del puntero, el tipo al que apunta el puntero, el área de memoria a la que apunta el puntero y la memoria ocupada por el puntero mismo.

Bueno, cuando el puntero de resultado de una expresión de puntero claramente tiene la memoria ocupada por el propio puntero, la expresión del puntero es un valor-l; de lo contrario, no es un valor-l.

En el ejemplo 7, a no es un valor l porque no ocupa memoria explícita. *ptr es un valor l, porque el puntero *ptr ya ocupa la memoria. De hecho, *ptr es el puntero pa. Dado que pa ya tiene su propia posición en la memoria, entonces *ptr ciertamente también tiene su propia posición.

La relación entre matrices y punteros

Si no comprende la declaración de matriz, consulte el artículo que publiqué hace algún tiempo Cómo comprender la complejidad de c. y c. Declaración de tipo gt;gt;.

El nombre de una matriz en realidad puede considerarse como un puntero. Mire el siguiente ejemplo:

Ejemplo 8:

intarray[10]=, valor

...

..

value=array[0];//También se puede escribir como: value=*array;

value=array[3];//También se puede escribir como: value=*(array 3 );

value=array[4]; //También se puede escribir como: value=*(array 4); En el ejemplo anterior, en términos generales, el nombre de la matriz matriz representa la matriz en sí, el tipo es int[10], pero si la matriz se considera como un puntero, apunta a la unidad 0 de la matriz, el tipo es int* y el El tipo señalado es el tipo de unidad de matriz, que es int. Por lo tanto, no es sorprendente que *array sea igual a 0. De la misma manera, la matriz 3 es un puntero al tercer elemento de la matriz, por lo que *(matriz 3) es igual a 3. Otros pueden deducirse por analogía.

Ejemplo 9:

char*str[3]={

"¡Hola, este es un ejemplo!",

"Hola, bien mañana .",

"Hola mundo"

};

chars[80];

strcpy(s, str[0] ) ;//También se puede escribir como strcpy(s, *str);

strcpy(s, str[1]); //También se puede escribir como strcpy(s, *(str). 1));

strcpy(s, str[2]); //También se puede escribir como strcpy(s, *(str 2)); Por ejemplo, str es una matriz de tres unidades. Cada elemento de la matriz es un puntero y cada uno de estos punteros apunta a una cadena. Si el nombre de la matriz de punteros str se considera un puntero, apunta a la unidad 0 de la matriz, su tipo es char** y el tipo al que apunta es char*.

*str también es un puntero, su tipo es char*, el tipo al que apunta es char y la dirección a la que apunta es la dirección del primer carácter de la cadena "¡Hola, esta muestra!" , esa es la dirección 'H'. str 1 también es un puntero, apunta a la unidad número 1 de la matriz, su tipo es char** y el tipo al que apunta es char*.

*(str 1) también es un puntero, su tipo es char*, el tipo al que apunta es char, apunta al primer carácter 'H' de "Hola, buenos días", etc. .

A continuación se resume la cuestión de los nombres de matrices para matrices. Cuando se declara una matriz TYPEarray[n], el nombre de la matriz tiene dos significados: primero, representa la matriz completa y su tipo es TYPE[n]; segundo, es un puntero y el tipo del puntero es TYPE; *, el tipo señalado por este puntero es TIPO, que es el tipo de unidad de matriz. El área de memoria señalada por este puntero es la unidad número 0 de la matriz. Tenga en cuenta que ocupa un área de memoria separada. la misma área que la unidad No. 0 de la matriz. Las áreas de memoria son diferentes. El valor de este puntero no se puede modificar, es decir, una expresión similar a una matriz es incorrecta.

La matriz de nombre de matriz puede desempeñar diferentes roles en diferentes expresiones.

En la expresión sizeof(array), el nombre de la matriz array representa la matriz en sí, por lo que la función sizeof mide el tamaño de toda la matriz en este momento.

En la expresión *matriz, la matriz actúa como un puntero, por lo que el resultado de esta expresión es el valor de la unidad 0 de la matriz. sizeof(*array) mide el tamaño de la unidad de matriz.

En la expresión matriz n (donde n=0, 1, 2, ....), la matriz actúa como un puntero, por lo que el resultado de la matriz n es un puntero y su tipo es TIPO* , el tipo al que apunta es TYPE y apunta a la enésima unidad de la matriz. Por lo tanto, sizeof(array n) mide el tamaño del tipo de puntero.

Ejemplo 10:

intarray[10];

int(*ptr)[10]; ;

En el ejemplo anterior, ptr es un puntero, su tipo es int(*)[10] y el tipo al que apunta es int[10]. para inicializarlo. En la declaración ptr=amp;array, array representa la matriz misma.

La función sizeof() se menciona en esta sección, así que déjame preguntar, ¿sizeof (nombre del puntero) mide el tamaño del puntero en sí o el tamaño del tipo al que apunta el puntero? La respuesta es la primera. Por ejemplo:

int(*ptr)[10];

En un programa de 32 bits, existe:

sizeof(int(*)[ 10] )==4

sizeof(int[10])==40

sizeof(ptr)==4

En realidad, sizeof(object) pruebas Lo que se genera es el tamaño del propio tipo del objeto, no el tamaño de otros tipos.

La relación entre punteros y tipos de estructura

Puede declarar un puntero a un objeto de tipo estructura.

Ejemplo 11:

structMyStruct

{

inta

intb; > intc;

}

MyStructss=;

// Declara el objeto de estructura ss e inicializa los tres miembros de ss en 20, 30 y 40.

MyStruct*ptr=amp; ss;

//Declara un puntero al objeto de estructura ss. Su tipo es MyStruct* y el tipo al que apunta es MyStruct.

int*pstr=(int*)&ss;

//Declara un puntero al objeto de estructura ss. Pero su tipo y el tipo al que apunta son diferentes de ptr.

¿Cómo acceder a las tres variables miembro de ss a través del puntero ptr?

Respuesta:

ptr-gt;a;

ptr-gt;b; p>

ptr-gt;c;

ptr-gt;b; p>

Además, ¿cómo puedo acceder a las tres variables miembro de ss a través del puntero pstr?

Respuesta:

*pstr; //Accedió al miembro a de ss.

*(pstr 1); //Accedió al miembro b de ss.

*(pstr 2)//Accedido miembro c de ss.

Aunque he depurado el código anterior en mi MSVC 6.0, debes saber que usar pstr para acceder a los miembros de la estructura es irregular. Para explicar por qué es irregular, veamos cómo usar los punteros. de la matriz:

Ejemplo 12:

intarray[3]=;

int*pa=array

El método de acceder a las tres unidades de la matriz a través del puntero pa es:

*pa; //Se accede a la unidad 0

*(pa 1);//La unidad 0 es accedió a la Unidad No. 1

*(pa 2); //Accedió a la Unidad No. 2

Desde el formato, es lo mismo que el método informal de acceder a los miembros de la estructura a través de punteros. .

Cuando todos los compiladores C/C organizan las unidades de una matriz, siempre almacenan cada unidad de la matriz en un área de almacenamiento continua, sin espacios entre unidades. Sin embargo, al almacenar cada miembro de un objeto de estructura, en un determinado entorno de compilación, es posible que se requiera alineación de palabras o alineación de palabras dobles u otra alineación, y es necesario agregar una cantidad de "bytes de relleno" entre dos miembros adyacentes, lo que da como resultado. en un espacio de varios bytes entre cada miembro.

Entonces, en el Ejemplo 12, incluso si *pstr accede a la primera variable miembro a del objeto de estructura ss, no hay garantía de que *(pstr 1) pueda acceder al miembro de estructura b.

Debido a que puede haber algunos bytes de relleno entre el miembro a y el miembro b, tal vez *(pstr 1) simplemente acceda a estos bytes de relleno. Esto también demuestra la flexibilidad de los punteros. Si su propósito es ver si hay bytes de relleno entre cada miembro de la estructura, este es un buen método.

La forma correcta de acceder a los miembros de la estructura a través de punteros debería ser utilizar el puntero ptr como en el Ejemplo 12.

La relación entre punteros y funciones

Un puntero se puede declarar como puntero a una función.

intfun1(char*, int);

int(*pfun1)(char*, int);

pfun1=fun1; p>....

....

inta=(*pfun1)("abcdefg", 7); //Llama a la función a través del puntero de función.

Los punteros se pueden utilizar como parámetros formales de funciones. En las declaraciones de llamada de función, las expresiones de puntero se pueden utilizar como parámetros reales.

Ejemplo 13:

intfun(char*);

inta;

charstr[]="abcdefghijklmn"; >

p>

a=fun(str);

...

...

intfun(char*s)

{

intnum=0;

for(inti=0;i{

num =*s; s;

}

returnnum;

}

La función fun en este ejemplo cuenta la suma de los valores del código ASCII de cada carácter en un string Como se mencionó anteriormente, la matriz. El nombre de también es un puntero. En una llamada de función, cuando str se pasa como parámetro real al parámetro formal s, el valor de str en realidad se pasa a s. s es la misma que la dirección señalada por str. Sin embargo, str y s ocupan cada uno su propio espacio de almacenamiento. La operación de incremento de s en el cuerpo de la función no significa que la operación de incremento de str se realice al mismo tiempo. p>

Conversión de tipo de puntero

Cuando inicializamos un puntero o asignamos un valor a un puntero, el lado izquierdo del número de asignación es un puntero y el lado derecho del número de asignación es un puntero expresión. En la mayoría de los casos, el tipo del puntero es. El tipo señalado por el puntero es el mismo que el tipo señalado por la expresión del puntero. floatf=12.3.

2. float*fptr=amp;

3. el puntero p apunta a un número real f, ¿qué debo hacer? ¿Utiliza la siguiente declaración?

p=amp

Incorrecto porque el tipo de puntero p es int*; Es int. El resultado de la expresión amp;f es un puntero, el tipo de puntero es float* y el tipo al que apunta es inconsistente. El método de asignación directa no funciona, al menos en mi MSVC 6.0. La declaración de asignación requiere que los tipos en ambos lados del número de asignación sean consistentes, y los tipos señalados también lo sean. No lo he probado en otros compiladores, pero usted puede probarlo.

Para lograr nuestro propósito, se necesita una "conversión de tipo forzada":

p=(int*)&f;

Si hay un puntero p, debemos cambiar su tipo; y el tipo señalado se cambia a TYEP*TYPE, entonces el formato de sintaxis es:

(TYPE*)p

El resultado de dicha conversión es un nuevo puntero y el nuevo puntero El tipo es TYPE *, el tipo al que apunta es TYPE y la dirección a la que apunta es la dirección a la que apunta el puntero original. Todos los atributos del puntero p original no han sido modificados.

Si una función utiliza un puntero como parámetro formal, la conversión del tipo de puntero también se producirá durante la combinación de los parámetros reales y los parámetros formales de la declaración de llamada de función.

Ejemplo 15:

voidfun(char*);

inta=125, b

fun((char*) amp; ; a);

...

...

voidfun(char*s)

{

charc;

c=*(s 3); *(s 3)=*(s 0); *(s 0)=c; s 2);*(s 2)=*(s 1);*(s 1)=c;

}

}

Ten en cuenta esto es un programa de 32 bits, por lo que el tipo int ocupa cuatro bytes y el tipo char ocupa un byte. La función de diversión es invertir el orden de los cuatro bytes de un número entero. ¿Observó? En la declaración de llamada de función, el resultado del parámetro real a es un puntero, su tipo es int* y el tipo al que apunta es int. El tipo de puntero de parámetro formal es char* y el tipo al que apunta es char. De esta manera, durante la combinación de parámetros reales y parámetros formales, debemos realizar una conversión del tipo int* al tipo char*. Combinando este ejemplo, podemos imaginar el proceso de conversión del compilador de esta manera: el compilador primero construye un puntero temporal char*temp, luego ejecuta temp=(char*)amp;a y finalmente pasa el valor de temp a s. Entonces el resultado final es: el tipo de s es char*, el tipo al que apunta es char y la dirección a la que apunta es la primera dirección de a.

Ya sabemos que el valor de un puntero es la dirección a la que apunta el puntero. En un programa de 32 bits, el valor del puntero es en realidad un entero de 32 bits. ¿Es posible utilizar un número entero como valor de un puntero y asignarlo directamente al puntero? Como la siguiente declaración:

unsignedinta;

TYPE*ptr; //TYPE es tipo int, char o estructura, etc.

...

...

a=20345686;

ptr=20345686 // Nuestro propósito es utilizar The el puntero ptr apunta a la dirección 20345686 (decimal

)

ptr=a; //Nuestro propósito es hacer que el puntero ptr apunte a la dirección 20345686 (decimal)

Compilar. Pruébalo. Resulta que las dos últimas afirmaciones son erróneas. ¿Entonces nuestro objetivo no se puede lograr? No, hay otra manera:

unsignedinta;

TYPE*ptr; //TYPE es int, char o tipo de estructura, etc.

...

...

a=un número, este número debe representar una dirección legal

ptr =( TYPE*)a;//Jaja, eso es todo.

Estrictamente hablando, el (TIPO*) aquí es diferente del (TIPO*) en la conversión de tipo de puntero.

(TIPO*) aquí significa tratar el valor del entero sin signo a como una dirección. Se enfatizó anteriormente que el valor de a debe representar una dirección legal; de lo contrario, se producirá un error de operación ilegal cuando use ptr.

Piense si se puede revertir y la dirección a la que apunta el puntero, es decir, el valor del puntero, se puede sacar como un número entero. Absolutamente. El siguiente ejemplo demuestra cómo sacar el valor de un puntero como un número entero y luego asignar el número entero como una dirección a un puntero:

Ejemplo 16:

inta =123, b;

int*ptr=amp; a;

char*str;

b=(int)ptr //Pon el puntero ptr Se toma el valor como un número entero.

str=(char*)b; //Asigna el valor de este entero al puntero str como dirección.

Ahora ya sabemos que el valor de un puntero se puede sacar como un número entero, o se puede asignar un valor entero a un puntero como una dirección.

Problemas de seguridad del puntero

Mire el siguiente ejemplo:

Ejemplo 17:

chars='a';

int*ptr;

ptr=(int*)&s;

*ptr=1298

El puntero ptr es un puntero int* A; de tipo, el tipo al que apunta es int. La dirección a la que apunta es la primera dirección del s. En un programa de 32 bits, el tipo s ocupa un byte y el tipo int ocupa cuatro bytes. La última declaración no solo cambia el byte ocupado por s, sino que también cambia los tres bytes en la dirección alta adyacente a s. ¿Para qué sirven estos tres bytes? Sólo el compilador lo sabe, y es poco probable que la persona que escribió el programa lo sepa. Tal vez estos tres bytes almacenen datos muy importantes, tal vez estos tres bytes sean un código del programa y, debido a su uso descuidado de los punteros, ¡los valores de estos tres bytes han sido cambiados! Esto puede provocar errores de bloqueo.

Veamos otro ejemplo:

Ejemplo 18:

1. chara; a;

...

...

3. >

Este ejemplo se puede compilar y ejecutar. ¿Pero lo viste? En la tercera oración, después de incrementar el puntero ptr en 1, ptr apunta a un área de almacenamiento en la dirección de dirección alta adyacente a la variable entera a. ¿Qué hay en esta zona de almacenamiento? No lo sabemos. Es posible que sea un dato muy importante, o tal vez incluso un fragmento de código. ¡Y la cuarta oración en realidad escribe un dato en esta área de almacenamiento! Este es un grave error. Entonces, al usar punteros, los programadores deben tener muy claro: ¿hacia dónde apunta exactamente mi puntero? Al acceder a una matriz con un puntero, tenga cuidado de no exceder los límites superior e inferior de la matriz; de lo contrario, se producirán errores similares.

En la conversión de tipo forzada del puntero: ptr1=(TYPE*)ptr2, si sizeof (tipo de ptr2) es mayor que sizeof (tipo de ptr1), entonces use el puntero ptr1 para acceder al almacenamiento al que apunta. por ptr2 La zona es segura. Si sizeof (tipo de ptr2) es menor que sizeof (tipo de ptr1), no es seguro utilizar el puntero ptr1 para acceder al área de almacenamiento señalada por ptr2. 2008 Baidu