Red de conocimientos sobre prescripción popular - Como perder peso - ¿Puedes decirme cómo utilizar punteros en lenguaje C?

¿Puedes decirme cómo utilizar punteros en lenguaje C?

Un puntero es una variable especial donde el valor almacenado en ella se interpreta como una dirección en la memoria. Para comprender un puntero, debemos comprender cuatro aspectos de un puntero: el tipo de puntero, el tipo de puntero, el valor del puntero o el área de memoria apuntada por el puntero y el área de memoria ocupada por el puntero mismo. . Expliquemoslos por separado.

Declaremos algunos consejos a modo de ejemplo:

Ejemplo 1:

(1)int * ptr;

(2 ) char * ptr;

(3)int * * ptr;

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

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

Si no comprende los últimos ejemplos, consulte el artículo que publiqué hace algún tiempo: & gt.

Tipo de puntero

Desde un punto de vista sintáctico, solo necesita eliminar el nombre del puntero de la declaración de puntero, y lo que queda es el tipo de puntero. Este es el tipo de puntero en sí. Echemos un vistazo al tipo de 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 de puntero es int(*)[3]

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

¿Cómo te va últimamente? ¿Es fácil saber el tipo de puntero?

El tipo al que apunta el puntero.

Cuando accede al área de memoria señalada por un puntero, el tipo señalado por el puntero determina cómo trata el compilador el contenido de esa área de memoria.

Sintácticamente, solo necesita eliminar el nombre del puntero y el declarador del puntero * a la izquierda del nombre en la declaración de declaración del puntero. 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 señalado por el puntero es int*

(4)int(* ptr)[3]; por el puntero es int()[3]

(5)int *(* ptr)[4] //El tipo al que apunta el puntero es int*()[4]

En el puntero En operaciones aritméticas, el tipo señalado por 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 señalado por el puntero" es uno de los puntos clave para dominar punteros uno. Leí muchos libros y descubrí que algunos libros mal escritos confundían los dos conceptos de punteros, por lo que la lectura era inconsistente y cuanto más leía, más confuso me sentía.

El valor del puntero, o el área de memoria o dirección a la que apunta el puntero.

El valor del puntero es el valor almacenado en el propio puntero. El compilador lo tratará como una dirección en lugar de un valor normal. En los programas de 32 bits, los valores de todos los punteros de tipo son números enteros de 32 bits, porque las direcciones de memoria en los programas de 32 bits tienen una longitud de 32 bits. El área de almacenamiento señalada por el puntero es el área de almacenamiento con una longitud de tamaño comenzando desde la dirección de almacenamiento representada por el valor del 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 cuya dirección comienza con XX; cuando decimos que un puntero apunta a una determinada área de memoria, es; equivalente a decir que el valor del puntero es la primera dirección de esta á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.

Cada vez que encuentres un puntero en el futuro, debes preguntar: ¿De qué tipo es este puntero? ¿De qué tipo es el puntero? ¿Adónde apunta el puntero?

El área de memoria ocupada por el propio puntero.

¿Cuánta memoria ocupa el puntero? Solo necesitas usar la función sizeof (tipo de puntero) para medirlo. En plataformas de 32 bits, el puntero ocupa 4 bytes de longitud.

El concepto de que el puntero en sí ocupa memoria es muy útil a la hora de determinar si una expresión de puntero es un valor l.

Operaciones aritméticas sobre punteros

Los punteros pueden sumar y restar números enteros. El significado de esta operación de punteros es diferente de la habitual suma y resta numérica. 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 se agrega a 1. El compilador lo maneja así: agrega el valor del puntero ptr a sizeof(int), y en el programa de 32 bits, se suma en 4. Debido a 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.

Debido a que la longitud del tipo char es un byte, ptr inicialmente se refiere a los cuatro bytes que comienzan desde la celda 0 de la matriz A, y ahora apunta a los cuatro que comienzan desde la celda 4 en la matriz A Bytes..

Podemos recorrer la matriz usando punteros y bucles. Ver ejemplos:

Ejemplo 3:

intarray[20];

int * ptr = array

...

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

...

for(I = 0;i<20;i++)

{

(* ptr)++ ;

ptr++;

}

Este ejemplo suma 1 al valor de cada celda en una matriz de números enteros. Dado que el puntero ptr se incrementa en 1 cada vez que pasa por el bucle, se puede acceder a la siguiente celda de la matriz cada vez que pasa por el bucle.

Mira este ejemplo nuevamente:

Ejemplo 4:

1. chara[20];

2. a;

...

...

3. ptr+= 5;

