Linha | Codigo |
001 | // Prof. Leo^nidas - http://www.matematica.br http://line.ime.usp.br |
002 | // MAC0122 - 2017/09 |
003 | |
004 | // Introducao aos apontadores em C |
005 | // Principio: os sistema operacionais alocam memoria de modo consecutivo, ou seja, para "int a, b;" |
006 | // o espaco para o 'a' estara' ao lado do espaco para o 'b'. No Linux o espaco do 'a' vem antes (i.e., alocacao "crescente"). |
007 | // Se voce^ usa outro sistema operacional, faca alguns testes para descobrir... (veja o bloco comentado com /* e */) |
008 | |
009 | // gcc -fsanitize=address -g -o introducao_apontadores introducao_apontadores.c |
010 | |
011 | #include <stdio.h> |
012 | |
013 | int main (void) { |
014 | int a, b, c; // os espacos para estas variaveis estarao consecutivos |
015 | int *ap_a = &a, *ap_b = &b, *ap_c = &c; // declarando apeontadores e fazendo-os apontar para as variaveis 'a, b, c': '&' devolve o endereco da variavel |
016 | float x, y, z; |
017 | float *ap_x = &x, *ap_y = &y, *ap_z = &z; // idem para 'x, y, z' |
018 | |
019 | int M[2][3][4], conta = 1, i, j, k, *p; // para teste com matrizes/"arranjos" |
020 | |
021 | // Agora vamos atribuir valores `as variaveis 'a,b,c,x,y,z' a partir de seus apontadores: |
022 | *ap_a = 1; *ap_b = 3; *ap_c = 5; // operador '*' devolve conteudo apontado (logo aplicavel apenas a apontadores) |
023 | *ap_x = 1; *ap_y = 3; *ap_z = 5; // assim, estamos atribuindo valores `as variaveis 'a,b,c,x,y,z'! |
024 | printf("a=%d, b=%d, c=%d\nx=%.1f, y=%.1f, z=%.1f\n", a, b, c, x, y, z); // devera imprimir: "a=1, b=3, c=5" e "x=1.0, y=3.0, z=5.0" |
025 | |
026 | /* Esta e' a vantagem de usar comando de linha (quando necessario e' facil "desligar" um bloco inteiro |
027 | // Se fizer uma entrada via teclado, pode usar o "scanf" com os apontadores |
028 | printf("Digitar um inteiro e um float: "); |
029 | scanf("%d %f", ap_a, ap_x); // passa os enderecos das variaveis 'a' e 'x' |
030 | printf("a=%d, x=%.1f\n", a, x); // logo imprime os valores digitados |
031 | */ |
032 | |
033 | // Agora facamos um teste com um agregado de dados do tipo matriz |
034 | // Ao declarar um vetor "int v[5];", reserva-se 5 posicoes para "int" sendo |
035 | // a primeira para X, entao a segunda para X+1 e assim por diante (supondo "end. crescente") |
036 | // Ao declarar uma matriz "int m[3][4];" reserva-se 3*4 posicoes, sendo |
037 | // * X, X+1, X+2 para a primeira linha (m[0]) |
038 | // * X+3, X+4, X+5 para a segunda linha (m[1]) e assim por diante |
039 | // Ao declarar uma matriz "int m[2][3][4];" reserva-se 2*3*4 posicoes, sendo |
040 | // * X, X+1, X+2, X+3 para a "primeira" matriz m[0][0] (m[0][0][0] ate m[0][0][3]) |
041 | // * X+3, X+4, X+5, X+6 para a "segunda" matriz m[0][1] (m[0][1][0] ate m[0][1][3]) e assim por diante |
042 | // PORTANTO, "M[i][j]" comporta-se com um vetor, ou seja, havendo uma funcao que tenha vetor para parametro formal, |
043 | // pode receber como parametro efetivo "M[i][j]". |
044 | // Exercicio: Implemente uma funcao 'produtoInterno' que faca o produto interno de dois vetores, depois use-a para computar A*x (A matriz e x vetor) |
045 | for (i=0; i<2; i++) |
046 | for (j=0; j<3; j++) |
047 | for (k=0; k<4; k++) |
048 | M[i][j][k] = conta++; |
049 | |
050 | // Supondo um sistema operacional como o Linux no qual o enderecamento e' crescente. |
051 | p = M; // aponta para inicio da matriz |
052 | for (i=0; i<2*3*4; i++) |
053 | printf("%2d ", *p++); |
054 | printf("\n"); |
055 | // Revendo, agora imprimindo via matriz e pulando linhas |
056 | for (i=0; i<2; i++) { |
057 | printf("---\nMatriz %d\n", i); |
058 | for (j=0; j<3; j++) { |
059 | for (k=0; k<4; k++) |
060 | printf("%2d ", M[i][j][k]); |
061 | printf("\n"); |
062 | } |
063 | } |
064 | |
065 | // Supondo um sistema operacional que use enderecamento decrescente (e.g., como o ?) |
066 | /* |
067 | p = M; // aponta para inicio da matriz |
068 | for (i=0; i<2*3*4; i++) |
069 | printf("%2d ", *p--); |
070 | printf("\n"); |
071 | */ |
072 | |
073 | return 0; |
074 | } |