quarta-feira, 11 de setembro de 2013

Tornando constante o ponteiro ou a memória apontada

O código a seguir apresenta a diferença entre tornar constante o valor do ponteiro ou valor na memória por ele apontada.

#include <stdio.h>  // scanf(), printf() 
#include <stdlib.h> // calloc(), free()

int main()
{

// declarar constante o conteúdo da memória apontada, mas
// o ponteiro poderá ser alterado
    const int *x = (const int *) calloc( 1, sizeof(int) );

// aviso por modificar o conteúdo da memória apontada
    scanf("%d", x);

// erro por tentar modificar o conteúdo da memória apontada
//    *x = 3210;

// declarar constante o conteúdo do ponteiro, mas
// o conteúdo da memória apontada poderá ser modificado
    int * const w = (int * const) calloc( 1, sizeof(int) );

// erro por tentar alterar o ponteiro
//    w = x;

// modificando o conteúdo da memória apontada
    *w = 123456;

    printf("x: %d\n", *x );
    printf("w: %d\n", *w );

// modificando o ponteiro
    x = w;

    printf("x: %d\n", *x );

    free( (void*)x );
    free( (void*)w );

    return 0;
}


sexta-feira, 16 de agosto de 2013

Uso de array por meio de alocação dinâmica de memória

A proposta deste código é usar alocação dinâmica de memória para suprir a função de array bi-dimensional:

double ptr[100][2];

Para tanto, esta declaração é substituída pela alocação de memória:

double **ptr = (double **) malloc(100*sizeof(double*));

Para cada ocorrência de *(ptr+j), sendo j de 0 a 99, alocar memória:

*(ptr+j)=(double *) malloc(2*sizeof(double));

O acesso aos elementos do array bi-dimensional ou da memória alocada dinamicamente pode ser feita da mesma forma:

*(*(ptr+j)+k))

ou

ptr[j][k],

variando j de 0 a 99, k de 0 a 1.

Aproveitando este projeto, também são apresentadas as funcionalidades de acesso ao relógio do sistema e formatação de data e hora.

Para a geração de dados, foi usada a função de randomização com parâmetros de faixa de valores, casas decimais e escala desejada.

Na impressão de dados numéricos, foi usada a configuração do ambiente de execução por meio da função 'setlocale()', tornando as saídas com ponto decimal em vírgulas.


#include <stdio.h> // printf(), fflush(), getchar(), stdin
#include <stdlib.h>       // malloc(), free(), srand(), rand(), RAND_MAX
#include <time.h>         // time_t, struct tm, time(), localtime()
#include <locale.h> // setlocale()

int main(){

 // dias da semana
 char dia[][14] = { 
  "Domingo", 
  "Segunda-Feira", 
  "Terça-Feira", 
  "Quarta-Feira",
        "Quinta-Feira", 
  "Sexta-Feira", 
  "Sábado" 
 };

 // data/hora em milésimos de segundos desde zero hora de 1900
 // ( time_t é um 'long long int' )
 time_t agora;
 
 // struct para relogio/calendario
 struct tm *calendario;

 // controle de loops
 int j, k;
 
 // declarar e alocar memória para 100 ponteiros de 'double'
 double **ptr = (double **) malloc(100*sizeof(double*));
 
 // para cada 1 dos 100 ponteiros de 'double' alocar memória para 2 'double'
 for (j=0; j<100;j++){
  *(ptr+j)=(double *) malloc(2*sizeof(double));
 }

 // inicializar a sequencia de randomização (semente) usando a hora corrente do sistema
 srand( (unsigned) time( NULL ) );

 // obter a hora corrente do sistema
 time( &agora );

 // converter a hora do sistema em estrutura 'hh:mm:ss, dd/mm/yy, weekDay, yearDay'
 calendario = localtime( &agora );

 // usar configurações regionais do sistema
 setlocale( LC_ALL, "" );

 // imprimir data e hora correntes
 printf( "%s - %02d/%02d/%04d - %02d:%02d:%02d - %dº dia do ano", 
  dia[calendario->tm_wday], // dia da semana (0=domingo, ..., 6=sábado)
  calendario->tm_mday,  // dia do mês
  calendario->tm_mon+1, // mês (0=janeiro, ..., 11=dezembro)
  calendario->tm_year+1900, // anos decorridos de 1900
  calendario->tm_hour,  // horas do dia (00~23)
  calendario->tm_min,  // minutos da hora (00~59)
  calendario->tm_sec,  // segundos do minuto (00~59)
  calendario->tm_yday+1 ); // dia do ano (0~365)
 
 // inicialização dos dados no array bi-dimensional
 for (j=0; j<100;j++){

  for (k=0; k<2; k++){

   *(*(ptr+j)+k) = 

    // gerar valores numéricos aleatórios
    // de 0.0 a 10.0 em intervalos de 0.125
    
    (int)(((double)rand() // 0 a RAND_MAX
    / (RAND_MAX+1))  // RAND_MAX
    * ((10.125 - 0.0) * 8.0)// faixa desejada * Ajuste de escala e casas decimais
    + 0.0)   // Deslocamento da faixa
    / 8.0;   // Ajuste de escala e casas decimais

  }
 }

 // impressão dos dados do array bi-dimensional
 for (j=0; j<100;j++){
  printf("\n");
  for (k=0; k<2; k++){
   printf( "%8.4lf\t", 
    //*(*(ptr+j)+k)
    ptr[j][k]
    );
  }
 }

 // liberar a memória de 2 'double' para cada um dos 100 ponteiros
 for (j=0; j<100;j++){
  free(*(ptr+j));
  *(ptr+j) = NULL;
 }

 // liberar a memória dos 100 ponteiros para 'double'
 free(ptr);
 ptr=NULL;

 // aguardar que teclem ENTER para encerrar o programa
 fflush(stdin);
 getchar();
 
 // return-code de encerramento do programa
 return 0;

}

segunda-feira, 22 de julho de 2013

Passando referência de uma função como argumento na chamada de outra função

No código a seguir, a função opera recebe 3 argumentos:
  • 1º argumento: um ponteiro para uma função que recebe 2 argumentos inteiros;
  • 2º argumento: um inteiro;
  • 3º argumento: um inteiro;
A função desejada para ser executada é passada no 1º argumento. Os outros argumentos são repassados para a função que será executada.


#include <stdio.h>

// declaração da assinatura da função a ser passada como argumento para
// outra função 
int (*f) (int, int);

int somar(int a, int b){
       return a+b;
}
int subtrair(int a, int b){
        return a-b;
}
int opera(int (*g) (int, int), int a, int b){
         return g(a, b);
}
int main(){
       printf( "\nsoma: %d\n", opera(somar, 25, 30 ));
       printf( "\nsubtração: %d\n", opera(subtrair, 25, 30 ));
       f = somar;
       printf( "\noutra soma: %d\n", opera(f, 25, 230 ));        
       f = subtrair;
       printf( "\noutra subtração: %d\n", opera(f, 25, 230 )
       return 0;
}



Para testar, foi usado o site ideone.com