En este ejemplo, ptr más 5. el compilador lo maneja así: suma 5 veces sizeof(int) al valor del puntero ptr, que es 5 veces 4=20 en un programa de 32 bits. Debido a que la unidad de dirección son bytes, la dirección señalada por ptr actual es 20 bytes mayor que la dirección señalada por ptr más 5. En este ejemplo, ptr apunta a los primeros cuatro bytes de la celda 0 de la matriz A antes de sumar 5. Después de sumar 5, ptr ha señalado el rango legal de la matriz A. Aunque esta situación causará problemas en la aplicación, es posible en la sintaxis. Esto también ilustra la flexibilidad de los punteros.

Si en el ejemplo anterior, ptr se reduce en 5, entonces el proceso es similar, excepto que el valor de ptr se reduce en 5 veces sizeof(int), y la dirección apuntada por el nuevo ptr será inferior a la dirección señalada por el ptr original. Mover 20 bytes.

En resumen, después de agregar un número entero n al puntero ptrold, el resultado es un nuevo puntero ptrnew. El tipo de ptrnew es el mismo que el tipo de ptrold y el tipo de ptrnew es el mismo. como el tipo de control. El valor de ptrnew aumentará n veces sizeof (el tipo señalado por ptr old) bytes en comparación con el valor de sizeof (ptrold). En otras palabras, el área de memoria señalada por ptrnew se moverá n veces sizeof (el tipo ptrold señalado por ptrold) bytes hacia la dirección más alta que el área de memoria señalada por ptrold.

El resultado de restar el número entero n del puntero ptrold es un nuevo puntero ptrnew, cuyo tipo es el mismo que el 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 (tipo señalado por ptrold) bytes en comparación con el valor de ptrold. Es decir, el área de memoria señalada por ptrnew se moverá n veces el tamaño de (señalado por ptrold) a. la dirección más baja que el área de memoria señalada por ptr old)byte.

Operadores &; y *

Este es un operador de dirección, y * se denomina operador indirecto en el libro.

& El resultado de la operación de ampA es un puntero. El tipo de puntero es el tipo de A más un *. El tipo de puntero es el tipo de A. La dirección del puntero es la dirección. de A..

*p tiene varios resultados de operación. En resumen, el resultado de *p es lo que apunta P y 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

int * * ptr

p = &a;

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

* p = 24

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

ptr = &p;

//El resultado de &p es un puntero, y el tipo de puntero es el tipo de p más a*, aquí está int * *. El tipo señalado por el puntero es el tipo p, aquí es int*. La dirección señalada por el puntero es la dirección del propio puntero P.

* ptr = & ampb;

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

* * ptr = 34

//* El resultado de ptr es a lo que apunta PTR, en este caso el puntero. Si vuelve a realizar la operación * en este puntero, el resultado será 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 lista de punteros.

Los siguientes son algunos ejemplos de expresiones de puntero:

Ejemplo 6:

inta, b;

intarray[10];

int * pa

pa = & ampa; //& &

int * * ptr = &pa; //&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, arr también lo es un modo de 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.

Debido a que el resultado de una expresión de puntero es un puntero, la expresión de puntero también tiene cuatro elementos del puntero: el tipo de puntero, el tipo señalado por el puntero, el área de memoria señalada por el puntero, y la memoria ocupada por el propio puntero.

Bueno, cuando el puntero de resultado de una expresión de puntero obviamente tiene la memoria ocupada por el puntero mismo, la expresión de 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 memoria. De hecho, *ptr es el puntero pa.

Dado que pa tiene su propia ubicación en la memoria, entonces *ptr, por supuesto, también tiene su propia ubicación.

La relación entre matrices y punteros

Si no comprende la declaración de una matriz, consulte el artículo que publiqué hace algún tiempo: & gt.

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

Realización 8:

intarray[10]=, valor

...

.. .

valor = matriz[0] //También se puede escribir como: valor = * matriz

valor = matriz[3] //También se puede escribir como : valor = *(matriz +3);

valor = matriz[4];//También se puede escribir como: valor = *(matriz+4);

En En el ejemplo anterior, en términos generales, el nombre de la matriz representa la matriz en sí y su tipo es int [10]. Pero si la matriz se considera como un puntero, apunta a la celda 0 de la matriz y al tipo al que apunta. es el tipo de celda de la matriz, que es int. Por tanto, no sorprende que *array sea igual a 0. Del mismo modo, matriz+3 es un puntero a la tercera celda de la matriz, por lo que *(matriz+3) es igual a 3. Otros y así sucesivamente.

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

En En el ejemplo anterior, str es una matriz de tres celdas, cada celda de la matriz es un puntero y cada puntero apunta a una cadena. Si el nombre de la matriz de punteros str se considera un puntero, apunta a la celda 0 de la matriz, el tipo es char** y el tipo puntiagudo es char*.

