[Powered by Google Translate] [Semana 4, continuación] [David J. Malan - Harvard University] [Esta es CS50. - CS50.TV] Esto es CS50, y este es el fin de semana 4. Así que una buena noticia y una mala noticia. No conferencia el lunes, no hay problema fijado la próxima semana. [Estudiantes vitoreando] No te va a gustar a dónde va esto. Pero tenemos este lugar el próximo miércoles, y también hay un programa de estudios por la conferencia el próximo viernes viernes para que podamos mantener el rumbo. Pero todo va a ser filmado, como de costumbre, por lo que no se preocupara. Y con respecto a quiz 0 lo que vamos a hacer a finales de la semana se publique en cs50.net página de inicio del curso una explicación de qué tipo de expectativas que usted debe tener cuando se trata de la primera prueba. En general, será de opción múltiple, verdadero-falso, respuesta corta, corta los problemas de codificación. Usted no va a esperar para poner en práctica el equivalente de un problema que usted vería en un conjunto de procesadores, para lo cual dispone de un ordenador y un depurador y similares, pero habrá pequeños problemas de codificación. Y, en efecto, la mejor guía para tener una idea de lo que CS50 concursos son como es ir a cs50.net, vaya al enlace de Concursos, y se puede ver en los últimos años por valor de concursos. Sólo se dan cuenta de que el plan de estudios no siempre ha sido igual a lo largo de los años. A veces se añade, a veces, restar, así que si ves algún tema en uno de esos viejos concursos que usted no tiene idea de lo que está hablando, o es que lo cubra o que no lo cubra. Pero en la forma de opiniones, este domingo, lunes y martes así como un curso de toda la sesión de revisión en la noche del domingo - hora y lugar que se anunciará en la página principal del curso - que todos tengan la oportunidad de revisar con compañeros docentes del curso el material para este año, tanto en la sección y como una clase completa, y los que se filmará como siempre también. Está bien. Así que sin más preámbulos, un comentario sobre pasa / no pasa y add / drop. Es posible que haya visto mis notas anoche, y esto es sólo un poco de tranquilidad adicional que si usted está entre los menos cómodos en particular o en algún punto intermedio y te sientes un poco adentro sobre su cabeza, darse cuenta de que es de hecho bastante normal, y no hay una estructura de apoyo suficiente en el lugar, uno de los cuales las horas de oficina tenían la intención de mejorar aún más por la última noche de correo electrónico, y darse cuenta también que una opción como apto / no apto para una clase como esta realmente se entiende como un mecanismo para tomar el borde de un curso como éste, de modo que de nuevo si usted está gastando esos 10, 15, 20 horas tratando de obtener algún conjunto de procesadores para trabajar y usted sabe que usted es el 90-95% del camino pero no se puede encontrar algún bug maldito, en un pasa / no pasa modelo que es una especie de bien. La idea es que con ese mecanismo se puede ir foco en sus conjuntos de procesadores otras o dormir o lo que sea que desee enfocar. Así que darse cuenta de que usted tiene hasta el próximo martes - técnicamente el quinto lunes, pero es un día de fiesta, por lo que el próximo martes - para cambiar de pasa / no pasa a la inversa graduadas o viceversa. Y si usted está realmente en el precipicio y están pensando en abandonar por completo, por favor me coge después de la conferencia o mándenme una nota. Nos encantaría que al menos charla antes de decir adiós. Está bien. Así que empezamos a tomar las ruedas de entrenamiento fuera la última vez. En particular, nos centramos en cadena. La cadena es algo que se declaró en la biblioteca CS50, específicamente en ese archivo llamado cs50.h que vamos a empezar a ver esta semana y la próxima. Pero la cadena es en realidad una simplificación de algo que es un poco más arcanely descrito como char *. Charla estamos familiarizados. Es sólo un carácter único. Pero a partir del lunes * denota qué? >> [Estudiante] Puntero. Un puntero. Y lo que es un puntero? >> [Estudiante] Una dirección. Es como una dirección, un lugar en la memoria. ¿Qué es una dirección o ubicación o la memoria? Una vez más, todos nosotros tenemos ordenadores portátiles con un giga o 2 gigas de RAM más probable es que en estos días, y eso significa que tienes un billón o 2 mil millones de bytes por valor de memoria. Y no importa lo que físicamente se parece, pero ten fe en que usted puede contar todos los bytes individuales que tiene su propio ordenador portátil - este es el byte 0, se trata de un byte, este es el byte 2 mil millones - y eso es exactamente lo que hace una computadora. Al asignar espacio para un solo carácter, por ejemplo, es obvio que tiene que vivir en algún lugar de la memoria del ordenador, y tal vez es en el byte número 12345, y que en algún lugar aquí en la memoria de su computadora. Y a continuación, la dirección de ese carácter es 12345. Ahora, en la semana 0 y ahora hasta el momento, no hemos atendido donde en las cosas de memoria se almacenan ya que por lo general utilizan símbolos, variables y matrices para conseguir realmente a nuestros datos. Pero a partir del lunes y todo el día de hoy más, usted está ahora va a tener todas las capacidades más expresivos con los programas de escritura para manipular realmente la memoria de una computadora sin embargo le parezca, tanto para fines buenos y malos, errores es un resultado muy común en este punto en el aprendizaje de esta materia. Pero, ¿qué es lo que realmente significa ser un char *? Vamos a seguir adelante para atrás - y volveremos a Binky como prometió hoy. Vayamos a un ejemplo simple aquí. Déjame guardar este archivo como compare.c, y me dejaron de conseguir un poco de código de plantilla aquí así como stdio.h, permítanme darme incluyen cs50.h. Voy a acercar hasta allí. Permítanme empezar a escribir int main, main (void), y ahora quiero hacer algo como esto: printf ("Dame una cadena:") y luego voy a utilizar la cadena s se GetString para obtener una cadena por parte del usuario, y luego me voy a preguntar al usuario por otro. ("Dame otra cadena:") y voy a preguntarles por GetString para conseguir eso. Voy a llamar a t t porque viene después de s y s es un bonito nombre para una cadena si es bastante genérico. Así GetString, y ahora sólo quiero hacer una comprobación de validez y yo voy a decir if (s == t), entonces yo voy a decirle al usuario printf ("Usted escribe lo mismo \ n"); más que voy a imprimir algo como ("que ha escrito algo diferente! \ n") o cualquiera que sea la sentencia será. Así que algo como eso. Entonces, como de costumbre, voy a devolver 0, lo que sólo significaba que nada malo ha pasado, y voy a seguir adelante y compilar y ejecutar este programa. Pero el lunes nos encontramos con este programa, y de hecho se les dijo que no se HOLA hola y adiós no es un adiós. El comportamiento que vimos fue un poco más de esta manera. Déjame ir a mi directorio de las fuentes, zoom aquí, y vamos a comparar hacen. Compilado bien. Déjame correr comparar. Dame una cadena: HOLA. Dame otra cadena: HOLA. Ha escrito algo diferente! Bueno, voy a tratar de algo más simple como 50, 50. Ha escrito algo diferente! hi, hi. Así que, claramente, algo está pasando aquí. ¿Pero cuál era la explicación de por qué? Al parecer, la línea 12 es completamente disfuncional. ¿Cuál es el problema fundamental aquí? Si. >> [Estudiante] Se comparan las direcciones. Sí, exactamente. De hecho, es la comparación de las direcciones en el cual HOLA HOLA y se almacenan. No es comparar las cartas HOLA una y otra vez, porque lo que realmente sucedió, todo este tiempo que hemos estado usando GetString - Esta pizarra es de nuevo la memoria de nuestro ordenador, y digamos que yo llamo GetString después de declarar una variable s. ¿Qué hace mi memoria parece? Vamos a decir que arbitrariamente s se parece a esto. Es un cuadrado. Y casi todo el tiempo que he dibujado un pedazo de la memoria en la pantalla si es de 32 bits que he estado dibujando cuadros como este porque de hecho en el aparato, un puntero, una dirección, es de 32 bits. Es lo mismo que un int. Eso puede variar basado en el sistema informático. Aquellos de ustedes que son vagamente familiarizado con el hecho de que tu Mac o PC es de 64 bits, que en realidad significa que el equipo está utilizando punteros de 64 bits, Direcciones de 64-bit, y entre los upsides de que los equipos RAM puede tener mucho más que antaño. Larga historia corta, de vuelta en el día en que los ordenadores sólo utilizan 32 bits para representar direcciones, el mayor número de bytes que puede representar en ese caso era lo que si usted tiene 32 bits? Así que 4 mil millones, a la derecha, ya que 2 de los 32 es de 4 millones de dólares. Este número ha sido recurrente en el curso. Así que si usted sólo tiene 32 bits, el número más alto que se puede contar hasta es aproximadamente 4 mil millones. Pero eso era una limitación fundamental de los ordenadores hasta hace unos años porque si sólo se puede contar tan alto como 4 mil millones, no importa si usted compra 8 gigabytes de RAM y hasta 5 gigabytes de RAM; no se puede contar tan alto, por lo que era inútil. Sólo se podía acceder a los primeros 3 o 4 gigabytes de memoria de su computadora. Eso es menos de un problema ahora, y usted puede comprar MacBook Pro y Dells con 8 gigabytes de RAM o incluso más en estos días. Pero si simplemente asignar en este programa un puntero, un puntero llamado s, que podría tener este aspecto en la pantalla porque en realidad tenemos que pelar esta capa. Sigo diciendo cadena, pero a partir del lunes, la cadena es realmente char *, la dirección de algún personaje. Así que vamos a tomar esa rueda de entrenamiento a pesar de que vamos a seguir utilizando GetString por ahora. Así que he declarado s, y esto es una porción de la memoria, 32 bits. ¿Qué hay aquí en la memoria por defecto? >> [Respuesta de los estudiantes inaudible] ¿Qué es eso? >> [Estudiante] basura. >> Basura. Exactamente. Si el programador no poner un valor en una variable, que sabe lo que es? A veces se tiene suerte y es 0, que es una especie de un valor agradable, limpio defecto, pero como vimos lunes, a veces es una completa tontería, un número muy grande positivo o negativo que viene de dónde? Si. >> [Estudiante] La función anterior. Sí >>. A menudo, la función que he llamado antes porque recuerden, como se llama a funciones de la memoria, que ocupan cada vez más espacio de abajo hacia arriba, y tan pronto como la función retorna, que la memoria se reutilizan por el tipo de al lado que se llama, quién está utilizando el mismo segmento de la memoria. Y si tienes basura izquierda hay, los valores anteriores, podríamos confundir s como tener algún valor, cuando en realidad no hemos puesto nada allí. Así que nuestra RAM en este punto se ve así. Ahora, en el lado derecho de la línea 7 que llamamos GetString, que hemos estado haciendo durante semanas ahora, pero lo que realmente GetString haciendo? GetString escrito por el personal CS50 es un poco inteligente en que tan pronto como el usuario inicia pulsan teclas y parada Intro, GetString se da cuenta de cómo las pulsaciones de teclas muchos hicieron el hit de usuario, número de caracteres que tengo que asignará memoria RAM. ¿Y dónde RAM que viene, ¿quién sabe? Está en algún lugar de 2 gigabytes de su ordenador o lo que sea de la memoria. Pero vamos a suponer que el equipo encontró espacio para la palabra HOLA aquí. La palabra que escribí fue H-E-L-L-O. Y si sacamos esto como una secuencia de caracteres, podríamos llamar así. Pero tengo que hacer una cosa más. Lo que pertenece al final de cualquier cadena en C? El carácter nulo, lo que se escribe como \ 0. Es técnicamente el número 0, pero la barra invertida hace todo más claro que esto es literalmente el número 0, el número entero 0; no lo es, por ejemplo, entre comillas 0 que podría escribir en el teclado. Así que esto es HELLO. ¿Y qué podemos decir hoy que una función como GetString en realidad está devolviendo todas estas semanas? No está devolviendo una cadena de por sí, ya que en realidad no tienen significado porque las cadenas no existen. Son una especie de una fabricación en la biblioteca CS50. Lo que es realmente una cadena, más técnicamente? >> [Estudiante] Es el primer carácter. Exactamente. Es, sencillamente, la dirección del primer carácter que el usuario escribió pulg Así que si mi palabra HOLA termina en 123 el número de bytes y luego en el byte número 124, 125, 126, y así sucesivamente, si tan sólo mi número de bytes en un máximo de 0, lo que realmente está regresando GetString es, literalmente, el número 123. Así que lo que se pone en s es el número 123, no la letra H, no la palabra HOLA, sencillamente, la dirección en la que puedo encontrar la primera letra de HELLO. Pero eso no parece ser suficiente. Te pedí una cadena, no un personaje. Entonces, ¿cómo sabe el ordenador o que tipo de ELLO vienen junto con la H? ¿Cuál es el tipo de acuerdo que tenemos? Si. [Estudiante] Se sigue diciendo sí mismo para encontrar algunos personajes más. >> Exactamente. Hay una convención persona-ordenador por lo que cuando se trata de cadenas, también conocida ahora como estrellas char, simplemente tienes que saber donde al final de cada cadena en la vida es realmente sólo iterar sobre ella con un bucle for, un bucle while, lo que sea, para que cuando encuentre el final de la cadena ahora se puede inferir de eso, oh, toda la palabra era HELLO. Aquellos de ustedes que tienen experiencia previa en programación puede saber en Java usted puede llamar. longitud y en otros idiomas se puede llamar a la longitud o similar. Eso es porque en una gran cantidad de idiomas, sobre todo cosas que se llaman lenguajes orientados a objetos, la longitud de algo es de tipo encapsulado dentro de la pieza de datos en sí, muy parecido a nosotros, los IDs y nombres encapsulados y casas en el interior de un estudiante el lunes. Sin embargo, C es el nivel mucho más bajo. No hay objetos o clases, si has escuchado esos términos antes. Todo lo que tienes es realmente direcciones de memoria. Así que esto es una especie de la manera tradicional de representar las estructuras de datos interesantes. Tiene un valor de inicio como la dirección del primer carácter y luego sólo una convención arbitraria que todo el mundo está de acuerdo en seguir. Entonces, ¿cómo se implementa longitud de la cadena, lo que proponemos? Strlen, strlen, que algunos de ustedes han usado un par de veces. Es bastante simple, ¿verdad? Es como dos líneas de código. Es más o menos un lazo para de algún tipo, tal vez con una variable local adicional. Pero strlen sólo tiene que echar un puntero y luego empezar a buscar \ 0. Y tan pronto como lo encuentra, puede devolver el número total de pasos que ha tomado en esa cadena. Así que podemos inferir de esto lo que sucede a continuación. Supongamos entonces declaro t como lo he hecho en la línea 10. Este es un valor basura. Quién sabe al principio? Pero en el lado derecho de la línea de 10 Voy a llamar a GetString nuevo. ¿Quién sabe dónde termina esto? Vamos a decir arbitrariamente que el sistema operativo se ha encontrado sitio para él hasta aquí. Sucede que escribir casualmente H-E-L-L-O de nuevo, y por lo que podemos llamar el mismo tipo de imagen. Pero el hecho de que he redibujado esta imagen es deliberada porque es una. diferente HOLA que éste Así que aquí esta podría ser la ubicación 456, esto es 457, y así sucesivamente. Así que lo que se pone en el signo de interrogación que una vez fue? En este caso 456. Estamos recibiendo estos números arbitrariamente porque realmente a partir de hoy no vamos a cuidar mucho sobre cuál es la dirección de algo es. Todo lo que importa es que podemos averiguar la dirección de algún dato como HELLO. Así que en realidad lo que la mayoría de la gente hace en ciencias de la computación cuando se habla de las direcciones de memoria y hablando de punteros en concreto, en lugar de preocuparse averiguando 123 - a quién le importa donde este material es en realidad, solo sabemos que es en alguna dirección numérica - simplificamos el mundo y decir que s está apuntando a ese personaje y t se señala a ese carácter. Y el hecho de que es una flecha es absolutamente intencional porque, literalmente, ahora s está apuntando a H y T está señalando en el otro H porque al final del día, no importa lo que la dirección es, pero sí importa que tengamos la capacidad de expresar esa dirección con alguna pieza de código. Realmente no hemos manipulado estas direcciones todavía así que vamos a ver donde podemos intervenir y ordenar de hacer las cosas con punteros, pero por el momento en la línea 12 literalmente qué valores estamos comparando de acuerdo con esta historia en la línea 12? Lo que estamos diciendo es 123 igual igual a 456? Y eso no es definitivamente el caso. E incluso conceptualmente, este puntero es definitivamente no es el mismo que este porque GetString llamado dos veces, y GetString no trata de ser super inteligente, no se trata de darte cuenta, oh, que escribió HOLA hace 5 minutos; te voy a dar el mismo puntero como que te di antes, sólo reserva un espacio de memoria cada vez que lo llaman. Entonces, ¿cómo podemos solucionar este problema? Si un nivel más alto que quiero comparar las cadenas Hola y hola - No me importan los punteros - ¿Cómo hago para contestar la pregunta, Por qué el usuario escriba la misma cosa? Lo que se necesita aquí? Si. [Estudiante] Utilice una función. >> Puedo utilizar una función fuera de la caja. Puedo utilizar una función llamada strcmp, s-t-r-c-m-p, sólo la versión abreviada de decir comparación de cadenas. Y si entramos en, por ejemplo, comparar 2, que es uno de los folletos de hoy, Hago exactamente eso. Guardé todo lo demás constante de la línea 1 hasta el 26 o así, y ahora cuenta de esta parte ha cambiado un poco. Vamos a pasar por alto la línea 28 por un momento y centrarse sólo en este caso. ¿Qué nos dicen hoy que str comparación hace? Se maneja el proceso de tomar 2 punteros, S y T en este caso, tipo de prácticamente poniendo su dedo en esas 2 cartas, y lo que debe hacer es algo parecido a un bucle while o un bucle for, y dice que estos son los mismos? Si es así, se mueve los dedos o los punteros hacia adelante. ¿Son los mismos, éstos lo mismo, ellos, el mismo estos mismo, estos mismo? Y ooh, estoy en el final de la cadena, tanto en s y t. No he encontrado ninguna contradicción. Sí, estas cadenas son iguales. ¿Y qué str comparar devolución si dos cadenas son iguales, al parecer? Cero. Así que 0 es bueno en este caso porque si devuelve -1 o +1, que significa que s le pasa a venir antes o después de t alfabéticamente t. ¿Y por qué tendría que ser útil disponer de una función que le indica qué cadena va antes o después de que en un diccionario? [Estudiante] Búsquedas. >> Búsqueda y ordenación. Así que usted puede hacer cosas como búsqueda binaria o tipo burbuja o fusionar especie donde usted tiene que comparar las cosas. Hasta ahora hemos especie de cortar algunas esquinas y sólo habló de clasificación en el contexto de los números, porque es agradable y fácil de hablar, pero que sin duda puede comparar cadenas, manzana y plátano, porque si la manzana es conocido por venir antes de plátano, de manera similar, Puede mover las cadenas en torno a la memoria al igual que hizo con Rob especie de mezcla en el video y lo hicimos aquí en el escenario con una especie de selección, ordenación por inserción, y una especie de burbuja. Entonces, ¿dónde más podemos tomar esto? Vamos a probar esto. Vamos a ordenar de olvidar esa lección por un momento y pruebe y copiar 1.c a hacer lo siguiente. En la línea 21 que estoy diciendo algo de impresión, entonces yo estoy haciendo una cadena del usuario, entonces yo estoy comprobando esto. Realmente no hemos entrado en esta costumbre todavía, pero ahora vamos a hacer esto. Vamos a pelar en realidad esta capa. Esto es realmente char *. Este tipo es realmente char *. Entonces, ¿qué significa estar comprobando si s == NULL? Resulta que cuando se llama a una función como GetString o más generalmente sólo pide una computadora para darle un poco de memoria, algo podría salir mal. Usted podría estar loco y pedir a la computadora por un terabyte de memoria pidiendo miles de millones de bytes de memoria que simplemente no existen en el equipo, pero las funciones GetString y otros necesitan alguna forma de gritarle a usted si has pedido demasiado. Y la forma en GetString hace esto es si usted ha pedido más memoria que está disponible en el equipo, incluso si eso probabilidad super, super bajo porque ninguno de nosotros va a escribir un billón de caracteres y luego presione Enter, pero baja probabilidad pesar de que puede ser, yo todavía desea comprobar por si acaso, y el valor especial que vuelve GetString, respuesta, y otras funciones si algo ha ido mal es NULL en mayúsculas. ¿Y cuál es NULL? NULL que pasa de representar un puntero. Es la dirección de memoria 0. El mundo arbitrariamente decidió que, si se trata de la memoria de mi ordenador - ¿sabes qué? - vamos a robar a sólo 1 byte de memoria cada equipo, y ésta es la posición 0. Vamos a darle un apodo de NULL, y vamos a prometer que en realidad nunca poner los datos reales no porque simplemente arbitrariamente necesita un valor especial, 0, NULL aka, para que podamos gritar a los usuarios si algo sale mal. De lo contrario usted puede no saber qué decir 0 poner algo aquí o significa algo salió mal? Tenemos que estar de acuerdo todo lo que no significa nada NULL fue devuelto, sin dirección real fue devuelto. Ahora, aquí estoy adoptando mi convención humana de regreso de un principal si algo sale mal. Esto se debe a la convención principal de retorno es devolver 0 si bien, 1 o algún otro valor si es mala. Pero GetString y cualquier otra función que se ocupa de los rendimientos de memoria NULL si algo sale mal. Bien. Así que, lamentablemente, la línea 27, super simple que sea, no puede copiar completamente la cadena. ¿Por qué? Podemos ver esto como sigue. Estoy reclamando en la línea 27 se hace una copia de s y decir que es t. Así que no estoy preguntando al usuario por 2 cadenas en esta ocasión, sólo estoy diciendo que el valor en s debe ser puesto en t también. Así que ahora sólo para demostrar cómo rota esto es, en la línea 29 en adelante ¿qué estoy haciendo? En primer lugar estoy comprobando si la longitud de t es mayor que 0. Hay un poco de cuerda allí. El usuario escribe algo pulg ¿Cuál es la línea 32 hace, al parecer? [Respuesta de los estudiantes inaudible] Derecho. >> Se puede inferir de la misma especie a partir de lo que he dicho que está haciendo. Pero, técnicamente, lo que se esta haciendo? t [0] representa qué? [Estudiante] El carácter cero. >> [Malan] El carácter cero. O, más parecidos a los humanos, el primer carácter en t, sea lo que sea, H tal vez en este caso. Y toupper hace lo que dice. Se aprovecha el carácter cero de toneladas y lo cambia. Así que esto significa tomar el carácter cero de t, lo convierten en mayúsculas, y poner de nuevo en ese mismo lugar. Así que si yo escriba hello en minúsculas, esto debe cambiar la h minúscula a mayúscula H. Pero el problema es que en las líneas 35 y 36, lo que voy a hacer es imprimir para nosotros s y t. ¿Y cuál es tu corazonada? ¿Qué es lo que realmente va a ver si he escrito en hola en minúsculas? ¿Qué va a quedar impreso? >> [Respuesta de los estudiantes inaudible] >> ¿Qué es eso? [Estudiante] Big H y el resto pequeñas. >> La gran H y el resto pequeño para que, s o t? [Estudiante] Las dos cosas. Ambos >>. Exactamente. Así que vamos a ver lo que está pasando aquí. Déjenme seguir adelante y compilar esto. Esto es copy1, así que copia1. Está bien. Zoom in Déjame seguir adelante y ejecutar copy1, Intro, Decir algo: hola en minúsculas. Se capitaliza la copia, pero al parecer capitalizan el original y, porque lo que ahora sucede en esta historia? En la línea 27 que en realidad no parece estar copiando la cadena, pero a pesar de que podría haber esperado intuitivamente que ese sea el caso, si usted piensa acerca de esta foto, lo que realmente he hecho? La mitad de la imagen es el mismo. Así que vamos a retroceder en el tiempo para que t todavía no existe en la historia. S puede existir en la historia, pero vamos a minúsculas hola este momento. Así que vamos a arreglar lo que en realidad escrito pulg En este caso aquí tenemos h-e-l-l-o. Vamos a dibujar como una secuencia de caracteres, puse las líneas de separación aquí y mi 0 \. Así que aquí es donde somos tan pronto como la línea 1 a la 24-ish, más o menos, se han ejecutado. Esta es la foto de mi memoria. Cuando llego a la línea 27, que pasa? Al igual que antes, aparece un puntero, lo que voy a dibujar como esta plaza. Se llama t. ¿Y cuál es su valor por defecto? ¿Quién sabe? Algunos valores de basura. Así que me voy abstracto que fuera como un signo de interrogación. Y tan pronto como el lado derecho de la línea 27 se ejecuta, lo que me pone dentro de t? Lo mismo que hay en s. Así que si por un momento retirar esa abstracción de la flecha y decimos, oh, esta es la dirección de memoria de carga 123, cuando dices t consigue s, punto y coma, que está literalmente poniendo 123 aquí. Ahora si que tipo de simplificar nuestro mundo de nuevo con los cuadros, lo que ha hecho en realidad se acaba de agregar otra flecha en su mundo que está señalando de t en la cadena exactamente el mismo. Por eso, cuando en la línea 31 y 32 que van realmente sobre el cambio de t [0], lo que es t [0] al parecer sinónimo de ahora? s [0] Así que eso es todo lo que está pasando. Y aunque este tipo de se siente un poco bajo nivel y arcano y este tipo de se siente como quizás intuitivamente esto debería haber sólo funcionaba - He hecho copias de cosas antes y ha funcionado - si usted realmente piensa acerca de lo que realmente es una cadena, es un char *. Bueno, ¿qué es eso? Es la dirección de algún personaje. Entonces, tal vez tiene más sentido que cuando se trata de hacer algo súper aparentemente simple como esto, todo lo que estamos haciendo es copiar una dirección de memoria. Usted no está haciendo nada con la propia cadena. Así que incluso si usted no tiene idea de cómo se podría resolver este problema en el código, alto nivel, conceptualmente, ¿qué es lo que tenemos que hacer para que ta copia fiel de s, al parecer? Si. >> [Estudiante] Le daría una nueva ubicación? >> Exactamente. Tenemos que dar a t un lugar completamente nuevo. Tenemos que crear de alguna manera un mundo en el que tenemos un espacio de memoria, que sólo por razones de claridad voy a llamar justo debajo de éste, pero no tiene por qué estar allí. Pero tiene que ser del mismo tamaño, así que voy a dibujar estas líneas verticales en el mismo lugar. Está muy bien si esto es todo basura inicialmente. ¿Quién sabe qué estaba allí? Pero el paso 1 se va a tener que darme tanta memoria como que necesito para adaptarse a una copia de hola, a continuación, encontrar la manera de copiar el h aquí, el correo aquí, el l aquí y así sucesivamente. Pero esto ya se debe sentir un poco obvio, aunque algunos de los detalles son todavía abstracto. Para copiar esta cadena en este, es sólo un bucle for o while o algo con lo que te has convertido en lo más familiar. Así que vamos a probar esto. Déjame entrar en copy2.c. En copy2.c tenemos casi el mismo programa, a excepción de la línea 27. Se parece un poco complejo, pero si se descomponen poco a poco, el lado izquierdo es el mismo. Char * t crea esta cosa en la memoria, aunque con un signo de interrogación porque no tenemos ni idea de lo que hay por defecto. En el lado derecho estamos ahora la introducción de una nueva función malloc,, para asignar memoria, dame la memoria, y al parecer se cuántos argumentos, cuántas cosas entre paréntesis? Oí murmullos de 1 y 2, pero es sólo 1. No hay una coma, lo que significa que sólo hay una cosa dentro de los paréntesis. A pesar de que hay otros paréntesis, quisiera destacar lo que hay dentro de los paréntesis más externos, y es esta expresión: (Strlen (s) + 1) * sizeof (char). Así que si realmente pensar en esto, esto está diciendo dame la longitud de s. ¿Por qué soy, sin embargo, añadir 1 a la longitud? >> [Respuesta de los estudiantes inaudible] Exactamente. Necesitamos espacio para este tipo de la cola, el sexto personaje que no tiene ningún significado Inglés pero tiene un significado especial programático. Así que necesitamos un + 1 para eso porque strlen Devuelve la expectativa humana de longitud, hola o 5, no le da el carácter nulo adicional. Así que agregar manualmente este con + 1. Y después de esto, de tamaño * (char), no hemos visto esto antes. Esto no es técnicamente una función. Es una palabra clave especial que sólo te dice lo que el tamaño es de otro tipo de datos en un ordenador porque en realidad, algunos de nosotros tenemos equipos de 32 bits. Tengo un ordenador bastante antiguo en el país, y que sólo utiliza 32 bits para representar los punteros. Y si lo hacía tamaño de un tipo de datos, puede ser de 32 bits. Pero si estoy usando mi computadora nueva fantasía, que podría volver un valor de 64 bits algo así como una dirección. Así que en este caso, sólo para estar seguro super, no vamos a codificar algo como - así, ¿cuál es el tamaño de un char de acuerdo con lo que hemos dicho hasta ahora? Hemos prácticamente me dijo verbalmente que se trata de un byte, y eso es bastante cierto en todos los ámbitos. Pero, de nuevo, los supuestos tienden a ser malo. Conducen a software defectuoso si las personas usan su software de maneras que no pensaba. Así que vamos a abstraer esta lejos y más justo decir genéricamente Necesito esto muchos trozos de la memoria y cada trozo de memoria debería ser equivalente al tamaño de un carácter, que de hecho es igual a 1 en este caso, pero es una forma más genérica de escribir. Así que si la palabra es hola, cuántos bytes se malloc aparentemente asignar a saludar? [Estudiante] Seis. >> Six. Exactamente como muchos ya que tenemos signos de interrogación en la pantalla. Y luego tomar una conjetura ahora se basa en la comprensión de GetString ¿qué malloc probablemente regrese? >> [Estudiante] Una dirección. Una dirección de qué? Por el primer fragmento de memoria. No tenemos idea de lo que está allí porque alguna otra función podría haber estado utilizando esta memoria previamente. Pero malloc, como GetString, devuelve la dirección del primer byte de la memoria que se ha reservado para usted. Sin embargo, lo que no hace es rellenar el espacio en blanco con un carácter nulo barra invertida porque resulta que usted puede utilizar malloc para asignar cualquier cosa: enteros, cadenas, matrices, flotadores, estructuras estudiantiles. Puede utilizar malloc totalmente genérica. No le importa ni tiene que saber lo que la asignación de memoria para. Así que sería presuntuoso para malloc poner un 0 \ al final de cada trozo de memoria que te está dando porque \ 0 cosa es sólo una convención para las cadenas. No se usa para enteros, no se utiliza para los flotadores, no se utiliza para los estudiantes. Y así el gotcha con malloc es que la carga es totalmente de usted al programador para recordar la cantidad de bytes que asignan y no utilizar nunca un bucle for o un bucle while e ir más allá del límite de la cantidad de memoria que han dado. En otras palabras, tan pronto como se asigna memoria, no se puede pedir al sistema operativo, oh, por cierto, qué tan grande de un trozo de memoria fue esto? Es totalmente de usted para recordar si usted necesita ese valor. Así que vamos a ver cómo procedo a utilizar esta memoria. En la línea 28 y 29 ¿por qué estoy haciendo esto? Sólo tienes que comprobar la cordura total. Sólo en caso de que algo iba mal, pido algo increíble cantidad de memoria o tengo tantas cosas que se ejecuta en el equipo que simplemente no hay suficiente memoria, algo así, yo por lo menos desea comprobar nula. En realidad, la mayoría de las computadoras le dará la ilusión de que todos los programas Puede utilizar la totalidad de la memoria RAM, pero aún así, si el usuario escribe en una cuerda larga loco tal vez porque eres un chico malo y en realidad están tratando de bloquear el programa o truco en ella, desea comprobar al menos el valor de retorno de malloc y si es igual a null. Y si lo hace, vamos a dejar de fumar en este momento porque no sé qué hacer en ese caso. ¿Cómo puedo copiar la cadena? Hay algunas maneras de hacer esto. Hay str copiar funciones en C, pero es muy sencillo para nosotros hacer esto la manera antigua. En primer lugar vamos a averiguar cuál es la longitud de s es. Yo podría haber puesto esto en el bucle, pero en lugar de eso sólo hay que poner aquí para mayor claridad. Así n ahora almacena la longitud de la cadena original, que aparentemente es 5. Luego, en mi bucle para iterar desde que estoy en 0 hasta n, y en cada iteración estoy poniendo s [i] dentro de la [i]. Así que eso es lo que implicaba con mis dos dedos apuntando a las cuerdas antes. Como este bucle for itera así, yo voy a estar copiando h en aquí, e en aquí, yo en aquí porque este es s, este es t. Y por último, en la línea 35 ¿por qué estoy haciendo esto? Tengo que asegurarme de que estoy terminando la cadena t. Y lo hizo de esta manera a ser súper explícito. Pero proponer a alguien, si pudiera, una forma diferente de hacer esto. Yo realmente no necesita la línea 35. Hay otra manera de hacer esto. Si. >> [Respuesta de los estudiantes inaudible] >> Dilo fuerte. [Estudiante] Menor o igual a. >> Exactamente. Podríamos decir inferior o igual a n, que en general ha sido mal porque casi siempre cuando subimos a un igual a lo que estamos contando vamos un paso demasiado lejos. Pero recuerde, la cantidad de bytes que se asignan? Se asignaron de strlen s, por lo que 5 + 1 para un total de 6. Así que en este caso podríamos hacer algo como esto por lo que estamos copiando no sólo el saludo sino también el 0 \ al final. Alternativamente, podríamos usar una función llamada str copia, strcpy, pero que no sería divertido casi como mucho. Pero eso es todo lo que hace por debajo de la capucha. A continuación, por último, hacemos lo mismo que antes. Yo t capitalizar y luego me dicen que el original están presentes y la copia es así. Así que vamos a tratar ahora. Déjame aquí. Hacer copy2. Vamos a ampliar y ejecutar copy2. Voy a escribir hola en minúsculas, y de hecho tengo minúsculas hola que el original pero el capital Hola para la copia. Pero no he terminado todavía. Tengo que hacer una última cosa aquí. 46 y 47 está claramente cómo liberar memoria, pero ¿qué significa eso realmente? ¿Qué estoy haciendo, ¿crees que, llamando a la línea 46 y la línea 47? ¿Qué efecto tiene eso? Si. [Respuesta de los estudiantes inaudible] >> Exactamente. Usted se acaba de decirle al sistema operativo, hey, gracias por este recuerdo. Ahora puede utilizar para otra persona. Y aquí está un ejemplo perfecto de los valores de basura. Acabo de utilizar esta memoria para escribir la palabra hola en 2 lugares, aquí, aquí, aquí y aquí. Así que este es h-e-l-l-o-\ 0. Pero entonces llame a la línea 46 y la línea 47, y ya sabes lo que pasa allí en términos de la imagen? En realidad, esperar, esta imagen es la antigua. Una vez que la copia sea, este hombre está apuntando aquí, así que vamos a quitar los números y sólo abstraer como nuestras flechas de nuevo. ¿Qué sucede en este cuadro cuando llamo libre? [Respuesta de los estudiantes inaudible] >> Ni siquiera. Si llamo gratis en s y t - una especie de pregunta capciosa - este panorama no cambia en absoluto porque llamando y llamando s t le dice al sistema operativo, hey, usted puede utilizar esta memoria de nuevo, pero eso no cambia este valor nulo o algún carácter especial, no cambia esto, no cambia el h o e el o la l o l o el o ya sea en el lugar para cualquier otra cosa. En cuanto a la imagen, tan pronto como se llame cambios libres, nada. Y ahí está el origen de los valores de basura porque si luego más adelante en este programa hacer que el sistema operativo para obtener más memoria con malloc o GetString o algo por el estilo y el sistema operativo dice, claro, tengo 12 bytes de memoria sólo liberados, utilizar estos, ¿qué vas a ser entregado? Usted va a ser entregado un trozo de memoria que normalmente se basaría con signos de interrogación, pero ¿cuáles son los signos de interrogación? Que se encuentren h-e-l-l-o, h-e-l-l-o. Estos son nuestros valores nuevos de basura tan pronto como liberar esa memoria. Hay una implicación mundo real aquí también. Esto sucede que ver con la RAM, pero los equipos en realidad hacen lo mismo con el disco. Hablaremos de esto en particular con un conjunto de problemas futuros que se centra en la medicina forense. Pero lo que realmente sucede si tiene algún archivo financiera sensible en el escritorio o alguna vaga JPEG y lo arrastra en su basura, lo que pasa cuando lo arrastra a la basura o la papelera de reciclaje? Usted sabía lo que estaba hablando. [Risas] ¿Qué sucede cuando se ha arrastrado tales documentos a la papelera de reciclaje o bote de basura? [Respuesta de los estudiantes inaudible] Bueno, así que ten cuidado. ¿Qué sucede cuando usted hace eso? La respuesta corta es no, ¿verdad? Expediente incompleto o sensible todavía allí sentado en algún lugar de su disco duro. La mayoría de nosotros por lo menos hemos aprendido por las malas que es necesario vaciar la basura o la papelera de reciclaje para eliminar realmente los archivos. Y, en efecto, al hacer clic o clic con el botón de control en el bote de basura o seleccione Archivo, Vaciar papelera o lo que sea y que en realidad vaciar la papelera o papelera de reciclaje, lo que realmente sucede entonces con esta imagen? Más nada. Así que nada sucede realmente en el disco. Y si sólo temporalmente divagar y escribir - I'Ll sólo tiene que utilizar la parte de atrás de esto. Así que ahora la historia está cambiando de RAM, que es donde existen programas mientras está en funcionamiento, el disco, que es donde se almacenan a largo plazo incluso cuando se va la luz, por ahora - y volveremos a ello en el futuro - vamos a pretender que esto representa el interior del disco duro de su ordenador porque en su día lo que solía ser discos circulares, al igual que los disquetes. Así que si usted tiene un poco de sensibilidad archivo de Excel, puede tardar hasta este trozo de memoria en el disco de su computadora, y estoy dibujando 1s y 0s mismo arbitrario. Al arrastrar el archivo al igual que a su bote de basura o la papelera de reciclaje, literalmente no pasa nada, ya que Apple y Microsoft acaba de decidir la papelera y papelera de reciclaje es en realidad un marcador de posición temporal. Tal vez, finalmente, el sistema operativo se vaciarlo para usted, pero por lo general, no hace nada, al menos hasta que estés realmente poco espacio. Sin embargo, cuando se va a la basura vacía o vacía la papelera de reciclaje, Del mismo modo, no ocurre nada a esta imagen. Todo lo que sucede está en otro lugar en el equipo, hay una especie de mesa. Es algo así como una hoja de trucos poco que dice que, digamos, resume.doc, por lo que su hoja de vida en un archivo de Microsoft Word solía vivir en el lugar 123 en el disco duro, no en la memoria y no en la memoria RAM, pero en su disco duro, y sus vidas incompletas JPEG con 456, y el archivo de Excel vive en 789 o donde sea. Al eliminar archivos en realidad vaciar la basura o la papelera de reciclaje, esta imagen no cambia. La 0s y 1s en su disco duro no van a ninguna parte. Pero esta mesa, esta base de datos poco de suerte, sí cambia. Al eliminar su hoja de vida, es como si el archivo se elimina en cierto sentido, pero todo el equipo no se olvide que lo que vive en su disco duro. El 0 y 1 que componen su hoja de vida o de cualquiera de estos archivos se encuentran aún intactos. Así que si usted lo hizo accidentalmente, todavía hay una probabilidad distinta de cero que usted puede recuperar sus datos utilizando Norton Utilities o algún software comercial cuyo propósito en la vida es encontrar 0s y 1s que han quedado huérfanos a causa del tipo, olvidado aquí, pero salió de aquí, para que pueda recuperar los datos. O los investigadores forenses con la policía o el FBI en realidad tendría un disco duro y realmente buscar patrones de 0s y 1s que se parecen a imágenes JPEG, se parecen a los archivos de Excel, y recuperarlas de esa manera, incluso si el equipo se ha olvidado de ellos allí. Así que la única manera de realmente eliminar los datos, como veremos en el futuro, es fregar o limpiar el archivo o disco duro - Realmente no se puede eliminar el 0 y 1 porque de lo contrario empezaría con una unidad de disco duro gigabyte y que iba a terminar con un disco duro megabyte si constantemente se borrar, literalmente, 0s y 1s. Entonces, ¿qué haría usted si realmente quería cubrir sus pistas y el problema fundamental es que todavía hay 0s y 1s en el disco? Veo a alguien que físicamente gesticulando rompería el dispositivo. Eso va a funcionar. [Risas] Pero si eso es algo de una solución cara, lo que sería más razonable? Si. >> [Estudiante] Sobrescribir ellos. >> Sobreescribirlos con qué? >> [Estudiante] Otros datos. Otros datos. Usted puede sobrescribir el disco con 0s o 1s o 0s todos, todos 1s. Y eso es precisamente lo que algunos de los programas hace. Usted puede comprar el software o incluso conseguir el software libre, e incluso integrada en Mac OS en estos días, por lo menos en Windows, es la capacidad de borrar de forma segura. En realidad, si usted quiere todo jonrones hoy si tienes un Mac y hacer esto, si tienes algunas cosas en su bote de basura, puede hacerlo Secure Empty Trash, que hace exactamente eso. En lugar de borrar archivos sólo aquí, no borra el aquí 0s y 1s, más bien, sólo cambia todos ellos, por ejemplo, a 0s y punto, punto, punto. Así que uno de los conjuntos de procesadores futuros en realidad será recuperar intencionalmente datos - fotografías que hemos tomado de las personas, lugares y cosas en el campus para que vamos a hacer una imagen forense de la tarjeta de memoria de una cámara digital, que es la idea misma - y que tendrá que ser desafiados a encontrar realmente los patrones que representan imágenes JPEG en el disco duro, al igual que el ex estudiante cuyo correo electrónico que leí hace unas semanas hizo para recuperar fotografías de su hermana. ¿Por qué no nos tomamos un descanso de 5 minutos aquí, y vamos a reagrupar con más memoria. Así que aquí es donde las cosas se ponen un poco alucinante, pero este es un paso muy potente hacia la comprensión de este aún más. Aquí hay un programa llamado pointers.c. Es uno de código de ejemplo de hoy. Note que en las primeras líneas, 19 a 22, todo lo que estamos haciendo es algo así como GetString y devolver una dirección, almacenándola en s. A partir de entonces para pset incluso 3 si quieres pero pset 4 y en donde usted puede comenzar a tomar estas ruedas de entrenamiento fuera de ti mismo, no hay ninguna razón para pretender que las cadenas de dejado de existir. Es ciertamente correcto empezar diciendo char *. Como acotación al margen, en referencias en línea y en los libros que a menudo puede ver la estrella junto a la variable. Usted podría incluso ver los espacios alrededor de los dos lados de la misma. Todos estos son funcionalmente correcto. Por ahora, sin embargo, vamos a estandarizar este método para hacer super claro char * que es como decir puntero a caracter. Ese es el tipo de datos. Y a continuación, el nombre de la variable s es en este caso. Para ello hemos conseguido una cuerda y lo hemos llamado s. Y entonces aquí cuenta de que estoy haciendo en realidad un poco de engaño. Esto se llama aritmética de punteros, que es una especie de súper simple. Sólo significa sumar y restar números a los punteros. Pero esto realmente funciona. Este programa aparentemente imprime la cadena s 1 carácter por línea de tal manera que el resultado final - Sólo así podemos echar a perder a dónde va esto, hacer sugerencias, ejecute punteros, déjame zoom in Ahora me deja escribir algo como HOLA y el tipo Intro e imprime un carácter por línea. Hasta hace un segundo, hubiéramos hecho esto con notación de corchetes. Tendríamos un bucle for y que haríamos printf de s [i] y nos gustaría hacer eso una y otra vez y otra vez con un n barra invertida al final de cada línea. Pero este programa es diferente. Este programa se utiliza, literalmente, la aritmética. Entonces, ¿qué está pasando aquí? En primer lugar, antes de que este lazo aún se ejecuta, lo que, para ser claros, es realmente s? S es? >> [Estudiante] Una dirección. >> Una dirección. Y es la dirección de, en el caso de hola, el primer carácter de la palabra, que es h. Así que s es, en este ejemplo particular, la dirección de h. Entonces, ¿qué significa eso para hacer s + i? Bueno, i comienza en 0 en este bucle for. Hemos hecho muchas veces. Me va a subir a la longitud de la cadena, al parecer. Así que en la primera iteración de este bucle, i es evidentemente 0. Así que esta expresión está diciendo s + i - más bien, s +0, eso es, obviamente, sólo s. Entonces, ¿qué es * s aquí? Ahora estamos utilizando la estrella de una manera ligeramente diferente. Déjame ir por delante y deshacerse de t porque hemos terminado hablando de t y copias de s. Ahora sólo quiero contar una historia que involucra s. Y así, en este momento, después de tipo string, nuestro mundo se ve absolutamente como lo hacía antes con sólo s almacenar la dirección de h y de manera más general que señala en la cadena hola. Si ahora hago una línea como * (s + i), vamos a probar esto. Así * (s + i). Permítanme simplificar esto porque esto es 0, por lo que este es * (s +0). Bueno, espera un minuto. Simplificar aún más. Esto es * (s). Bueno, ahora los paréntesis son una especie de estúpido, así que ahora vamos a hacer * s. Así, en la primera iteración de este bucle, que la línea que está resaltado, 26, es más o menos equivalente a la impresión de esto. ¿Cuál es el tipo de datos * s? En este contexto, porque la estrella pasa a ser casi el mismo s, pero más específicamente, porque ya no estamos declarando s, no estamos creando una variable más, no hay ninguna mención de char * en la línea 26, no hay mención de la cadena de palabras clave, sólo estamos usando una variable llamada s, Resulta que ahora la estrella tiene un poco diferente y, sin duda, confundiendo el significado. * S aquí significa ir a la dirección de s e imprimir lo que está allí. Así que s está aquí, s * es - algo así como Serpientes y Escaleras, siga la flecha - aquí. Así que esto es * s. Así que lo que se imprime en la primera iteración de ese bucle en la línea 26? Puedo imprimir% c, que es el marcador de posición para un carácter, entonces un \ n para una nueva línea. * (S + i), donde i es 0 es precisamente esto. Entonces, ¿qué puedo hacer carbón en lugar de c%? H. En la siguiente iteración del bucle - es probable que pueda ver dónde va esto - la siguiente iteración i es obviamente 1, por lo que este medio s +1, y ahora me hace falta el paréntesis porque ahora la estrella tiene que decir ir a la dirección de memoria s +1. ¿Cuál es s? Vamos a retroceder en el tiempo y decir esto ahora arrow realidad no se nos está haciendo ningún favor. Que es más específicamente decir que este es el almacenamiento de la serie 123 ya que el inicio de esta cadena hola, esta es la dirección 123, esto es 124, y así sucesivamente. Así que en la segunda iteración cuando digo s +1, que es como decir que un 123, también conocido como 124, así que lo que se imprime caracteres en la segunda iteración? E en dirección de memoria 124. Entonces + más, 125, 126, 127, y por suerte este bucle se detiene antes de llegar aquí porque estoy usando strlen para asegurarse de que no cuenta demasiado alto. De modo que también lo es. De nuevo, esto es como si hubiéramos hecho hace una semana. Deja que lo escriba en la línea de abajo a pesar de que no queremos hacer ambas cosas. Esto es idéntico a este ahora. Así que, aunque s es una cadena, como lo hemos estado llamando durante semanas, s es realmente un char *. Así que si queremos ser súper anal, es muy adecuado para escribir el carácter específico en la posición i-ésima usando estas direcciones numéricas y de este operador estrella, pero, francamente, esto es simplemente mucho más limpio. Así que esto no es malo. No hay razón para dejar de hacer la línea 27 aquí, pero el 26 es funcionalmente el mismo, y es funcionalmente lo mismo exactamente por las razones que hemos estado discutiendo hasta ahora. Y por último, 29 es sólo una buena práctica. Llamar gratis de s significa que ahora usted está dando de nuevo la memoria que le dio GetString porque, de nuevo, como he mencionado lunes, GetString por semana ha sido la introducción de un bug en el código. Su código de semana ha tenido pérdidas de memoria por el que usted ha estado preguntando GetString para la memoria, pero nunca he estado dando vuelta. Y eso fue elegido deliberadamente por nosotros pedagógicamente porque es simplemente demasiado como para pensar en el principio. Pero ahora necesitamos más simetría. Si le pide al equipo para la memoria, como es el caso de GetString, como es el caso aparentemente para malloc, Ahora debe de pset 4 en adelante también liberar la memoria tal. Tenga en cuenta que esto es diferente de decir n int. No es necesario para liberar a esto porque usted no llamó a GetString y usted no llamó a malloc. E incluso si usted llama getInt ya que finalmente va a ver, GetInt no asigna memoria para usted, porque en realidad se puede pasar alrededor de los números enteros y flota y caracteres exactamente de la manera que hemos estado haciendo durante semanas. Cuerdas, sin embargo, son especiales porque en realidad son la concatenación de caracteres múltiples. Así que son sólo diferentes de caracteres y carrozas y enteros y similares. Pero vamos a volver a eso en poco tiempo. Cualquier pregunta luego en este inicio de punteros? Si. [Pregunta estudiante inaudible] Ah, muy buena pregunta. Una de las pocas cosas en realidad C hace por ti, lo que es conveniente, se da cuenta de que para ti lo que el tamaño es del tipo de datos y luego hace ese tipo de multiplicación para usted. Esto es irrelevante en el caso de los caracteres, ya que casi siempre es un char es un byte, así que esto funciona. Pero por el bien de la discusión, si en realidad estaban imprimiendo los números enteros y que estaba tratando de imprimir un poco de s valor que se apunta a un número entero, Del mismo modo que no tendría que hacer + 4 * i sólo porque un int es de 4 bytes. La aritmética de punteros significa que C y el compilador hacer todo lo que cálculos por usted. Todo lo que tienes que tener en cuenta es la cuenta en una especie de sentido humano. Si. [Estudiante] Si se declara una cadena dentro de un bucle for, tienes que liberarlo más tarde? Buena pregunta. Si se declara una cadena dentro del bucle for, ¿es necesario para liberarlo más tarde? Sólo es necesario para liberar la memoria que se puede asignar a GetString o con malloc. Así que si usted acaba de decir algo como - déjame poner llaves ahora lo que todo el código está relacionado. Si hizo algo, aunque buggily, como este, char * t = s, usted no necesita t t libres porque no incluía ninguna mención de malloc o GetString. Si por el contrario te hizo esto, GetString, entonces sí, usted tendría que t libres. Y de hecho, la única oportunidad de hacerlo es ahora dentro de este bucle, para la misma edición de alcance que hemos discutido en el pasado. De lo contrario, estaría la asignación de memoria, asignación de memoria, asignación de memoria, y al final del programa, porque estás fuera de ese circuito, t no existe, pero nunca se dijo que el sistema operativo que no era necesario que la memoria más. Y en poco tiempo, por pset 4 o 5 te equipará con un programa llamado Valgrind, que es similar en espíritu al BGF ya que tiene algo así como una interfaz arcano, pero su propósito en la vida es ayudar. Y Valgrind es un programa que en el futuro busque sus programas en busca de fugas de memoria, ya sea por GetString o malloc, que vamos a empezar a utilizar con mayor razón ahora que deje de usar la biblioteca CS50 tanto. Por fin ahora tenemos una especie de vocabulario y el tipo de modelo mental en la teoría con los que resolver este programa rota. Así que en este programa rota, swap trabaja dentro de swap, pero en realidad nunca funcionó en la principal causa principal pasaba en x e y, recordemos, y los que fueron pasados ​​por en valores, por así decirlo. Las copias de ellos fueron dados a cambiar. Al final del intercambio, a y b se había hecho intercambiado, pero, por supuesto, x e y, como vimos el lunes, no lo había sido. Así que propongo en verde aquí que esta es realmente la solución aquí. Y, de hecho, vamos a mover mis estrellas para estar en consonancia aunque, de nuevo, funcionalmente esto no importa. En las próximas semanas vamos a explicar cuándo y por qué es importante. Así, en verde ahora es una solución. Francamente, parece mucho más desordenado porque tengo todas estas estrellas. Permítanme señalar una cosa. La línea superior aquí donde dice int * a * b e int fundamentalmente haciendo lo mismo que siempre ha hecho. Se declara dos argumentos o parámetros a cambiar, el primero de los cuales es un puntero int llamada, el segundo de los cuales es un puntero int llamado b. Lo único que hay de nuevo en este punto es el hecho de que hay una estrella allí. ¿Qué significa eso? A no es un int, b no es un int. Una es la dirección de un entero y b es la dirección de un int diferente. Aquí abajo, aquí es donde admito C vuelve confuso. Ahora estamos utilizando una estrella, pero tiene un significado diferente en este contexto. Porque no estamos declarando punteros como estamos aquí, aquí estamos dereferencing cosas. Así que, técnicamente, la estrella en este contexto de la primera línea, segunda y tercera dentro de swap es el operador de indirección, lo cual significa ir allí. Así que como mi dedo seguía la flecha en h, * A los medios ir a esa dirección y me hallaréis, el int que está ahí. * B medios ir a la dirección y me pasa lo que hay. Así que vamos a volver a dibujar la imagen de lunes ahora usando una pila de marcos, el fondo de la cual va a ser principal, el superior de los cuales va a ser swap, para que nuestro mundo se ve, al igual que lunes, así. He aquí un trozo de memoria que principal se va a utilizar. Recuerde del lunes que el programa sólo tenía 2 variables, uno llamado X y un llamado y, y yo había puesto los números 1 y 2 hay. Ahora, cuando yo llamo cambiar como lo hice el lunes, anteriormente cuando he utilizado la versión roja de este programa, que tiene este aspecto, Tengo dos parámetros, a y b, y lo que escribimos aquí y aquí? Sólo 1 y 2, literalmente copias de x e y. Hoy podemos cambiar eso. Hoy en vez de pasar en enteros a y b que vamos a pasar en dos direcciones. Las direcciones de suceder para que apunte a ints, pero esas direcciones no son ellos mismos intercepciones. Son direcciones. Es como una dirección postal. Así que ahora tenemos que acaba de darme un poco más detalle en la pantalla. Esta es la memoria de mi computadora, ya que ha estado todo el día. Ahora necesitamos algo de arbitrario esquema de numeración. Así que vamos a decir, por casualidad, que esta es la dirección de memoria de 123, 124. Digamos que este es de 125, esto es 126, y así sucesivamente, pero eso es totalmente arbitraria. Sólo necesitamos un esquema de numeración en mi memoria. Así que ahora cuando realmente pasa en x e y, no voy a pasar en X e Y; Voy a pasar en la dirección postal, por así decirlo, de x y de y de modo que lo que se almacena aquí y aquí no es 1 y 2, pero si puedes ver mi pequeño texto, lo que se pasa por aquí y aquí? [Respuesta de los estudiantes inaudible] >> Exactamente. 123 se puso aquí y 124 se puso aquí. Ahora, porque yo la estrella de esta forma primera línea aquí en la parte superior, mi programa sólo sabe que 123 y 124, aunque son obviamente enteros que cualquier humano podría notar, ellos deben ser interpretados como direcciones, direcciones numéricas. No son en sí mismos enteros, que son las direcciones, y eso es porque me he puesto explícitamente las estrellas allí. Así que ahora en mi línea de primera, segunda y tercera de código real lo que sucede aquí? Vamos a dibujar el resto de la imagen. Tmp es igual que lo fue el lunes. Nada especial en tmp. Está a sólo unos locales de 32 bits variable, y dentro de ese parecer estoy almacenando el valor de * a. Ahora, si me acaba de decir tmp = a, lo que me puso aquí? >> [Estudiante] 123. 123. Pero eso no es lo que estoy haciendo. Estoy diciendo tmp = * a. Significa estrella ir allí. Así que aquí está una, 123. ¿Cómo puedo ir? Imagina como si hubiera una flecha. Bueno, ahí está, 1. Así que lo que se almacena en tmp, al parecer? A sólo 1. En otras palabras, tmp es * a *, un medio de ir a la dirección que se encuentra actualmente en una, que aparentemente es 123. Bueno, aquí estamos en la posición 123, veo el número 1, así que me voy a poner el número 1 allí. Ahora, ¿qué es lo que hago en la línea 2, * a * = b? Este es un poco más complicado porque ahora lo que es un? Es 123. Así que * a es ¿dónde? Justo donde estaba antes. Así que ir allí. Bien. Ahora, por último, y, finalmente, se empezará a tener sentido, es de esperar, * B significa que lo que está en b? 124. Así que tengo que ir allí, que es 2. Entonces, ¿qué me pongo a dónde? 2 entra aquí porque va a * b * a. Así que voy a hacer eso. Y ya se puede ver, tal vez, que estamos mucho más cerca a la solución de este problema estúpido, simple correctamente por primera vez porque ahora todavía nos queda un recuerdo de lo que era x, tenemos 2 copias, sin duda, de y, pero ahora dice que la línea 3 * b. Así que aquí está b. B * significa ir allí. Entonces, ¿dónde es la ubicación 124? Es al parecer aquí. Entonces, ¿qué pongo aquí? Obviamente, tmp. Así que ahora hago esto. Así que tengo una aquí y 2 aquí. Y ahora, ¿qué pasa con todo esto, el 123, el 124, y el 1? Tan pronto como retornos de swap, esta memoria es tan buena como perdido porque tan pronto como retornos de intercambio, el sistema operativo es libre de utilizar la memoria de nuevo en el futuro. Sólo la memoria principal en la parte inferior de esta pila de llamada se pega alrededor. Y así, por fin tenemos ahora una versión de trabajo. Déjame entrar en swap.c y observe lo siguiente. En la parte superior del programa que he cambiado mi prototipo para ser int * a * b e int. Así que lo único que cambié para ir de rojo, que era malo, al verde, lo cual es bueno, se le añadí estas estrellas de hoy. Pero aquí abajo, en sí mismo cambiar tuve que copiar, pegar lo que era justo en la diapositiva. Tengo aquí una estrella, la estrella aquí - que coincide con el prototipo - y entonces todas estas cosas ahora tienen estrellas excepto tmp porque el uso de una variable temporal, no hay nada nuevo allí. Sólo necesito de almacenamiento temporal para un int. Así que no necesitamos una estrella allí. Sólo necesitamos la estrella para que podamos atravesar este tipo de límite arbitrario entre estos dos marcos en la memoria de mi ordenador. Pero una última cosa tiene que cambiar, y que podría haber vislumbrado ya. ¿Qué otra línea es obviamente diferente ahora? >> [Los estudiantes] y x. Sí, así que 25 es la última línea de código que necesita cambiar para que esto funcione. Hace una semana y hasta el lunes de la línea 25 se veía así, intercambie x e y, y esta se rompió porque si dices swap (x, y) le está dando copias de x e y para intercambiar, entonces está haciendo lo suyo, pero nunca en realidad está cambiando xey sí mismo. Así que incluso si usted nunca ha visto antes a este personaje con el símbolo de unión en el código, acaba de tomar una conjetura. ¿Qué significa el símbolo de unión hacen, al parecer? [Estudiante] Tome la dirección. >> Toma la dirección. De modo que el signo está diciendo dame la dirección de x. ¿Quién sabe dónde está? Le pasa a ser 123. No me importa. Sólo dame la dirección de x. & Y significa dame la dirección de y. Y en ese punto la historia es perfectamente coherente con la imagen que dibujó hace un momento. Así que voy a admitir punteros, sin duda para mí cuando empecé a aprender esto, fueron sin duda una de las cosas más difíciles de envolver mi cabeza alrededor. Pero dese cuenta, sobre todo porque seguimos jugando con este tipo de cosas, si lo desglosamos a esta clase de súper simple intelectualmente interesantes problemas de mover sólo los números más, la respuesta a una gran confusión con los punteros realmente se pueden derivar de estas mecánicas muy básicas. Aquí está la dirección. Ve allí con la estrella. O a la inversa, esto es un símbolo de unión. Averiguar cuál es la dirección que realmente es. Está bien. Entonces, ¿dónde está toda esta memoria viene? Hemos elaborado esta imagen un par de veces, y me siguen prometiendo que vamos a volver a ella, pero aquí es la representación de la memoria del equipo que es un poco más marcado que nuestro pizarrón aquí está. El segmento de texto en la parte superior representa lo que respecta a su programa? [Respuesta de los estudiantes inaudible] >> ¿Cómo? Dilo de nuevo. [Estudiante] El programa actual. >> El programa en sí. Así que el Clang 0 y 1 que ha compilado después de escribir código C y que luego y la generación de extremos 0s y 1s hasta quedar escondido allí en la memoria porque cuando se hace doble clic en un icono en tu Mac o PC o ejecutar un comando como mario en su sistema, su 0s y 1s de disco se cargan en la memoria para que el ordenador pueda manipular y ejecutarlas con mayor rapidez. Así datos inicializados y datos sin inicializar, no vamos a hablar mucho de ellos, pero eso son sólo las variables globales. Inicializar las variables globales significa que usted dio a valores; sin inicializar variables globales significa que usted todavía no dan valores a. Entonces hay estas variables de entorno que estoy totalmente de onda va la mano menos, pero están ahí y que almacena cosas como su nombre de usuario y otro tipo de información de nivel inferior. Pero los más jugosos trozos de la disposición de su memoria es esa cosa llamada la pila y el heap. La pila de nuevo, para que quede claro, es la memoria que se utiliza cada vez que se llama a funciones, siempre que hay variables locales y siempre que haya parámetros que se pasan alrededor. Todo esto ocurre en la pila. El montón no hemos hablado, pero tomar una conjetura que usa la pila. Sólo una parte diferente de la memoria. Le pasa a ser dibujado aquí en la parte superior, pero eso es una convención pictórica arbitraria. ¿Quién está al parecer se utiliza la memoria del montón por semanas? Es técnicamente pero indirectamente. >> [Estudiante] GetString. GetString y malloc. Así que aquí está la diferencia fundamental. ¿Sabes para las últimas semanas de que si necesitas memoria, sólo declarar una variable. Si usted necesita mucha memoria, declarar una matriz de derecho dentro de su función. Pero el problema que hemos mantenido enfrentamos es si declara las variables locales dentro de funciones, tan pronto como la función retorna, lo que ocurre con la memoria y las variables de esos? Sólo especie de que ya no es tuyo, ¿no? Simplemente desaparece una especie de vista conceptual. Sigue siendo físicamente allí, obviamente, pero ya no es su derecho de uso. Esto es obviamente problemático si quieres escribir funciones en la vida que en realidad asignar memoria y no devolverlo inmediatamente. Caso en cuestión: GetString propósito en la vida es no tener idea de antemano lo grande de una cadena que voy a escribir en el teclado, sino que tiene que ser capaz de asignar memoria para contener David o hola o un ensayo entero de que el usuario podría haber escrito pulg Así GetString ha estado usando malloc. Malloc por lo tanto no debe utilizar la pila; sino que está usando esta cosa llamada el montón. No hay nada diferente en la memoria. No es más rápido o más lento o algo por el estilo. Es sólo físicamente en un lugar diferente. Pero la regla es que la memoria que está asignada en el montón Nunca será quitado de vosotros, hasta que se llama - tomar una conjetura - libre. Por el contrario, cualquier memoria que pedir en la pila con sólo declarar una matriz o declarar una variable como la que hemos estado haciendo durante semanas, que, por defecto termina en la pila. Y que funciona muy bien 90% del tiempo, pero en esas ocasiones más raras en la que desea asignar la memoria y mantener a su alrededor, entonces usted necesita utilizar una función como malloc. O hemos utilizado una función como GetString, que a su vez utiliza malloc. Vamos a ver dónde podría romper hacia abajo y luego echar un vistazo a Binky. Volveremos a que en el futuro. Aquí hay un programa super sencillo que en las primeras 2 líneas hace qué? En Inglés, ¿qué estas primeras 2 líneas de código realizan dentro de la principal? [Respuesta de los estudiantes inaudible] Con cuidado. No me da la dirección de x o y. [Estudiante] Proporciona punteros a enteros. Bueno >>. Dame 2 punteros a enteros. En otras palabras, me dan 2 trozos de memoria que guardo dibujo hoy, a pesar de que lo ha borrado ahora, como cuadrados. Dame dos trozos de memoria, una llamada x, que se llama y - antes me llamaban s y t - y cuál es el tipo de ese trozo de memoria? Se va a almacenar una dirección. * Es de tipo int. Así que la dirección de un int con el tiempo va a vivir en x, la dirección de un int con el tiempo va a vivir en y, pero en un principio, lo que hay dentro de x e y? ¿Quién sabe? Valores de basura. No tiene nada que ver con punteros. Si no hemos puesto algo allí, ¿quién sabe lo que está realmente allí? Ahora, x. ¿Qué sucede aquí? Esto es de fiar porque ahora x es un puntero. Es un * int. Así que eso significa que puedo poner en la dirección x de algún trozo de memoria. ¿Qué malloc volver? Perfecto, devuelve las direcciones, la dirección del primer byte de un pedazo entero de memoria. ¿Cuántos bytes se esta asignando al parecer, por ejemplo, en el aparato? ¿Cuál es el tamaño de un int? 4. Si piensas en la semana 1, no es super importante recordar siempre que, pero en este caso, es útil saber, 4 bytes. Así que esta es la asignación en el montón de 4 bytes y se devuelve la dirección de la primera que me arbitrariamente. Ahora, ¿qué está haciendo x? A * x = 42 está haciendo qué? Si en este punto de la historia que tenemos x, que tiene este aspecto con un valor basura, esto es ahora y con un valor basura, ahora en la línea 3 que he asignado 4 bytes. Este cuadro esencialmente se parece a esto. O más específicamente, si esta es la dirección arbitraria 123, esto es lo que nuestra historia ahora parece. * X = 42 ahora ¿qué significa? Eso significa ir a la dirección 123 y poner el número 42 allí. No es necesario dibujar estas líneas porque no estamos haciendo cadenas. Debería haber escrito así, y sólo por causa de la manifestación, 42 como un tipo int ocupa mucho espacio, 4 bytes. Así que eso es lo que ha pasado allí, pero hay un problema ahora. * Y = 13. ¿Qué va a pasar aquí? El problema es y * en nuestro mundo simplificado sólo significa ir a la dirección en y. ¿Qué hay en y? Es cierto valor basura. Así que vamos a suponer que ese valor es 5551212 basura, algo de loco. * Significa que Y van a abordar 5551212. Esto es así por aquí. No existe, por ejemplo. Así obtiene 13 * y medio que estoy tratando de dibujar 13 aquí. No existe. He superado el segmento de la pizarra. ¿Qué obtengo? Ese mensaje críptico error de segmentación porque estoy tratando de poner en la memoria un valor como 13 en un lugar que no existe. El resto del programa puede funcionar bien, pero hasta ese momento no lo hace. Así que vamos a tratar de contar esta historia. Volveremos a que una vez que hemos hablado hexagonal. Volvamos a esto y concluir con esta cosa llamada Binky, que recuerdo es un profesor de Stanford que se sienta como en casa jugando con plastilina, para contar la historia de exactamente el mismo programa. Es sólo alrededor de 3 minutos de duración. Aquí tenemos Binky. [Hablante masculino en el vídeo] Hey Binky, despierta. Es tiempo para la diversión puntero. [Binky] ¿Qué es eso? Aprenda acerca de los punteros? Oh, qué bien! [Hablante masculino] Bueno, para empezar, creo que vamos a necesitar un par de punteros. [Binky] Bueno. Este código asigna 2 punteros que pueden apuntar a enteros. [Hablante masculino] Bueno. Bueno, veo que los dos punteros, pero no parecen estar apuntando a nada. [Binky] Eso es correcto. Inicialmente, los punteros no apuntan a nada. Las cosas que apuntan son llamados pointees y configurarlos es un paso separado. [Hablante masculino] Oh, claro, claro. Ya lo sabía. Los pointees están separados. Er, así que ¿cómo asignar un pointee? [Binky] Bueno. Este código asigna un número entero pointee nuevo, y esta parte se presentan x para que apunte a él. [Hablante masculino] Hey, eso se ve mejor. Así que haga algo. >> [Binky] Bueno. Voy a eliminar la referencia al puntero x para almacenar el número 42 en su pointee. Para este truco que voy a necesitar mi varita mágica de la cancelación de referencia. [Hablante masculino] Tu varita mágica de la eliminación de referencias? Eso es genial. [Binky] Esto es lo que el código parece. Voy a establecer el número y la ... [Apareciendo de sonido] [Hablante masculino] Hey mira, ahí va. Así que hacer una desreferencia de x sigue la flecha para acceder a su pointee, en este caso para almacenar 42 en allí. Hey, trata de usarlo para almacenar el número 13 a través del otro puntero, y. [Binky] Bueno. Voy a repasar aquí para obtener yy el número 13 establecido y luego tomar la vara de eliminación de referencias y sólo ... [Zumbido] Whoa! [Hablante masculino] Oh bueno, eso no funcionó. Digamos, Binky, no creo dereferencing y es una buena idea porque la creación de la pointee es un paso separado y no creo que alguna vez lo hizo. [Binky] Hmm, buen punto. [Hablante masculino] Yeah. Nos asignaron el puntero y pero nunca ponerlo para que apunte a un pointee. [Binky] Hmm, muy observador. [Hablante masculino] Hey, te ves muy bien allí, Binky. ¿Puedes arreglarlo para que y apunta a la pointee mismo que x? >> [Binky] Claro. Voy a usar mi varita mágica de la asignación de puntero. [Hablante masculino] ¿Es que va a ser un problema como antes? [Binky] No, esto no toca las pointees. Sólo cambia un puntero para señalar a la misma cosa que otra. [Apareciendo de sonido] [Hablante masculino] Oh, ya veo. Ahora y apunta al mismo lugar que x. Así que esperar. Ahora y es fijo. Tiene un pointee. Así que usted puede probar la varita de eliminación de referencias volver a enviar los más de 13 años. [Binky] Uh, está bien. Aquí va. [Apareciendo de sonido] [Hablante masculino] Hey, mira eso. Ahora eliminación de referencias a obras y. Y debido a que los punteros que están compartiendo un pointee, ambos ven el 13. [Binky] Sí, compartir. Lo que sea. Así que vamos a cambiar de lugar ahora? [Hablante masculino] Oh, mira, estamos fuera de tiempo. >> [Binky] Pero - [Hablante masculino] Sólo recuerda las 3 reglas de puntero. El número 1, la estructura básica es que usted tiene un puntero y apunta a un pointee. Pero el puntero y pointee están separados, y el error común es la creación de un puntero pero se olvide de darle un pointee. Número 2, desreferencia puntero comienza en el puntero y sigue su flecha sobre para acceder a su pointee. Como todos sabemos, esto sólo funciona si hay un pointee, qué tipo de vuelva a la regla número 1. Número 3, asignación de puntero toma un puntero y lo cambia para que apunte a la pointee mismo como otro puntero. Así que después de la cesión, los 2 punteros que apuntan a la pointee mismo. A veces eso se llama compartir. Y eso es todo lo que hay en realidad. Bye-bye ahora. Esto es Binky. Esto es CS50. Nos vemos la semana que viene. [Aplauso] [CS50.TV]