[Powered by Google Translate] Imos falar sobre estruturas.
Estruturas fornecer un xeito de agrupar unha morea de variables xuntas
un bo paquete.
É probablemente máis doado para ver un exemplo de inmediato,
por iso dicimos struct,
a continuación, unha chave de apertura,
e nesa estrutura, imos ter unha idade int,
un nome de char *,
e é iso.
Pode parecer estraño cun punto e coma despois dunha chaveta,
pero é, de feito, é necesario, con estruturas.
Calquera tipo válido pode ir dentro da definición de struct.
Aquí usamos un int e un char *,
pero tamén pode usar unha matriz, de, digamos, 100 elementos
ou mesmo struct outro.
Cando está a usar structs en C,
está creando novos tipos
dunha colección de outros tipos.
Aquí, nós estamos facendo un novo tipo
dun enteiro e un char *.
Como veremos máis adiante, un tipo de estrutura
está unha morea de formas equivalentes a calquera outro tipo que está acostumado.
Normalmente, eu vou estar comparando como un tipo de estrutura
é semellante a un tipo enteiro.
Mentres o código que escribiu é válido C,
non é moi útil,
e bumbum vai dar un aviso.
Teña en conta que como estruturas e os seus son semellantes?
Ben, basicamente, só dixo
int,
o que non é unha liña moi útil.
Entón, imos realmente declarar unha variable deste tipo
, Dándolle un nome antes do punto e coma.
Imos chamar o estudante variable.
Agora que xa declarou un estudante variable chamada
co tipo de dado pola estrutura.
Como chegamos ás variables dentro da estrutura?
Tecnicamente, os nomes para esas variables
son membros.
Para acceder calquera membro particular nunha estrutura de estudante,
vostede engadir un punto para o nome da variable,
seguido do nome do membro que desexe.
Entón, aquí, as únicas dúas posibilidades válidos
son student.age
e student.name.
E podemos facer algo como
student.age = 12
e student.name = estudante.
Agora, o que se quería facer un segundo alumno?
Podes pensar que copiar e pegar estas liñas
e cambiar alumno para alumno dous ou algo así,
e que pode traballar,
pero tecnicamente alumno e alumno 2
non teñen o mesmo tipo.
Mira, non será capaz de atribuílo los a outro.
Isto é porque, ata agora,
súa estrutura foi anónima.
Necesitamos darlle un nome.
Para facer isto, introduza o nome da struct
tras a struct palabra.
estudante,
seguido pola definición.
Aínda podemos inmediatamente declarar unha variable do tipo
struct alumno, como fixemos antes.
Imos chamalo de S1
Ao dar a estrutura dun nome,
agora podemos utilizar estudante struct
en case exactamente o mesmo que usaría int.
Así, podemos declarar unha variable de tipo struct alumno,
como
struct alumno S2.
Como arrays, estruturas proporcionan unha sintaxe de inicio de atallo,
así podemos dicir struct alumno S2
é igual
esquerda rizados cinta 3, S2.
Aquí, S2.age será de 3,
e S2.name ha apuntar S2.
Debería todas as cousas que podes facer con un tipo int
ea maioría deles pode facer un tipo de estudante struct.
Podemos usar un estudante de estrutura como un tipo de parámetro de función.
Podemos usar struct alumno dentro dunha estrutura nova.
Podemos ter un punteiro para un estudante struct.
Podemos facer o tamaño alumno struct.
Estudante struct é un tipo
como int é un tipo.
Podemos tamén dar S1 a S2
xa que ambos son do mesmo tipo, para que poidamos facer
S1 = S2.
Qué acontece se non facemos
S1.age = 10?
Cambia S2 en todo?
Unha vez máis, creo que as estruturas só como enteiros regulares.
Se atribuirmos algunha X int a algún Y int,
como X = Y
e despois cambiar X,
como en X + +,
Y non cambia en nada?
Y non é alterado aquí, e así tampouco S2 anterior.
S2.age aínda é 3.
Pero nótese que, cando a asignación dunha estrutura a outra,
todos os punteiros aínda apuntan á mesma cousa,
xa que só foron copiados.
Se non quere que os punteiros para ser compartido,
terá que tratar con isto manualmente
quizais por malicking un bloque de memoria para un dos punteiros para apuntar para
e copiar os datos máis.
Pode ser aburrido ter que escribir struct alumno en todas as partes.
Empregando un def tipo, podemos facer
Tipo de def
struct
e imos chamalo de estudante.
Agora, podemos utilizar estudante en todos os lugares
que adoitaba empregar estudante struct.
Este tipo de def é unha estrutura anónima
e chámase alumno.
Pero tamén manter o identificador de estudante
á beira do struct palabra, como no estudante typedef struct,
podemos utilizar tanto o alumno e alumno struct alternativamente agora.
Eles nin sequera teñen que ter o mesmo nome.
Poderiamos escribir def estudante estrutura para Bob
e despois struct alumno e Bob
sería tipo intercambiábeis.
Independentemente do tipo de def,
necesitamos do próximo identificador para a estrutura
a definición da estrutura
é recursiva.
Por exemplo, a
def tipo struct nodo
e ela defínese como un int val
e terá un punteiro que apunta a outro nodo struct.,
como na estrutura do nó * seguinte.
E entón imos chamalo de nós.
Esta estrutura é recursiva,
unha vez que a definición de nodo struct contén dentro del
un punteiro para un nó de estrutura.
Teña en conta que temos que dicir struct node * próxima
dentro da definición do nodo struct,
desde a definición do tipo aínda non rematou para permitir simplificar este
* Só para o próximo nó.
Vai saber máis sobre estruturas semellantes a este
cando se trate de listas ligadas e árbores.
E sobre estruturas en función?
Isto tamén é perfectamente válida.
Poderiamos ter
void func
que toma como argumento,
estudante s
e fai algo con ese alumno.
E entón podemos pasalo como struct alumno así.
Func de S1 de antes.
A estrutura comporta
exactamente como un número enteiro que cando pasadas a unha función.
Func recibe unha copia de S1
e por iso non pode modificar S1;
en vez diso, só a copia do mesmo que está almacenado en S.
Se queres que a función de ser capaz de modificar S1,
función terá de ter un alumno * S,
e vai ter que pasar por enderezo S1, así.
Estudante * S, func & S1.
Hai outra razón para pasar por enderezo aquí.
E se a nosa estrutura contiña 100 campos?
Cada vez que pasar por un estudante a func,
noso programa necesita copiar os 100 campos en función do S argumento,
aínda que el nunca usa a gran maioría deles.
Así, aínda que función non planea modificar o alumno,
aínda pode ser útil para pasar por enderezo.
Ok, o que se desexa crear un punteiro para un struct?
Nós poderiamos facer algo como
estudante * S
é igual malloc
tamaño do alumno.
Teña en conta que o tamaño aínda traballa aquí.
Entón, como imos agora acceder ao membro idade
do bloque que apunta para S?
Podes primeiro pensar en facer
* S.age = 4,
pero iso non funciona moi ben.
Dende que iso vai realmente ser interpretada como
* S.age entre parénteses = 4,
que non vai mesmo compilar,
desde S non é unha estructura ou mellor, un punteiro para unha estrutura,
e así o punto non vai funcionar aquí.
Nós poderiamos facer
(* S) idade. = 4
pero os parénteses poden estar aburrido e confuso.
Afortunadamente, temos un operador frecha especial
que é algo así como
S-> idade = 4.
Estas dúas formas de referenciamento idade
son equivalentes
e nós realmente non precisa de o operador frecha,
pero iso fai as cousas máis fermosos.
Dende que S é un enlace a un bloque de memoria que contén a estrutura,
pode pensar S idade> como segue o punteiro de
e coller o membro idade.
Entón por que debemos usar sempre estruturas?
É en definitiva posible para fuxir con só os números enteiros primitivos,
chars, enlaces e similares
que estamos afeitos;
en vez de antes S1 e S2,
poderiamos ter idade1, idade2, nome1, nome2 e
todos de variables separadas.
Iso é bo, con só dous alumnos,
pero o que se tivésemos 10 deles?
E se en vez de só dous campos,
a estrutura estudante tivo 100 campos?
GPa, cursos, cor do cabelo, sexo, e así por diante.
En vez de só 10 estruturas, necesitamos mil variables separadas.
Ademais, considerada unha función
que leva ese estrutura con 100 campos co seu único argumento
e imprime todos os campos.
Se non usar unha estrutura,
cada vez que chamar esa función,
temos que pasar en todas as 100 variables,
e se temos 100 variables nunha estudante,
e 100 variables para estudante, 2
necesitamos ter seguro de que non poida pasar algunhas variables dun estudante
e algunhas variables de estudante 2.
É imposible facer ese erro cunha estrutura,
unha vez que todas as variables son 100 contida nunha única embalaxe.
Só un par de notas finais:
Se entendeu todo ata este punto, gran.
O resto do vídeo é para ser completo.
Como estruturas poden realizar calquera tipo de punteiro,
eles tamén poden conter punteiros de función.
Se está familiarizado coa programación orientada a obxectos,
Isto proporciona unha maneira de usar estruturas de programa nun estilo de obxecto orientado.
Máis sobre punteiros de función noutro momento.
Tamén, ás veces pode ter dúas estruturas
cuxas definicións dependen un do outro.
Por exemplo, a
poderiamos ter struct A,
que é definido como
un enlace a un B struct,
struct B * X,
e agora podemos ter unha estrutura B
que é definido como un punteiro
para unha estrutura A,
struct A * Y.
Pero iso non vai compilar,
desde B struct non existe no momento en que struct A está compilado.
E se cambiar struct struct A e B,
entón nós só queda con el;
esta vez con struct A non existente.
Para solucionar isto, podemos escribir
struct B;
antes da definición de struct A.
Iso é chamado de unha declaración para a fronte.
Isto só deixa o compilador saber que
struct B é un tipo válido que será totalmente definido máis tarde ou noutro lugar.
O meu nome é Rob Bowden, e este é o CS50.
[CS50.TV]