mirror of
https://gitlab.com/blau_araujo/cblc.git
synced 2025-05-10 10:36:37 -03:00
Compare commits
2 commits
6bce833943
...
fb0c380d15
Author | SHA1 | Date | |
---|---|---|---|
fb0c380d15 | |||
68e34affc4 |
8 changed files with 360 additions and 0 deletions
|
@ -28,3 +28,4 @@ qualquer distribuição.
|
|||
- 19.03.2025 [[./aulas/04-variaveis/README.org][Aula 4: Variaveis e ponteiros]] ([[https://youtu.be/i7RKtMgSSrM][vídeo]]) ([[./exercicios/04/README.org][exercícios]])
|
||||
- 21.03.2025 [[./aulas/05-controle/README.org][Aula 5: Estruturas de controle de fluxo]] ([[https://youtu.be/9dvDL7FbYKY][vídeo]]) ([[./exercicios/05/README.org][exercícios]])
|
||||
- 26.03.2025 [[./aulas/06-vetores/README.org][Aula 6: Vetores]] ([[https://youtu.be/W5TGNQYFs4E][vídeo]]) ([[./exercicios/06/README.org][exercícios]])
|
||||
- 28.03.2025 [[./aulas/07-vps/README.org][Aula 7: Vetores, ponteiros e strings]] ([[https://youtu.be/hhySl3ClTLE][vídeo]]) ([[./exercicios/07/README.org][exercícios]])
|
||||
|
|
1
aulas/07-vps/.#testes.c
Symbolic link
1
aulas/07-vps/.#testes.c
Symbolic link
|
@ -0,0 +1 @@
|
|||
blau@xeon.1422306:1741809967
|
213
aulas/07-vps/README.org
Normal file
213
aulas/07-vps/README.org
Normal file
|
@ -0,0 +1,213 @@
|
|||
#+title: Curso Básico da Linguagem C
|
||||
#+subtitle: Aula 7: Vetores, ponteiros e strings
|
||||
#+author: Blau Araujo
|
||||
#+startup: show2levels
|
||||
#+options: toc:3
|
||||
|
||||
* Aula 7: Vetores, ponteiros e strings
|
||||
|
||||
[[https://youtu.be/hhySl3ClTLE][Vídeo desta aula]]
|
||||
|
||||
#+begin_quote
|
||||
Parte do conteúdo desta aula foi antecipado nas [[../06-vetores/README.org][anotações da aula 6]]!
|
||||
#+end_quote
|
||||
|
||||
Embora sejam conceitos totalmente distintos, existem relações importantes entre
|
||||
vetores e ponteiros que nós precisamos conhecer.
|
||||
|
||||
** Notações de acesso
|
||||
|
||||
Tanto ponteiros quanto vetores (e seus elementos) podem ser acessados de
|
||||
duas formas...
|
||||
|
||||
| Acesso | Aritmética | Subscrito |
|
||||
|----------------+------------------+---------------|
|
||||
| Valor/Elemento | =*(nome + índice)= | =nome[índice]= |
|
||||
| Endereço | =nome + índice= | =&nome[índice]= |
|
||||
|
||||
*** Exemplo
|
||||
|
||||
*Dados o vetor e o ponteiro abaixo...*
|
||||
|
||||
#+begin_src c
|
||||
char v[] = {65, 66, 67, 68, 69, 0}; // Vetor de caracteres (bytes)
|
||||
char *ptr = "FGHIJ"; // Ponteiro para uma string em .rodata (read only)
|
||||
#+end_src
|
||||
|
||||
*Impressão do endereço de um caractere...*
|
||||
|
||||
#+begin_src c
|
||||
// Impressões do vetor...
|
||||
printf("v[2] : %c (%d) --> &v[2]: %p\n", v[2], v[2], &v[2]);
|
||||
printf("*(v + 2): %c (%d) --> v + 2: %p\n", *(v + 2), *(v + 2), v + 2);
|
||||
|
||||
// Impressões do ponteiro...
|
||||
printf("p[2] : %c (%d) --> &p[2]: %p\n", p[2], p[2], &p[2]);
|
||||
printf("*(p + 2): %c (%d) --> p + 2: %p\n", *(p + 2), *(p + 2), p + 2);
|
||||
#+end_src
|
||||
|
||||
*Saída do programa...*
|
||||
|
||||
#+begin_example
|
||||
v[2] : C (67) --> &v[2]: 0x7ffda53a16c4
|
||||
*(v + 2): C (67) --> v + 2: 0x7ffda53a16c4
|
||||
p[2] : H (72) --> &p[2]: 0x562d0c93100a
|
||||
*(p + 2): H (72) --> p + 2: 0x562d0c93100a
|
||||
#+end_example
|
||||
|
||||
** Vetores e funções
|
||||
|
||||
Observe esta função:
|
||||
|
||||
#+begin_src c
|
||||
int array_sum(int arr[], int size) {
|
||||
int sum = 0;
|
||||
for (int i = 0; i < size; i++)
|
||||
sum += arr[i]; // arr é um ponteiro, não um vetor!
|
||||
return sum;
|
||||
}
|
||||
#+end_src
|
||||
|
||||
- Funções não podem receber vetores como argumentos, apenas seus endereços.
|
||||
- Escreve-se =int arr[]= apenas para indicar que o argumento esperado é o
|
||||
endereço de um vetor, já que =arr= será compilado como um ponteiro.
|
||||
- Do mesmo modo, utiliza-se =arr[i]=, na iteração, para manter a coerência
|
||||
semântica, já que a notação =nome[índice]= também pode ser utilizada com
|
||||
ponteiros.
|
||||
|
||||
Este mesmo exemplo poderia ser escrito apenas com notações de ponteiros
|
||||
e aritmética de ponteiros:
|
||||
|
||||
#+begin_src c
|
||||
int array_sum(int *arr, int size) {
|
||||
int sum = 0;
|
||||
for (int i = 0; i < size; i++)
|
||||
sum += *(arr + i); // Notação aritmética!
|
||||
return sum;
|
||||
}
|
||||
#+end_src
|
||||
|
||||
Em ambos os casos, a função lidará com o ponteiro (=arr=) que recebeu como
|
||||
argumento o endereço de um vetor. O vetor em si, jamais será convertido
|
||||
em ponteiro e nem tampouco /"decairá para um ponteiro"/!
|
||||
|
||||
** Strings são vetores de caracteres
|
||||
|
||||
Strings são vetores de caracteres terminados com o caractere nulo (=\0=).
|
||||
|
||||
*Declaração de um vetor para receber uma string...*
|
||||
|
||||
#+begin_src c
|
||||
char str[TAMANHO];
|
||||
#+end_src
|
||||
|
||||
Quando o vetor é declarado sem ser inicializado, é obrigatório definir
|
||||
a quantidade de elementos que o vetor receberá.
|
||||
|
||||
*Declaração e inicialização de um vetor com uma string...*
|
||||
|
||||
#+begin_src c
|
||||
char str[] = {'b', 'a', 'c', 'a', 'n', 'a', '\0'};
|
||||
#+end_src
|
||||
|
||||
Quando o vetor é inicializado, a quantidade de elementos pode ser
|
||||
omitida para ser definida na compilação.
|
||||
|
||||
#+begin_quote
|
||||
A presença da terminação do caractere terminador ='\0'= é que define
|
||||
uma cadeia de caracteres como uma string, ou seja: uma cadeia de bytes
|
||||
que pode ser utilizada com segurança em funções que procuram o terminador
|
||||
para determinar o fim do processamento da cadeia de caracteres.
|
||||
#+end_quote
|
||||
|
||||
*Declaração e inicialização de um vetor com uma string literal...*
|
||||
|
||||
#+begin_src c
|
||||
char str[] = "bacana";
|
||||
#+end_src
|
||||
|
||||
Quando a string literal ="bacana"= é utilizada na inicialização do vetor,
|
||||
o compilador copia cada um de seus bytes para o vetor e inclui o terminador
|
||||
nulo ('\0') como último elemento.
|
||||
|
||||
*Inicialização de um ponteiro com uma string literal...*
|
||||
|
||||
#+begin_src c
|
||||
char *ptr = "cabana";
|
||||
#+end_src
|
||||
|
||||
Ponteiros são variáveis que recebem endereços como argumentos. Sendo assim,
|
||||
o compilador copia os bytes da string literal ="cabana"= e inclui o terminador
|
||||
nulo na seção =.rodata= (/read only data/) como um vetor de caracteres de 7
|
||||
elementos e passa o endereço do primeiro byte para o ponteiro.
|
||||
|
||||
#+begin_quote
|
||||
O endereço de uma string, que é um vetor, é o endereço de seu primeiro byte.
|
||||
#+end_quote
|
||||
|
||||
** Inicializadores escalares e agregados
|
||||
|
||||
Ponteiros são variáveis e, portanto, requerem /inicializadores escalares/: no
|
||||
caso, especificamente endereços.
|
||||
|
||||
Todos esses dados são escalares e podem inicializar variáveis:
|
||||
|
||||
#+begin_src c
|
||||
// Variável inicializada com o valor '10' (expressão constante)...
|
||||
int a = 10;
|
||||
|
||||
// Ponteiro inicializado com valor '&a' (endereço de 'a')...
|
||||
int *pa = &a;
|
||||
|
||||
// Ponteiro inicializado com o endereço do primeiro byte de uma string...
|
||||
char *ps = "uma string literal";
|
||||
#+end_src
|
||||
|
||||
Vetores, por sua vez, são estruturas que agrupam vários dados de mesmo tipo e,
|
||||
por isso, requerem /inicializadores agregados/.
|
||||
|
||||
Todos esses dados são agregados de valores e podem inicializar vetores...
|
||||
|
||||
#+begin_src c
|
||||
// Vetor inicializado com uma lista de 5 valores...
|
||||
int n[5] = {1, 2, 3, 4, 5};
|
||||
|
||||
// Vetor inicializado com 5 valores '0'...
|
||||
int z[5] = {0};
|
||||
|
||||
// Vetor inicializado com 5 caracteres (bytes)...
|
||||
char c[] = {'a', 'b', 'c', 'd', '\0'}; // Quantidade de elementos definida na compilação...
|
||||
|
||||
// Vetor inicializado com 7 caracteres (bytes)...
|
||||
char s[] = "qwerty"; // O sétimo byte é o caractere nulo (\0 == 0x00)...
|
||||
#+end_src
|
||||
|
||||
Mas, repare nessas linhas...
|
||||
|
||||
#+begin_src c
|
||||
char *ps = "uma string literal";
|
||||
char s[] = "qwerty";
|
||||
#+end_src
|
||||
|
||||
As strings literais são dados agregados do tipo =char *=, mas podem ser
|
||||
utilizadas para inicializar tanto variáveis quanto vetores: tudo depende
|
||||
do contexto...
|
||||
|
||||
#+begin_src c
|
||||
long a = (long)"uma string"; // Endereço da string modelado para long int.
|
||||
|
||||
char *p = "outra string"; // O endereço da string é do tipo 'char[N bytes]'.
|
||||
|
||||
char s[] = "mais uma"; // O endereço da string será o endereço do vetor,
|
||||
// que só recebe os caracteres como elementos.
|
||||
|
||||
char f[] = {'o', 'i', '\0'}; // Equivale e inicializar com "oi".
|
||||
#+end_src
|
||||
|
||||
*Nota:*
|
||||
|
||||
Por ser uma estrutura de dados, o tipo de um vetor é frequentemente
|
||||
descrito como =TIPO[TAMANHO]=. Sendo um vetor de caracteres, o tipo de
|
||||
uma string literal na memória é =char[TAMANHO]=. Quando atribuída a
|
||||
uma variável, a string literal expressa o endereço de seu primeiro
|
||||
byte, ou seja, o endereço de um dado do tipo =char=.
|
31
aulas/07-vps/diagrama.txt
Normal file
31
aulas/07-vps/diagrama.txt
Normal file
|
@ -0,0 +1,31 @@
|
|||
|
||||
|
||||
Notações de acesso (vetores e ponteiros para endereços de vetores):
|
||||
|
||||
===============================================
|
||||
| Expressa | Aritmética | Subscrito |
|
||||
===============================================
|
||||
| Valor | *(nome + índice) | nome[índice] |
|
||||
|----------+------------------+---------------|
|
||||
| Endereço | nome + índice | &nome[índice] |
|
||||
===============================================
|
||||
|
||||
|
||||
Incialização de vetores: Inicialização de ponteiros:
|
||||
Requer inicializadores "agregados" Requer inicializadores "escalares"
|
||||
|
||||
|
||||
&c[0] &c[1] &c[2] &c[3] &p[0] &p[1] &p[2] &p[3]
|
||||
+--------+--------+--------+--------+ +--------+--------+--------+--------+
|
||||
char c[] = {65, 66, 67, 0}; ==> | 0x41 | 0x42 | 0x43 | 0x00 | char *p = "xyz"; ==> | 0x78 | 0x79 | 0x7a | 0x00 |
|
||||
+--------+--------+--------+--------+ +--------+--------+--------+--------+
|
||||
↑
|
||||
&s[0] &s[1] &s[2] &s[3] |
|
||||
+--------+--------+--------+--------+ +--- Endereço em .rodata (read only)
|
||||
char s[] = "abc"; ==> | 0x61 | 0x62 | 0x63 | 0x00 |
|
||||
+--------+--------+--------+--------+
|
||||
|
||||
&b[0] &b[1] &b[2] &b[2]
|
||||
+--------+--------+--------+--------+
|
||||
char b[4] = {0}; ==> | 0x00 | 0x00 | 0x00 | 0x00 |
|
||||
+--------+--------+--------+--------+
|
34
aulas/07-vps/inicializa.c
Normal file
34
aulas/07-vps/inicializa.c
Normal file
|
@ -0,0 +1,34 @@
|
|||
#include <stdio.h>
|
||||
|
||||
int main(void) {
|
||||
|
||||
// Declaração do vetor...
|
||||
float notas[4];
|
||||
|
||||
// Definição individual dos elementos...
|
||||
notas[0] = 7.5;
|
||||
notas[1] = 9.0;
|
||||
notas[2] = 8.3;
|
||||
notas[3] = 8.6;
|
||||
|
||||
// Inicialização do vetor...
|
||||
int vetor[3] = {1, 2, 3};
|
||||
|
||||
// Inicialização sem número de elementos...
|
||||
char c[] = {65, 66, 67, 68, 69}; // char[5]
|
||||
char str[] = "string"; // = {'s', 't', 'r', 'i', 'n', 'g', '\0'};
|
||||
|
||||
// Inicialização parcial...
|
||||
int n[6] = {1, 2, 3}; // = {1, 2, 3, 0, 0, 0};
|
||||
|
||||
// Inicialização com zeros...
|
||||
int z[5] = {0}; // = {0, 0, 0, 0, 0};
|
||||
|
||||
// Inicialização com elementos de mesmo valor...
|
||||
int r[4] = {23}; // = {23, 0, 0, 0};
|
||||
|
||||
for (int i = 0; i < 4; i++) r[i] = 23;
|
||||
|
||||
|
||||
return 0;
|
||||
}
|
33
aulas/07-vps/notations.c
Normal file
33
aulas/07-vps/notations.c
Normal file
|
@ -0,0 +1,33 @@
|
|||
#include <stdio.h>
|
||||
|
||||
int main() {
|
||||
|
||||
/*
|
||||
Notações de acesso:
|
||||
|
||||
===============================================
|
||||
| Expressa | Aritmética | Subscrito |
|
||||
===============================================
|
||||
| Valor | *(nome + índice) | nome[índice] |
|
||||
|----------+------------------+---------------|
|
||||
| Endereço | nome + índice | &nome[índice] |
|
||||
===============================================
|
||||
*/
|
||||
|
||||
long s = (long int)"banana";
|
||||
printf("%lx\n\n", s);
|
||||
|
||||
char v[] = {65, 66, 67, 68, 69, 0};
|
||||
char *p = "FGHIJ";
|
||||
|
||||
// Impressão do vetor...
|
||||
printf("v[2] : %c (%d) --> &v[2]: %p\n", v[2], v[2], &v[2]);
|
||||
printf("*(v + 2): %c (%d) --> v + 2: %p\n", *(v + 2), *(v + 2), v + 2);
|
||||
|
||||
// Impressão do ponteiro...
|
||||
printf("p[2] : %c (%d) --> &p[2]: %p\n", p[2], p[2], &p[2]);
|
||||
printf("*(p + 2): %c (%d) --> p + 2: %p\n", *(p + 2), *(p + 2), p + 2);
|
||||
|
||||
|
||||
return 0;
|
||||
}
|
13
aulas/07-vps/string.c
Normal file
13
aulas/07-vps/string.c
Normal file
|
@ -0,0 +1,13 @@
|
|||
#include <stdio.h>
|
||||
|
||||
int main(void) {
|
||||
|
||||
// Vetor de caracteres com terminador nulo...
|
||||
char vstr[] = "bacana";
|
||||
|
||||
// Ponteiro para um vetor char[7] em .rodata...
|
||||
char *pstr = "cabana";
|
||||
|
||||
|
||||
return 0;
|
||||
}
|
34
aulas/07-vps/testes.c
Normal file
34
aulas/07-vps/testes.c
Normal file
|
@ -0,0 +1,34 @@
|
|||
#include <stdio.h>
|
||||
|
||||
#define NBIM 4
|
||||
|
||||
float favg(float *arr, int size) {
|
||||
float sum = 0;
|
||||
for (int i = 0; i < size; i++) {
|
||||
sum += arr[i];
|
||||
}
|
||||
return sum / size;
|
||||
}
|
||||
|
||||
int main(void) {
|
||||
|
||||
float notas[NBIM];
|
||||
|
||||
notas[0] = 7.5;
|
||||
notas[1] = 9.0;
|
||||
notas[2] = 8.3;
|
||||
notas[3] = 8.6;
|
||||
|
||||
float avg = favg(notas, NBIM);
|
||||
|
||||
puts("============");
|
||||
|
||||
for (int i = 0; i < NBIM; i++)
|
||||
printf("Bim. %d: %.1f\n", i + 1, notas[i]);
|
||||
|
||||
puts("------------");
|
||||
printf("Média : %.1f\n", avg);
|
||||
puts("============");
|
||||
|
||||
return 0;
|
||||
}
|
Loading…
Add table
Reference in a new issue