*str también es un puntero, el 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, este es un ejemplo!", que es la dirección de la dirección 'h'. Str+1 también es un puntero que apunta a la celda 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 y apunta al primer carácter 'h' de "Hola, buenos días". ", etc.

Resumamos el tema de los nombres de matriz para matrices. Si se declara una matriz TYPEarray [n], el nombre de la matriz tiene dos significados: uno representa la matriz completa y el tipo es tipo [n]; El segundo es un puntero. El tipo de puntero es TYPE *, y el tipo señalado por el puntero es TYPE, que es el tipo de unidad de matriz. El área de memoria a la que apunta el puntero es la unidad de matriz 0. , que ocupa un área de memoria separada. Debido al área de almacenamiento ocupada por la unidad de matriz 0, el valor del puntero no se puede modificar, lo que significa que expresiones como array++ son incorrectas.

Se puede reproducir el nombre de la matriz. diferentes roles en diferentes expresiones.

p>

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 la expresión *array, la matriz actúa como un puntero, por lo que el resultado de esta expresión es el valor de la celda 0 de la matriz. Sizeof(*array) mide el tamaño de la celda de la matriz.

La expresión matriz +n (donde n = 0, 1, 2,...), la matriz es un puntero, por lo que el resultado de la matriz +n es un puntero, su tipo es TIPO* , apunta a El tipo es TIPO, que apunta a la enésima celda de la matriz. Entonces sizeof(array+n) mide el tamaño de un 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]. Lo inicializamos con la primera dirección de toda la matriz. En la declaración ptr = & en matriz, matriz representa la matriz misma.

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

int(* ptr)[10];

Luego, en un programa de 32 bits, existen:

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

sizeof(int[10])==40

sizeof(ptr)==4

De hecho, sizeof ( objeto) la medida es el tamaño del propio tipo de objeto, no el tamaño de ningún otro tipo.

La relación entre punteros y tipos de estructura

Puede declarar un puntero a un objeto de tipo de estructura.

Ejemplo 11:

Estructura

{

inta

intb

intc

}

my structs =;

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

MyStruct * ptr = & ampss;

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

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;

ptr-& gt;c ;

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

Respuesta:

* pstr//Visitado miembro a de ss.

*(pstr+1); //Miembro SS visitado b.

*(pstr+2)//Acceso miembro C de ss.

Aunque actualicé el código anterior en mi MSVC++6.0, debes saber que no es normal usar pstr para acceder a los miembros de la estructura. Para explicar por qué no es normal, veamos cómo acceder a cada elemento del array mediante un puntero:

Ejemplo 12:

int array[3]=;

int * pa = array

El método para acceder a las tres unidades del array a través del puntero pa es:

* pa//Unidad visitada 0.

*(pa+1); //Visité la unidad 1.

*(pa+2); //Visité la unidad 2.

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

Todos los compiladores de C/C++ siempre almacenan las unidades de matriz en un área de almacenamiento continuo al organizar las unidades de matriz, sin espacios entre las unidades.

Sin embargo, al almacenar miembros de un objeto de estructura, en ciertos entornos de compilación, es posible que se requiera alineación de palabras o alineación de palabras dobles u otros métodos de alineación, y es necesario agregar varios "bytes de relleno" entre dos miembros adyacentes. Esto puede generar espacios en blanco. de varios bytes entre miembros.

Por lo tanto, 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) acceda definitivamente al miembro de estructura B. Debido a que member A y puede haber algunos bytes de relleno entre los miembros B, probablemente *(pstr+1) simplemente accede 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 los miembros de la estructura, esta es una buena idea.

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

Relación entre punteros y funciones

Puedes declarar un puntero como puntero a una función.

intfun1(char*, int);

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

pfun 1 = diversión 1; >

....

....

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

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

Ejemplo 13:

int fun(char *);

inta

charstr[]= "abcdefghijklmn";

inta

p>

a = divertido(cadena);

...

...

intfun(char*s)

