04 diciembre 2006
Problemas
1.- Crear una funcion que reciba dos parametros del tipo punteros y que a traves de un menu nos permita ver el resultado de la suma, resta, multiplicacion y division de los dos numeros.
Validar que el divisor nunca sea menor a cero, si es asi, no debera realizar la operacion y debera indicarlo con un mensaje.
El menu puede ser algo como lo que se muestra a continuacion:
....(MENU DE OPERACIONES)......
1......... suma
2......... resta
3.......... multiplicacion
4.- ....... division
Comentarios: El parmetro que recibe la funcion podra ser del tipo que ustedes quieran (float, int, double, etc...)
2.- Generar dos vectores de dimensión 10 y construir un tercer vector del tipo puntero e
imprimirlo, cuyos componentes sean la suma de los dos anteriores.
Funciones con Punteros
/*
El Siguiente ejercicio lo que realiza es crear una funcion que reciba
* El procedimiento es el mismo
*/
using System.Collections.Generic;
using System.Text;
namespace punterosw_y_funciones
{
class Program
{
unsafe static void RecibePuntero(int* val)
{
Console.WriteLine("Este es el valor recibido: {0}",*val);
}
unsafe static void
{
int valor = 90;
int* pvalor = &valor;
Console.WriteLine("La Direccion donde se encuentra el valor: {0} y el valor de la direccion: {1}",(int)pvalor, *pvalor);
RecibePuntero(pvalor);
Console.ReadLine();
}
}
Utilización de Stackalloc
Este ejercicio pasenlo a la computadora. Recuerden modificar el proyecto para que les permita utilizar código inseguro.
El programa si funciona!
Que hace?: Declaramos un vector del tipo int, y otro vector del tipo puntero. Guardamos el contenido del vector original en otro vector del tipo puntero. Declaramos otro puntero que apunta a la direccion fisica de memoria donde se ecuentra el vector original.
Guradamos en el vector puntero los datos del vector original y lo incrementamos para que pueda seguir guradando datos en la siguiente direccion del tipo int.
Al finalzar de llenarlo, recorremos otro puntero que contiene la direccion original del vector y lo recorremos con otro ciclo for al cual le hacemos un incremento.
Este ejemplo esta basado en el tema de Punteros parte 2 Operadr Stackalloc creacion de pilas
using System;
using System.Collections.Generic;
using System.Text;
{
class Program
{
unsafe static void
{
int[] arreglo = new int[] { 1,3,4,5,6,7,6,4,3,2};// Un arreglo
int* pt = stackalloc int[10]; //Un puntero
int* ppt;// Un puntero sencillo
*pt = arreglo[0];// Aqui apuntamos a la direccion
ppt = pt;// Igualamos las direcciones donde se encuentra el inicio
for (int i = 0; i <>
{
*pt = arreglo[i];// Grabamos en esa direccion de memoria el contenido
pt++;// Nos movemos en memoria la distancia del tipo int para poder grabar en el siguiente espacio
}
// Como ya movimos el puntero pt de su lugar de origen, vamos a utilizar el puntero ppt que se encuentra en el lugar
//de inicio del vector orignal, de esa forma lo podemos recorrer.
for (int i = 0; i <>
{
Console.WriteLine("el arreglo: {0}", *ppt);
ppt++;//En este lugar estamos recorriendo nuevamente directametne la memoria. Recordemos que el puntero ppt apuntaba a la direccion de un puntero tipo vector, el cual a su ves apuntaba directamente a un vector del tipo int. No olvidemos que cuando utilizamos el incremento ++, lo que estamos haciendo es incrementando una posicion en memoria del tamaño del tipo del puntero. En este caso es del tipo INT (entero).
}
Console.ReadLine();
}
}
}
Punteros parte #2
Cuando se trabaja con punteros puede resultar interesante reservar una zona de memoria en la pila donde posteriormente se puedan ir
almacenando objetos. Precisamente para eso está el operador stackalloc, que se usa siguiéndose la siguiente sintaxis:
stackalloc
stackalloc reserva en pila el espacio necesario para almacenar contiguamente el número de objetos de tipo
stackalloc sólo puede usarse para inicializar punteros declarados como variables locales y sólo en el momento de su declaración.. Por ejemplo, un puntero pt que apuntase al principio de una región con capacidad para 100 objetos de tipo int se declararía con:
int * pt = stackalloc int[100];
Sin embargo, no sería válido hacer:
int * pt;
pt = stackalloc int[100]; // ERROR: Sólo puede usarse stackalloc en declaraciones
Aunque pueda parecer que stackalloc se usa como sustituto de new para crear tablas en pila en lugar de en memoria dinámica, no hay que confundirse: stackalloc sólo reserva un espacio contiguo en pila para objetos de un cierto tipo, pero ello no significa que se cree una tabla en pila. Las tablas son objetos que heredan de System.Array y cuentan con los miembros heredados de esta clase y de object, pero regiones de memoria en pila reservadas por stackalloc no. Por ejemplo, el siguiente código es inválido.
int[] tabla; int * pt = stackalloc int[100];
tabla = *pt; // ERROR: El contenido de pt es un int, no una tabla (int[])
Console.WriteLine(pt->Length); // ERROR: pt no apunta a una tabla
Sin embargo, gracias a que como ya se ha comentado en este tema el operador [] está redefinido para trabajar con punteros, podemos usarlo para acceder a los diferentes objetos almacenados en las regiones reservadas con stackalloc como si fuesen tablas. Por ejemplo, este código guarda en pila los 100 primeros enteros y luego los imprime:
class Stackalloc
{
public unsafe static void Main()
{
int * pt = stackalloc int[100];
for (int i=0; i<100; i++)
pt[i] = i;
for(int i=0; i<100; i++)
System.Console.WriteLine(pt[i]);
}
}
Fijación de variables apuntadas
Aunque un puntero sólo puede apuntar a datos de tipos que puedan almacenarse completamente en pila (o sea, que no sean ni objetos de tipos referencia ni estructuras con miembros de tipos referencia), nada garantiza que los objetos apuntado en cada momento estén almacenados en pila. Por ejemplo, las variables estáticas de tipo int o los elementos de una tabla de tipo int se almacenan en memoria dinámica aún cuando son objetos a los que se les puede apuntar con punteros.
Un uso frecuente de fixed consiste en apuntar a objetos de tipos para los que se puedan declarar punteros pero que estén almacenados en tablas, ya que ello no se puede hacer directamente debido a que las tablas se almacenan en memoria dinámica. Por ejemplo, copiar usando punteros una tabla de 100 elementos de tipo int en otra se haría así:
class CadenaInsegura {
public unsafe static void Main()
{
string s=”Hola”;
Console.WriteLine(“Cadena inicial: {0}”, s);
fixed (char * ps=s)
{
for (int i=0;i
Console.WriteLine(“Cadena final: {0}”, s);
}
}
La salida por pantalla de este último programa es:
Hola
AAAA
Cuando se modifiquen cadenas mediante punteros hay que tener en cuenta que, aunque para facilitar la comunicación con código no gestionado escrito en C o C++ las cadenas en C# también acaban en el carácter ‘\0’, no se recomienda confiar en ello al recorrerlas con punteros porque ‘\0’ también puede usarse como carácter de la cadena. Por ello, es mejor hacer como en el ejemplo y detectar su final a través de su propiedad Length.