Você está aqui: Delphi ::: Dicas & Truques ::: Ponteiros, Referências e Memória |
Como usar nil para testar ou indicar que um ponteiro Delphi não referencia nenhuma posição de memóriaQuantidade de visualizações: 15051 vezes |
O propósito dos ponteiros é nos permitir acessar e manipular os valores de outras variáveis. Isso é feito acessando-se diretamente o endereço de memória destas variáveis. Porém, há situações nas quais queremos testar se um determinado ponteiro está realmente apontando para um local na memória. Veja o seguinte trecho de código:---------------------------------------------------------------------- Se precisar de ajuda com o código abaixo, pode me chamar no WhatsApp +55 (62) 98553-6711 (Osmar) ---------------------------------------------------------------------- procedure TForm1.Button1Click(Sender: TObject); var pvalor: ^integer; begin // vamos exibir o valor da variável referenciada pelo // ponteiro pvalor ShowMessage(IntToStr(pvalor^)); end; Ao executarmos este código nós teremos um valor aleatório sendo exibido (e um warning do tipo W1036 Variable 'pvalor' might not have been initialized. Isso acontece porque criamos um ponteiro para um Integer mas não indicamos o endereço da variável para a qual ele aponta, ou seja, até o momento este ponteiro é nulo (não aponta para nenhuma posição de memória). Mova a declaração do ponteiro para a seção interface e verá que código compilará mas teremos uma exceção do tipo EAccessViolation (Exception class EAccessViolation with message 'Access violation at address ... in module ...). Clássico erro de lógica. Estamos tentando acessar dados não existentes na memória. Esta situação pode ser evitada testando se o ponteiro ainda é nulo antes de tentarmos desreferenciá-lo. Veja: ---------------------------------------------------------------------- Se precisar de ajuda com o código abaixo, pode me chamar no WhatsApp +55 (62) 98553-6711 (Osmar) ---------------------------------------------------------------------- procedure TForm1.Button1Click(Sender: TObject); begin // vamos exibir o valor da variável referenciada pelo // ponteiro pvalor if pvalor = nil then ShowMessage('O ponteiro ainda é nulo.') else ShowMessage(IntToStr(pvalor^)); end; Note que movi a declaração do ponteiro para a secão interface, de forma a torná-la global. Isso evita que o ponteiro seja automaticamente inicializado (o que sempre acontece com as variáveis locais). Ao executar o código novamente você verá a mensagem indicando que o ponteiro ainda é nulo. Podemos também usar nil para, explicitamente, marcar um ponteiro como nulo, ou seja, definir que o ponteiro não aponta para nenhum local na memória. Comece declarando as variáveis abaixo na seção interface do formulário: valor: Integer; pvalor: ^Integer; Em seguida coloque o código abaixo no evento Click de um botão: ---------------------------------------------------------------------- Se precisar de ajuda com o código abaixo, pode me chamar no WhatsApp +55 (62) 98553-6711 (Osmar) ---------------------------------------------------------------------- procedure TForm1.Button1Click(Sender: TObject); begin // vamos atribuir um valor à variável valor valor := 14; // vamos "apontar" nosso ponteiro para o local de // memória da variável valor pvalor := @valor; // vamos exibir o valor da variável apontada por pvalor ShowMessage(IntToStr(pvalor^)); // vamos marcar pvalor como nulo pvalor := nil; // vamos causar um EAccessViolation já que pvalor // não aponta para nenhum local na memória agora ShowMessage(IntToStr(pvalor^)); end; Sempre que marcamos um ponteiro como nil, a memória até então ocupada por ele é liberada para uso por parte do sistema operacional ou demais programas. Este procedimento ajuda a evitar os vazamentos de memória (memory leak) tão frequentes em códigos que trabalham com memória alocada dinamicamente. Para fins de compatibilidade, esta dica foi escrita usando Delphi 2009. |
![]() |
Delphi ::: Dicas & Truques ::: MIDI Musical Instrument Digital Interface, Mapeamento e sequenciamento MIDI, Entrada e saída MIDI |
Como retornar uma lista dos dispositivos de saída MIDI no sistema usando DelphiQuantidade de visualizações: 11176 vezes |
Em algumas ocasiões nós precisamos obter uma lista dos dispositivos de saída MIDI no sistema, talvez com o propósito de selecionar um determinado dispositivo em uma ListBox ou ComboBox. O trecho de código abaixo mostra como isso pode ser feito. O primeiro passo é declarar uma variável do tipo TMidiOutCaps. Este registro está declarado na unit MMSystem.pas e é uma tradução da estrutura MIDIOUTCAPS da API do Windows. Entre outros tipos de dados, esta estrutura possui um membro szPname que retorna o nome do dispositivo. Na unit MMSystem.pas este membro está declarado como array[0..MAXPNAMELEN-1] of AnsiChar, ou seja, uma matriz de AnsiChar que será preenchida pela API do Windows e terá seu final marcado com o caractere null (NULL terminated string). Note a conversão deste valor para o tipo String no momento de inserí-lo no ComboBox. Em versões anteriores do Delphi (estou escrevendo este código no Delphi 2009) podíamos usar a função StrPas() para esta finalidade. O passo seguinte é obter a quantidade de dispositivos de saída MIDI. Isso é feito com uma chamada à função midiOutGetNumDevs da API do Windows. Uma vez obtida a quantidade de dispositivos nós usamos um laço for e, no corpo deste laço, usamos o valor da variável de controle i para efetuar uma chamada à função midiOutGetDevCaps(), também da API do Windows: midiOutGetDevCaps(i, @MidiOutCaps, sizeof(TMidiOutCaps)); Esta função recebe o identificador do dispositivo (um valor inteiro começando em 0 e indo até a quantidade de dispositivos - 1), um ponteiro para um registro MidiOutCaps e o tamanho em bytes do registro. Se a função for executada com sucesso, o registro MidiOutCaps será preenchido com várias informações úteis, tais como o nome do dispositivo, o ID do fabricante, o ID do produto, versão do driver, tipo do dispositivo MIDI, número de vozes suportadas, número máximo de notas que podem ser tocadas simultaneamente, etc. Para finalizar, nós acessamos o campo szPname do registro MidiOutCaps e o adicionamos no ComboBox. Veja o código completo a seguir: ---------------------------------------------------------------------- Se precisar de ajuda com o código abaixo, pode me chamar no WhatsApp +55 (62) 98553-6711 (Osmar) ---------------------------------------------------------------------- procedure TForm1.Button2Click(Sender: TObject); var i: Integer; MidiOutCaps: TMidiOutCaps; // este registro (record) está definido em MMSystem.pas erro: Word; begin // uses MMSystem ComboBox2.Clear; // midiOutGetNumDevs retorna a quantidade de dispositivos de saída MIDI no sistema for i := 0 to midiOutGetNumDevs - 1 do begin // vamos obter o dispositivo identificado pela variável i (uDeviceID) erro := midiOutGetDevCaps(i, @MidiOutCaps, sizeof(TMidiOutCaps)); if erro <> MMSYSERR_NOERROR then raise Exception.Create('Não foi possível obter a lista de dispositivos ' + 'de saída MIDI'); // vamos adicionar o nome do dispositivo no ComboBox ComboBox2.Items.Add(StrPas(MidiOutCaps.szPname)); end; end; Ao executar este código o ComboBox será preenchido com valores semelhantes à: Microsoft GS Wavetable SW Synth MPU-401 Nas demais dicas relacionadas a este assunto você deverá sempre indicar o dispositivo de saída MIDI. Geralmente você poderá fornecer os valores 0 ou 1 para as funções MIDI que pedem o ID do dispositivo de saída. Para fins de compatibilidade esta dica ou anotação foi escrita usando Delphi 2009. |
Delphi ::: Dicas & Truques ::: Matemática e Estatística |
Como obter o resultado de uma divisão de inteiros, incluindo o resto, usando a procedure DivMod() do DelphiQuantidade de visualizações: 16043 vezes |
Em algumas situações precisamos obter o resultado de uma divisão de inteiros e gostaríamos de obter também o resto da divisão, ou seja, se dividirmos 10 por 3 o resultado será 3 (3 x 3 = 9) e o resto será 1. A procedure DivMod(), presente na unit Math nos permite fazer isso. Ela requer quatro argumentos: ---------------------------------------------------------------------- Se precisar de ajuda com o código abaixo, pode me chamar no WhatsApp +55 (62) 98553-6711 (Osmar) ---------------------------------------------------------------------- procedure DivMod(Dividend: Integer; Divisor: Word; var Result, Remainder: Word); Veja que fornecemos o dividendo e o divisor como Integer e Word mas, as variáveis que receberão o resultado e o resto da divisão deverão ser passadas por referência. Veja um exemplo: ---------------------------------------------------------------------- Se precisar de ajuda com o código abaixo, pode me chamar no WhatsApp +55 (62) 98553-6711 (Osmar) ---------------------------------------------------------------------- procedure TForm2.Button1Click(Sender: TObject); var dividendo, divisor: Integer; resultado, resto: Word; begin // uses Math // vamos dividir 10 por 3 dividendo := 10; divisor := 3; DivMod(dividendo, divisor, resultado, resto); // vamos exibir o resultado ShowMessage('Resultado da divisão: ' + IntToStr(resultado)); // vamos exibir o resto ShowMessage('Resto da divisão: ' + IntToStr(resto)); end; Note que DivMod() realiza seu trabalho e guarda os resultados nas variáveis resultado e resto, que, como vimos na assinatura da procedure, devem ser fornecidas por referência. Para fins de compatibilidade, esta dica foi escrita usando Delphi 2009. |
Delphi ::: Data Access Controls (Controles de Acesso a Dados) ::: TClientDataSet |
Como usar a propriedade Bof para verificar se estamos no primeiro registro do TClientDataSet do DelphiQuantidade de visualizações: 11073 vezes |
Em algumas situações gostaríamos de verificar se já estamos no primeiro registro do TClientDataSet, ou seja, estamos percorrendo todos os registros do dataset de trás para frente e queremos saber se já estamos no primeiro. Para isso podemos usar a propriedade Bof da classe TClientDataSet. Esta propriedade retorna true se estivermos no primeiro registro e false em caso contrário. Veja um trecho de código no qual usamos um laço while para percorrer todos os registros de um TClientDataSet de trás para frente. Note o uso da propriedade Bof para finalizar as iterações do laço: ---------------------------------------------------------------------- Se precisar de ajuda com o código abaixo, pode me chamar no WhatsApp +55 (62) 98553-6711 (Osmar) ---------------------------------------------------------------------- procedure TForm3.Button4Click(Sender: TObject); begin // vamos percorrer todos os registros do TClientDataSet // de trás para frente ClientDataSet1.Last; // vamos para o último registro // e agora disparamos um laço While while not ClientDataSet1.Bof do begin // vamos mostrar em um TMemo os valores do primeiro // campo de cada registro Memo1.Lines.Add(ClientDataSet1.FieldByName('id').AsString); // vamos mover para o registro anterior ClientDataSet1.Prior; end; end; A propriedade Bof é verdadeira quando: a) Abrimos um dataset. b) Efetuamos uma chamada ao método First (primeiro) do dataset. c) Chamamos o método Prior (anterior) do dataset e a chamada falha porque o registro atual já é o primeiro registro no dataset. d) Efetuamos uma chamada ao método SetRange em uma faixa de dados ou dataset vazio. Esta dica foi escrita e testada no Delphi 2009. |
Desafios, Exercícios e Algoritmos Resolvidos de Delphi |
Veja mais Dicas e truques de Delphi |
Dicas e truques de outras linguagens |
Códigos Fonte |
![]() Diga adeus às planilhas do Excel e tenha 100% de controle sobre suas contas a pagar e a receber, gestão de receitas e despesas, cadastro de clientes e fornecedores com fotos e histórico de atendimentos. Código fonte completo e funcional, com instruções para instalação e configuração do banco de dados MySQL. Fácil de modificar e adicionar novas funcionalidades. Clique aqui e saiba mais |
![]() Tenha o seu próprio sistema de controle de estoque web. com cadastro de produtos, categorias, fornecedores, entradas e saídas de produtos, com relatórios por data, margem de lucro e muito mais. Código simples e fácil de modificar. Acompanha instruções para instalação e criação do banco de dados MySQL. Clique aqui e saiba mais |
Linguagens Mais Populares |
1º lugar: Java |