{

int num = 0;

for(inti = 0; i{

num+ = * s; s++;

}

returnnum

}

La función divertida en este ejemplo calcula la suma del código ASCII valores de cada carácter en la cadena. El nombre de la matriz también es un puntero. En una llamada de función, cuando str se pasa a S como parámetro real, el valor de str en realidad se pasa a S. La dirección señalada por. S es la misma que la dirección señalada por str, excepto que str y S Ocupan su propio espacio de almacenamiento Agregar S 1 al cuerpo de la función no significa que str 1 se agregue al mismo tiempo. conversión de tipo

Cuando inicializamos un puntero o le damos un puntero Al asignar, hay un puntero en el lado izquierdo del número de asignación y una expresión de puntero en el lado derecho del número de asignación. En el ejemplo anterior, en la mayoría de los casos, el tipo de puntero es el mismo que el tipo de expresión de puntero y el tipo al que apunta el puntero es el mismo. Los tipos a los que apuntan las expresiones de puntero son los mismos.

Ejemplo 14:

1. float TF = 12.3;

float * fptr = & ampf;

3. >

En el ejemplo anterior, si desea que el puntero P apunte al número real F, ¿qué debe hacer?

p = &f;

Porque es incorrecto. El tipo de puntero p es int*, apunta al tipo int. El resultado de la expresión &;f es un puntero de tipo float*, el tipo al que apunta es float. Los dos son inconsistentes y el método de asignación directa es. no es aceptable Al menos en mi MSVC ++ 6.0, la declaración de asignación del puntero requiere el mismo tipo en ambos lados del número de asignación, y el tipo al que apunta no es el mismo en otros compiladores. Probado, puedes intentarlo.

Para lograr nuestro objetivo, necesitamos realizar un "casting":

p = (int *)& f

Si hay un puntero p, debemos convertirlo; El tipo y el tipo al que apunta se cambian a TYEP*TYPE, luego el formato de sintaxis es:

(TYPE *)p;

El resultado de esta conversión es un nuevo puntero. , su 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. Y 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:

void fun(char *);

inta=125, b

fun((char *) )&a);

...

...

voidfun(número de caracteres)

{

charc

c = *(s+3)= *(s+0)= c;

c = *(s+2); *(s+2)= *(s+1)= c;

}

}

Tenga en cuenta que este 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 fun consiste en invertir el orden de los cuatro bytes de un número entero. ¿Te has dado cuenta? En la declaración de llamada de función, el resultado del parámetro &a es un puntero, su tipo es int* y el tipo al que apunta es int. El tipo de puntero de parámetro es char* y el tipo al que apunta es char. De esta manera, en el proceso de combinar parámetros reales y parámetros formales, se debe realizar la conversión del tipo int* al tipo char*. Combinado con este ejemplo, podemos imaginar el proceso de conversión del compilador: el compilador primero construye un puntero temporal char*temp, luego ejecuta temp = (char *)&;a, y finalmente pasa el valor de temp a S, por lo que final El resultado 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. ¿Se puede asignar un número entero directamente a un puntero como valor del puntero? Como la siguiente declaración:

unsignedinta

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

...

...

a = 20345686

ptr = 20345686//Nuestro propósito es dejar que 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).

Compílalo. Resulta que las dos últimas afirmaciones están equivocadas. ¿Entonces no podemos lograr nuestro objetivo? No, hay otro método:

unsignedinta

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

...

...

A=Un número debe representar una dirección legal;

ptr =(TIPO *) a;//Jaja, está bien.

Estrictamente hablando, (TYPE*) aquí es diferente de (TYPE*) en la conversión de tipo de puntero. (TIPO*) aquí significa tratar el valor del entero sin signo A como una dirección. Lo anterior enfatiza 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 la dirección señalada por el puntero, es decir, el valor del puntero, se puede sacar como un número entero. Absolutamente.

El siguiente ejemplo demuestra cómo tomar el valor de un puntero como un número entero y luego asignar el número entero como una dirección al puntero:

Ejemplo 16:

inta=123, b;

p>

int * ptr = & ampa;

char * str

b =(int)ptr //Obtiene el valor del puntero ptr como an. entero.

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

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

Problemas de seguridad de los punteros

Consulte el siguiente ejemplo:

Realización 17:

chars = ' a

int * ptr

ptr = (int *)&s;

* ptr = 1298;

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

Veamos otro ejemplo:

Realización 18:

1. chara

int * ptr = & ampa;< / p>

...

...

3.ptr++;

4.*ptr = 115; Este ejemplo se puede compilar y ejecutar. ¿Pero lo viste? En la tercera oración, después de que el puntero ptr se incrementa en 1, ptr apunta al área de almacenamiento en la dirección alta adyacente a la variable entera A. ¿Qué hay en esta área de almacenamiento? No lo sabemos. Puede haber un dato muy importante o incluso un código. ¡Y la cuarta oración en realidad escribe un dato en esta área de almacenamiento! Este es un grave error. Entonces, cuando usan punteros, los programadores deben tener muy claro: ¿Adónde apunta mi puntero? Al acceder a una matriz con un puntero, tenga cuidado de no exceder los límites inferior y superior de la matriz; de lo contrario, se producirán errores similares.

En la conversión de tipo forzada de punteros: ptr1=(TYPE*)ptr2, si sizeof (tipo de ptr2) es mayor que sizeof (tipo de ptr1), use el puntero ptr 1 para acceder al área de almacenamiento señalada. a por ptr 2. Seguro. Si sizeof (tipo de ptr 2) es menor que sizeof (tipo de ptr1), acceder a la memoria a la que apunta ptr 1 no es seguro.