Saltar para o conteúdo principal
Versão: 19

Ponteiro

Uma variável ou expressão ponteiro é uma referência a outra variável (incluindo matrizes e elementos de matriz), tabela, campo, ou objecto. Não há campo do tipo Pointer.

Os apontadores fornecem uma forma avançada (na programação) para se referir aos dados. Quando você usar a linguagem, você acessa vários objetos - em particular, tabelas, campos, variáveis, objetos e matrizes - simplesmente usando seus nomes. No entanto, muitas vezes é útil fazer referência a estes elementos e aceder aos mesmos sem conhecer os seus nomes. Isto é o que os indicadores lhe permitem fazer.

O conceito subjacente aos ponteiros não é assim tão incomum na vida cotidiana. Muitas vezes você se refere a algo sem saber sua identidade exata. Por exemplo, poderia dizer a um amigo: "Vamos dar uma volta no seu carro" em vez de "Vamos dar uma volta no carro com a placa 123ABD". Neste caso, está a referenciar o carro com a matrícula 123ABD, utilizando a frase "o seu carro". A frase "carro com matrícula 123ABD" é como o nome de um objecto, e utilizar a frase "o seu carro" é como utilizar um ponteiro para fazer referência ao objecto.

Ser capaz de se referir a algo sem conhecer a sua identidade exata é muito útil. De facto, o seu amigo poderia obter um carro novo, e a frase "o seu carro" continuaria a ser exata - continuaria a ser um carro e ainda poderia dar uma volta nele. Os ponteiros funcionam da mesma maneira. Por exemplo, um ponteiro poderia, de uma vez, referir-se a um campo numérico chamado Age, e mais tarde referir-se a uma variável numérica chamada Old Age. Em ambos os casos, o ponteiro faz referência a dados numéricos que poderiam ser utilizados num cálculo.

Pode usar apontadores para referenciar tabelas, campos, variáveis, matrizes, elementos de array, e objetos. A tabela a seguir dá um exemplo de cada tipo de dado:

TipoReferenciaçãoPara usarAtribuição
TabelavpTable:=->[Table]DEFAULT TABLE(vpTable->)n/a
CampovpField:=->[Table]FieldALERT(vpField->)vpField->:="John"
VariávelvpVar:=->VariableALERT(vpVar->)vpVar->:="John"
ArrayvpArr:=->ArraySORT ARRAY(vpArr->;>)COPY ARRAY (Arr;vpArr->)
Elemento ArrayvpElem:=->Array{1}ALERT (vpElem->)vpElem->:="John"
ObjectvpObj:=->myObjectALERT (vpObj->myProp)vpObj->myProp:="John"

Usando um ponteiro: Exemplo básico

É mais fácil explicar o uso de ponteiros através de um exemplo. Este exemplo mostra como acessar uma variável através de um ponteiro. Começamos por criar uma variável:

$MyVar:="Hello"

$MyVar é agora uma variável que contém a string "Olá". Agora podemos criar um ponteiro para $MyVar:

C_POINTER($MyPointer)  
$MyPointer:=->$MyVar

O símbolo -> significa "fazer um ponteiro para". Este símbolo é formado por um traço seguido por um sinal "maior que". Neste caso, ele recebe o ponteiro que faz referência ou "aponta para" $MyVar. Este ponteiro é atribuído ao MyPointer com o operador de atribuição.

$MyPointer é agora uma variável que contém um ponteiro para $MyVar. $MyPointer não contém "Olá", que é o valor em $MyVar, mas pode usar $MyPointer para obter este valor. A seguinte expressão devolve o valor em $MyVar:

$MyPointer->

Nesse caso, ela retorna a seqüência de caracteres "Olá". O símbolo -> , quando segue um ponteiro, faz referência ao objecto apontado. A isto chama-se desreferenciação.

