Ver Mensaje Individual
  #24  
Antiguo 25-10-2012
Avatar de Al González
[Al González] Al González is offline
In .pas since 1991
 
Registrado: may 2003
Posts: 5.610
Reputación: 32
Al González Es un diamante en brutoAl González Es un diamante en brutoAl González Es un diamante en brutoAl González Es un diamante en bruto
Cita:
Empezado por roman Ver Mensaje
Algo que no me queda claro es en qué afectaría que la rutina de la API escribiera sobre el argumento. No recuerdo cómo funciona el paso de parámetros de tipo string, o cómo afecta el modificador const. Porque si el parámetro pasa a la pila, como otros parámetros, no tendría porque haber problemas, aunque quizá fuera necesario no usar const [...]
Con valores que tienen contadores de referencias, usar Const es más eficiente, se reduce en varias instrucciones el código máquina de la función que declara el parámetro. De lo contrario se añade una referencia más a la cuenta. Prescindir del Const sólo tiene sentido si el parámetro ha de usarse también como variable de trabajo (modificable) dentro de la función que declara el parámetro. Esta es una buena convención que vino a inculcar Borland, y en lo personal (y saliéndome un poco del tema) he de decir que la extiendo más allá de los parámetros que usan contadores de referencias, es decir, hasta con parámetros simples como los de tipo Integer suelo usar Const si la rutina no ha de modificar su valor (ahí no hay impacto en el código máquina generado, pero lo hago porque puede ser informativo para el programador que lea el código).

Respecto a la primera parte de tu duda, hice este ejemplo para ayudar a esclarecerla:

Código Delphi [-]
Procedure Modificar (C :PChar);
Begin
  StrCopy (C, '¡X!');
End;

Procedure Proc1 (S :String);
Begin
  Modificar (PChar (S));
End;

Procedure Proc2 (Const S :String);
Begin
  Modificar (PChar (S));
End;

procedure TForm1.Button1Click(Sender: TObject);
Var
  Nombre :String;
begin
  Nombre := Self.Name;

  // Antes de ser modificado el nombre
  ShowMessage ('El nombre del formulario es: ' + Nombre);
  ShowMessage ('El nombre del formulario es: ' + Self.Name);

  Proc1 (Nombre);  // O bien "Proc2 (Nombre);"

  // Después de ser modificado el nombre
  ShowMessage ('El nombre del formulario es: ' + Nombre);
  ShowMessage ('El nombre del formulario es: ' + Self.Name);
  
  Close;
end;

En pantalla aparecerán los resultados:

Cita:
El nombre del formulario es: Form1

El nombre del formulario es: Form1

El nombre del formulario es: ¡X!

El nombre del formulario es: ¡X!
Todo reside en el hecho, como habrás de recordar, de que las variables y parámetros de tipo String no guardan el valor de la cadena, sino un puntero hacia dicho valor.

Para quienes inicien en el tema de los punteros-cadena, lo siguiente puede ayudar a entenderlo:

-- Memoria RAM --
...
Byte 3400: 'F'
Byte 3401: 'o'
Byte 3402: 'r'
Byte 3403: 'm'
Byte 3404: '1'
Byte 3405: #0 (fin de la cadena)
...

Al comienzo Self.Name es igual a 'Form1', porque la propiedad Name del formulario es un puntero de valor 3400. Al procedimiento Modificar le termina llegando ese valor (3400) como parámetro puntero (PChar) y, en esa ubicación de memoria, cambia la 'F' por '¡', la 'o' por 'X', la 'r' por '!' y la 'm' por #0 (nuevo fin de la cadena).

Espero haberme explicado.
Responder Con Cita