É importante compreender que pode utilizar um ponteiro seguido do símbolo -> em qualquer lugar para o qual pudesse ter utilizado o objecto para o qual o ponteiro aponta. Isto significa que poderia usar a expressão $MyPointer-> em qualquer lugar onde pudesse usar a variável original $MyVar . Por exemplo, a linha seguinte exibe uma caixa de alerta com a palavra Olá nela:

ALERT($MyPointer->)

Pode também utilizar $MyPointer para alterar os dados em $MyVar. Por exemplo, a seguinte declaração armazena a string "Goodbye" na variável $MyVar:

$MyPointer->:="Goodbye"

Se examinar as duas utilizações da expressão $MyPointer->, verá que ela actua como se tivesse utilizado $MyVar em seu lugar. Em resumo, as duas linhas seguintes realizam a mesma ação - ambas apresentam uma caixa de alerta contendo o valor actual na variável $MyVar:

ALERT($MyPointer->)
ALERT($MyVar)

As duas linhas seguintes executam a mesma ação - ambas atribuem a string "Goodbye" a $MyVar:

$MyPointer->:="Goodbye"
$MyVar:="Goodbye"

Operadores de Ponteiros

Con:

  vPtrA e vPtrB apontam para o mesmo objecto
vPtrA:=->anObject
vPtrB:=->anObject
` vPtrC aponta para outro objecto
vPtrC:=->outroObject
OperaçãoSintaxeRetornaExpressionValor
IgualPonteiro = PonteiroParâmetrosvPtrA = vPtrBTrue
vPtrA = vPtrCFalse
DesigualdadePointer # PointerParâmetrosvPtrA # vPtrCTrue
vPtrA # vPtrBFalse

Principais usos

Ponteiros para tabelas

Em qualquer lugar que a língua espere ver uma tabela, pode usar um ponteiro desreferenciado para a tabela. Cria-se um ponteiro para uma mesa usando uma linha como esta:

$TablePtr:=->[anyTable]

Também pode obter um ponteiro para uma tabela usando o comando Tabela :

$TablePtr:=Table(20)

Pode usar o ponteiro desreferenciado em comandos, como este:

DEFAULT TABLE($TablePtr->)

Ponteiros a campos

Em qualquer lugar que a língua espere ver um campo, pode usar um ponteiro desreferenciado para referenciar o campo. Cria-se um ponteiro para um campo usando uma linha como esta:

$FieldPtr:=->[aTable]ThisField

Também pode obter um ponteiro para um campo usando o comando Field , por exemplo:

$FieldPtr:=Field(1;2)

Pode usar o ponteiro desreferenciado em comandos, como este:

OBJECT SET FONT($FieldPtr->;"Arial")

Ponteiros para variáveis locais

Quando se utilizam apontadores para processar ou variáveis locais, é necessário ter a certeza de que a variável apontada já está definida quando o apontador é utilizado. Tenha em mente que as variáveis locais são eliminadas quando o método que as criou tiver concluído a sua execução e as variáveis de processo são eliminadas no final do processo que as criou. Quando um ponteiro chama uma variável que já não existe, isto causa um erro de sintaxe no modo interpretado (variável não definida) mas pode gerar um erro mais grave no modo compilado.

Os ponteiros para variáveis locais permitem-lhe guardar variáveis de processo em muitos casos. Os ponteiros para variáveis locais só podem ser utilizados dentro do mesmo processo. No depurador, quando se mostra um ponteiro para uma variável local que tenha sido declarada noutro método, o nome do método original é indicado entre parênteses, após o ponteiro. Por exemplo, se escrever no Método1:

 $MyVar:="Hello world"
Method2(->$MyVar)

No Método2, o depurador exibirá $1 como se segue:

$1->$MyVar (Method1)

O valor de $1 será:

$MyVar (Method1)"Hello world"

Ponteiros para os elementos do array

Pode criar um ponteiro para um elemento de array. Por exemplo, as linhas seguintes criam um array e atribuem um ponteiro ao primeiro elemento do array a uma variável chamada $ElemPtr:

ARRAY REAL($anArray;10) //Cria um array
$ElemPtr:=->$anArray{1} //Cria um ponteiro para o elemento da array

Poderia usar o ponteiro desreferenciado para atribuir um valor ao elemento, como este:

$ElemPtr->:=8

Ponteiros a arrays

É possível criar um ponteiro para um array. Por exemplo, as seguintes linhas criam um array e atribuem um ponteiro ao array a uma variável chamada $ArrPtr:

ARRAY REAL($anArray;10) //Cria um array
$ArrPtr:=->$anArray //Cria um ponteiro para a array

É importante compreender que o ponteiro aponta para a matriz; ele não aponta para um elemento da matriz. Por exemplo, pode utilizar o ponteiro desreferenciado das linhas anteriores como este:

ORDENAR ARRAY($ArrPtr->;>) //Ordenar o array

Se precisar de se referir ao quarto elemento do array usando o ponteiro, faça desta maneira:

 ArrPtr->{4}:=84

Indicadores como parâmetros para os métodos

Pode passar um ponteiro como parâmetro para um método. Dentro do método, você pode modificar o objeto referenciado pelo ponteiro. Por exemplo, o seguinte método, takeTwo, toma dois parâmetros que são indicadores. Altera o objecto referenciado pelo primeiro parâmetro para caracteres maiúsculos, e o objecto referenciado pelo segundo parâmetro para caracteres minúsculos. Aqui está o método do projecto:

  //takeTwo project method
//$1 - Ponteiro para um campo de string ou variável. Alterar isto para maiúsculas.
//$2 - Apontador para um campo de string ou variável. Mudar isto para minúsculas.
$1->:=Uppercase($1->)
$2->:=Lowercase($2->)

A linha seguinte utiliza o método takeTwo para alterar um campo para caracteres maiúsculos e para alterar uma variável para caracteres minúsculos:

takeTwo(->[myTable]myField;->$MyVar)

Se o campo [myTable]myField contivesse a corda "jones", esta seria alterada para a corda "JONES". Se a variável $MyVar contivesse a string "HELLO", esta seria alterada para a string "olá".

No método takeTwo, e de facto, sempre que se utilizam apontadores, é importante que o tipo de dados do objecto a ser referenciado esteja correcto. No exemplo anterior, os apontadores devem apontar para algo que contenha um fio ou texto.

Ponteiros a ponteiros

Se gosta realmente de complicar as coisas, pode usar apontadores para referenciar outros apontadores. Considerem este exemplo:

 $MyVar:="Hello"
$PointerOne:=->$MyVar
$PointerTwo:=->$PointerOne
($PointerTwo->)->:="Goodbye"
ALERT(($PointerTwo->)->)

Exibe uma caixa de alerta com a palavra "Adeus".

Aqui está uma explicação de cada linha do exemplo:

  • $MyVar:="Hello" --> This line puts the string "Hello" into the variable $MyVar.
  • $PointerOne:=->$MyVar --> $PointerOne now contains a pointer to $MyVar.
  • $PointerTwo:=->$PointerOne --> $PointerTwo (a new variable) contains a pointer to $PointerOne, which in turn points to $MyVar.
  • ($PointerTwo->)->:="Goodbye" --> $PointerTwo-> references the contents of $PointerOne, which in turn references $MyVar. Por conseguinte ($PointerTwo->)-> faz referência ao conteúdo de $MyVar. Assim, neste caso, $MyVar é atribuído o "Adeus".
  • ALERTA (($PointerTwo->)->) --> O mesmo: $PointerTwo-> refere o conteúdo de $PointerOne, que por sua vez refere $MyVar. Por conseguinte ($PointerTwo->)-> faz referência ao conteúdo de $MyVar. Por conseguinte ($PointerTwo->)-> faz referência ao conteúdo de $MyVar.

A seguinte linha coloca "Olá" em $MyVar:

($PointerTwo->)->:="Hello"

A seguinte linha recebe "Olá" de $MyVar e coloca-o em $NewVar:

$NewVar:=($PointerTwo->)->

Importante: A desreferência múltipla requer parênteses.