[Powered by Google Translate] [제 5 - 더 편안한] [롭 보덴 - 하버드 대학교 (Harvard University)] [이 CS50입니다. - CS50.TV] 내 이메일에 말씀 드렸듯이, 당신이 사용할 수있는 일들이 많이 있습니다 실제로 문제 세트를 수행 할 수있는 기기가 아닌. 우리는 우리가 더 쉽게 당신을 도울 수해서 사용하면 어플라이언스에서 수행하는 것이 좋습니다 우리는 모든 일 것입니다 방법을 알고. 그러나 말한다면 당신이 일을 할 수있는 곳 중 하나가 예를 들어, 당신은 권한이 없습니다 어플라이언스에하거나 과학 센터 지하에서 일하려면 - 어떤 사실 그들도 어플라이언스가 - 어디서든 작업 할 경우. 하나의 예를 들어 당신은 본적이 / SSH를 들어 본 적이있다? SSH는 뭔가에 연결처럼 기본적으로 있습니다. 사실, 지금 나는 어플라이언스에 SSHed거야. 나는이 어플라이언스에 직접 작동하지 않습니다. 여기 어플라이언스이며, 여기에 보면이 IP 주소를 참조하십시오. 나는 어플라이언스의 자체에서 일할 수 없을; 항상 iTerm2 창 / 터미널 창으로 있습니다. 당신은 IP 주소, SSH jharvard@192.168.129.128에 SSH 할 수 있습니다. 그러한 좋은 패턴이기 때문에 매우 쉽게 번호를 기억 해요. 하지만 그건 제 암호를 물어 것이며, 지금은 어플라이언스에있어. 기본적으로,이 시점에서, 경우는 기기 자체의 내부 터미널을 열어 이 인터페이스는, 그러나 당신이 그것을 사용할 정확히 동일합니다 인터페이스로 전 여기 사용하지만 이제 당신 SSHed하고 있습니다. 당신은 어플라이언스에 SSH 할 필요가 없습니다. 에게 당신은 수 SSH 다른 곳의 한 예는 당신이 기본적으로 가지고 확신입니다 - 오. 큰. 당신의 모든 FAS 서버의 기본 FAS 계정이 있어야합니다. 나에게, 나 SSH는 rbowden@nice.fas.harvard.edu 싶습니까. 당신의 그 처음 물을 거예요, 그리고 네 말한다. 비밀번호 그냥 내 FAS 비밀번호 될 것입니다. 그리고 지금, 나는 좋은 서버에 SSHed, 나는 여기에서 원하는 무엇이든 할 수 있습니다. 당신은 124와 같이 걸릴 수 있습니다 클래스의 많은, 여기에 콘텐츠를 업로드 할 거예요 실제로 문제 세트를 제출합니다. 그러나이 어플라이언스에 액세스 할 수 없습니다 말한다. 그럼 당신은 일을 할 수있다 여기서처럼 말 것 - 이건 그냥 질문에 우리의 섹션입니다. 이 어플라이언스에이 작업을 수행하라는 메시지가 표시됩니다. 대신 난 그냥 서버에서 할 수 있습니다. 난 압축을 풀고거야. 문제는 당신이 gedit 같은 것을 사용하여 사용중인 될 것입니다 어플라이언스의 또는 무엇이든 내부. 당신은 FAS 서버에 해당이되지 않을 꺼예요. 모든 게이 텍스트 인터페이스거야. 그래서, 그들은이 있다는 텍스트 편집기 내용 중 하나 시도 수 있습니다. 그들은 나노가 있습니다. 나노는 일반적으로 사용하기 매우 편리합니다. 귀하의 화살표를 사용하여 정상적으로 입력 할 수 있습니다. 그래서 열심히 아닙니다. 당신이 정말로 멋진 싶은 경우, 이맥스를 사용할 수 있습니다 나는 심지어 이맥스을 닫는 방법을 알고하지 않기 때문에 어느 아마도 열 사람이 아니란 것입니다. 제어 X, 제어 C? 그래. 아니면 내가 사용하는 무엇 VIM을 사용할 수 있습니다. 그리고 그 귀하의 옵션이 있습니다. 네가 그렇게하지 ​​않으면 또한, 당신은 보면 manual.cs50.net .. - 오. PC에서는 SSH는 퍼티를 사용하여 수 당신은 별도로 다운로드해야 할거야된다. Mac에서는, 당신은 단지 기본 사용 터미널 또는 당신은 iTerm2을 다운로드 할 수 있습니다 수 이는 좋은, 멋진 터미널과 같은 것입니다. 당신이 manual.cs50.net로 이동합니다 경우 메모장에 대한 링크를 볼 수 있습니다 + +, 이는 당신이 PC에 사용할 수 있습니다. 이 메모장에서 당신은 SFTP 수 있습니다 + +, 이는 기본적으로 SSH입니다. 이게 당신이하게 될 것은 로컬 파일을 편집합니다 그리고 당신이 그들을 저장할 때마다 그것은 nice.fas에 저장됩니다 당신은 그것들을 실행할 수있는. 그리고 Mac에서 이에 상응하는 TextWrangler 될 것입니다. 그래서 당신이 같은 일을 수행 할 수 있습니다. 지금 당신은 로컬 파일을 편집하고 nice.fas에 저장 할 수 있습니다 당신은 그것들을 실행할 수있는. 당신은 어느 기기없이 붙어있는 경우 그럼,이 옵션을 사용할 수 있습니다 문제 세트를 계속합니다. 한 문제는 CS50 라이브러리가 않을 거라고 될 것입니다 nice.fas은 기본적으로 그렇게하지 ​​않기 때문에. 당신도 CS50 라이브러리를 다운로드 할 수 있습니다 - 나는이 시점에서 그 필요하다고 생각하지 않습니다. 당신도 CS50 라이브러리를 다운로드하여 nice.fas에 이상 복사 할 수 있습니다 아니면 내가이 시점에서 우리는 어차피 더 이상 사용하지 않습니다 생각합니다. 우리가 할 경우 또는 시간으로 대체되고 있습니다 어쨌든 CS50 라이브러리에있는 함수의 구현. 그래서 그런 제한의 정도 안됩니다. 그리고 했어. 지금은 어플라이언스으로 데려 갈 테니, 우리는 어플라이언스에 모든 걸 할게요. 내 이메일에 말처럼, 처음에, 질문 우리의 절을 보면, 우리는 당신이보고하기로 한 짧은 하나에 대해 이야기해야합니다. 우리는 리디렉션 및 파이프 이러한 세 가지 질문이 있습니다. 할 스트림과 같은 기능은 printf 기본적으로 작성해야합니까? 스트림 그럼. 스트림은 무엇입니까? 그냥 어떤 것 스트림은 기본적이다 - 심지어 1 초와 0s의 원천이 아니야. 여기 부탁 스트림은 표준 부족합니다. 그리고 표준 아웃은 스트림 당신이 그것에게 쓸 때 이 화면에 나타납니다. 표준 아웃은 스트림에 의해, 당신이 단지 1 초와 거기에 0s 쓰고 및 표준 밖으로의 다른 쪽 끝을 그냥 스트림에서 읽습니다. 단지 1 초와 0s의 문자열입니다. 당신은 스트림에 쓸하거나 스트림에서 읽을 수 있습니다 스트림이 실제로 무엇인지에 따라 다릅니다. 다른 두 기본 스트림과 표준 오류의 표준입니다. 당신은 GetString 수행 할 때마다의 표준은, 당신에 대한 입력 걸을 기다리고있어. 그래서 당신을 위해 기다리고, 사실에 표준을 기다리고있어 이것은 당신이 키보드에 입력 할 때 이런 기분 정말입니다. 당신이 꼭 표준에 입력하는 표준 오류, 표준 글쓰기 기본적으로 동일합니다 당신이 표준 오류로 인쇄하면하지만, 그 전문입니다 당신은 그것에 오류 메시지를 인쇄해야하는 그래서 당신은 화면에 인쇄 정기적으로 메시지를 구별 할 수 있습니다 그들은 표준 출력이나 표준 오류에 가서 여부에 따라 오류 메시지 대. 너무 파일이 있습니다. 표준 아웃에서 표준 및 표준 오류, 그냥 특별한 스트림 아르 하지만 정말 모든 파일은, 당신은 파일을 열 때, 그것은 바이트의 스트림이된다 어디 그 스트림에서 읽을 수 있습니다. 당신은 대부분의 단지 바이트 스트림으로 파일을 생각할 수 있습니다. 그래서 스트림은 기본적으로로 작성하려면 어떻게해야합니까? 표준 아웃. >와 >> 사이의 차이점은 무엇입니까? 사람이 미리 동영상을 감상나요? 좋아요. >는, 당신이 파일로 리디렉션하는 방법이 될 것입니다 그리고 >> 또한, 파일로 출력을 리디렉션하는 것이다 하지만 대신 파일에 추가 할거야. 예를 들어, 주자 나, 여기 DICT가 생긴다고 그리고 DICT 내부 유일한 물건은 고양이, 고양이, 개, 물고기, 개입니다. 당신은 커맨드 라인에서 가지고 하나의 명령은, 고양이 이는 단지 파일에 어떤 인쇄 할 것이다. 그래서 고양이 DICT 말을 할 때, 고양이, 고양이, 개, 물고기, 개를 인쇄 할거야. 그게 전부 고양이가 수행입니다. 그게 고양이, 고양이, 개, 물고기, 개 밖에 표준 출력을 의미합니다. 내가 대신 파일로 그를 리디렉션 할 수 있다면 사용>와 파일이 뭐든간에으로 리디렉션 할 수 있습니다. 나는 파일을 파일을 호출합니다. 제가 혹시 있다면 이제, 제가 파일을라는 새 파일을 볼 수 있습니다. 내가 열한다면, 그것은 고양이가 커맨드 라인에서 넣어 정확하게 할거야. 다시는 그렇게 됐다면, 다음, 파일에 출력을 리디렉션하는거야 와 같은 정확한 일을하지 않을 수 없네요. 따라서 기술적으로는 완전히 우리가했던 일 overrode. 그리고 DICT을 변경하는 경우 우리가 볼거야, 개를 꺼냈다. 다시 파일에 우리 고양이가 DICT 경우, 우리는 개를 삭제 한 새로운 버전을거야. 그래서 완전히 무시합니다. 우리가 >> 사용하는 경우 대신, 그것은 파일을 추가 할거야. 이제 파일을 여는, 우리는 두 번 인쇄 단지 같은 일을해야 볼 수 그것은 한 번가있어서, 우리는 원래에 추가. 그럼 그 무엇>와 >>는 않습니다. 다음 묻지 않는다 - 이건에 대해 문의하지 않습니다. 우리가하는 다른 하나는 표준 아웃을 리디렉션 <경우>입니다 <표준을 인치로 리디렉션 할 것입니다 우리가 예를 들어이 있으면 봅시다. 한 실제 빠른을 작​​성할 수 있습니다. 의 어떤 파일, hello.c를 보자. 비교적 간단 파일입니다. 난 그저 내가 방금 입력 한 문자열은 이었든 "안녕하세요"를 인쇄 한 다음 문자열을 받고거야. 그럼,여보세요하고 확인. /. 이제 뭔가를 입력하라고 메시지거야 그 말은 인치 표준에 입력 할 일을 기다리고있어 의미 그래서 우리는 단지 롭 안녕하세요, 무슨 말을 인치 나 표준에 원하는 입력! 그럼, 안녕 아웃 표준에 로브를 인쇄거야! 나는. / 인사 한 후 리디렉션 할 경우 지금 당신은 단지 파일에서 리디렉션 할 수 있습니다. 나는 일부 파일, TXT에 넣어, 나는, 롭 넣어면 내 안부 실행 한 다음에 파일을 TXT를 리디렉션하는 경우. / 안녕하세요, 롭, 인사거야! 즉시. 그것은 먼저 GetString 수 없게은에 표준을 기다리고있어 때 의 표준 입력하게 ​​할 데이터의 키보드에서 기다리고 더 이상 사용할 수 없습니다. 대신, 우리는 파일을 TXT를 읽는의 표준 이동합니다. 그리고 이제, 그냥 선 로브 파일 TXT에서 읽을거야 다음은 안녕하세요, 롭를 인쇄 할거야! 그리고 내가하고 싶은 경우, 또 할 수있는. / 안녕하세요 는 2 일> 그 표준 오류를 리디렉션있어. 일이 표준 오류에 갔다면, 그것은 txt2으로 쓰지 않습니다. 하지만 2>를하지 않으면 발견하고 그것은 여전히​​ 롭여보세요를 인쇄거야! 명령 줄 나는 단지 표준 오류 리디렉션하는거야 때문에, 나는 표준을 리디렉션 아니에요. 표준 오류 및 표준 출력이 다릅니다. 당신은 실제로 표준 오류에 기록하고 싶었 경우 그럼 내가 STDERR to fprintf 할이 변경 될 수 있습니다. 따라서 printf 기본적으로 표준 곳으로 출력합니다. 제가 수동으로 표준 오류에 인쇄하려는 경우 그럼 내가 fprintf 이용해야 내가에 인쇄하고자하는 지정합니다. 대신 나는 fprintf STDOUT 짓을한다면, 그 printf에 기본적으로 동등한입니다. 그러나 fprintf 표준 오류합니다. 그래서 지금, 내가 txt2에이 방향을 바꾸는 경우,여보세요, 아버지! 여전히 커맨드 라인에서 인쇄하는데 그것은 표준 오류에 인쇄지고, 난 단지 표준을 리디렉션하는거야 때문입니다. 지금 표준 오류를 리디렉션하는 경우, 지금이 인쇄되지 않은, 그리고 txt2가, 안녕 롭 될 것입니다! 이제, 당신은 표준 오류로 실제 오류를 인쇄 할 수 있습니다 과 표준 출력에 정기적으로 메시지를 인쇄 할 수 있습니다. 그리고 당신이 프로그램을 실행하므로 때 2 인사 이러한 종류로 실행합니다. / 수> 프로그램은 정상적으로 실행 것입니다 수 있도록 하지만 당신을 얻을 오류 메시지가 귀하의 오류 로그에서 나중에 확인하실 수 있습니다 오류 있도록 한 후 나중에 볼 및 오류 파일이 일어난 오류를해야합니다. 질문이 있으십니까? 마지막 하나는 한 명령의 표준을 뽑아내는 등의 방법으로 생각할 수 파이프입니다 하고 다음 명령에서 표준 만들기. 예를 들어 여기에 에코는 명령 줄 것입니다 그 단지는 인자로 넣어 어떤 반향 것입니다. 나는 따옴표를 넣어하지 않습니다. 에코 나불 나불는 어쩌구는, 어쩌구 저쩌구를 인쇄하는 것이다. 전에 말했듯 때 txt 파일로 로브를 넣어했습니다 나는 단지 txt 파일을 리디렉션 대신 할 수 있기 때문에, / 나는 로브를 반향하는 경우 그리고 파이프 그것을에. /여보세요, 또한 일을 같은 유형을 다할 것입니다. 이이 명령의 출력, 에코 롭을하고있다 과에 대한 입력으로 사용합니다. / 안녕하세요. 귀하는 먼저 파일에 에코 롭을 리디렉션 그것을 생각할 수 그리고. / 안녕하세요 해당 파일에 입력 단 출력 거죠. 그러나 그림의 임시 파일을 꺼낸다. 그 질문 있나? 다음 질문이 포함 예정이다. 어떤 파이프 라인은 당신이 names.txt라는 파일에 고유 한 이름의 수를 찾기 위해 사용할 수? 우리가 여기서 사용하고자 할거야 명령은 독특한, 그래서 uniq하고 화장실입니다. 당신은 실제로 그 무엇을 보는 사람이 uniq을 수행 할 수 그리고는 그냥 입력에서 옆에 일치하는 행을 필터링 할거야. 그리고 남자 화장실은 줄 바꿈, 단어, 각 파일에 대한 바이트 수를 인쇄 할 것이다. 그리고 우리가 사용하고자 할거야 마지막 하나는 일종의 이는 단지 txt 파일의 행을 정렬 할 것이다. 좀 txt 파일, names.txt을 만들고 그 로브, 토미, 요셉, 토미, 요셉, RJ, 로브,면 내가 여기서하고 싶은 것은이 파일에서 고유 한 이름의 번호를 찾을 수 있습니다. 그래서 답은 무엇이어야 하는가? >> [학생] 4. >> 그래. 그것은 롭, 토미, 조셉부터 4 여야합니다, RJ이 파일에서 유일한 고유 한 이름입니다. 첫 번째 단계, 난 그냥 names.txt에 단어 수를하면, 이 사실은 나에게 모든 걸 얘기하고 있습니다. 이와 같은 사실은 실제로 인쇄입니다 - 뉴 라인, 단어, 바이트 수 - 남자 화장실, 보자. 나는 단지 라인에 관심 있다면, 난 그냥 WC-난 names.txt을 수행 할 수 있습니다. 그래서 단계 1. names.txt는 모든 이름을 포함되어 있기 때문에하지만, 화장실 - 난 names.txt하고 싶지 않아요 나는 비 고유 사람을 필터링하고 싶습니다. 나는 uniq의 names.txt을 그럼, 만약 꽤 내가 원하는 걸주지 않습니다 중복 이름은 아직 거기 때문입니다. 왜 그럴까요? 왜 uniq 내가 원하는 일을하지 않습니까? [학생] 중복되지 않습니다 [안 들리게] >> 그래. uniq에 대한 man 페이지를 기억 필터 옆에 일치하는 라인을 말한다. 그들은 인접하지 때문에이를 필터링하지 않습니다. 내가 그들을 먼저 정렬하면 정렬 names.txt 함께 모든 중복 행을 넣어 것입니다. 이제 정렬 names.txt이 있다는 것입니다. uniq | I는 uniq에 입력으로 해당을 사용하려는거야. 그게 날 요셉, RJ, 로브, 토미를 제공합니다 그리고, 화장실 - 난에 입력으로 해당을 사용하려면 이는 나에게 4 줄 예정이다. 여기 말처럼, 어떤 파이프 라인을 사용할 수? 당신은 명령 일련의를 사용하여 같은 일을 많이 할 수 당신은 다음 명령의 입력으로 한 명령의 출력을 사용하여 곳. 당신은 많은, 말썽 많은 작업을 수행 할 수 있습니다. 질문이 있으십니까? 좋아요. 파이프 리디렉션은 기록이다. 이제 우리는 실제 물건 코딩 재료로 이동합니다. 이 PDF의 내부, 당신은이 명령이 표시됩니다 그리고 당신은 어플라이언스에서이 명령을 실행하는 것이 좋습니다. wget은 기본적으로, 그냥 인터넷에서 뭔가를위한 명령입니다 그래서 wget이 URL. 귀하의 브라우저에서이 URL에 간 경우, 해당 파일을 다운로드해야합니다. 난 그냥 클릭, 그래서 나 파일을 다운로드. 그러나 터미널의 내부에 그 일을 wget 쓰기 그냥 터미널에 다운로드 할 수 있습니다. 전 section5.zip이 있고 당신은 section5.zip의 압축을 풉니 다하고자합니다 그 때문에 당신에게 section5라는 폴더를 드릴 겁니다 우리가 내부 오늘날 사용하려고하는 모든 파일을 가야된다. 이러한 프로그램 '파일 이름이 제안으로, 그들은 약간의 버그가있어, 그래서 당신의 임무는 gdb를 사용하는 이유를 알아내는 것입니다. 그들을 모두 다운로드 / 그들을 다운로드 얻는 방법을 알고있다니까 자신의 어플라이언스에? 좋아요. ./buggy1 실행, 그것은 세그먼트 오류 (코어 버려진)를 말할 것이다 귀하가 segfault를 언제든지, 그건 나쁜 일이야. 어떤 상황에서는 당신이 segfault하려면 어떻게해야합니까? [학생] 널 포인터를 Dereferencing. >> 그래. 그래서 그 한 예입니다. 당신은 segfault을받을거야 널 포인터를 Dereferencing. 당신은 메모리를 만지고 어떤 수단을 segfault 것은 당신이 만지는해서는 안됩니다. 그래서 널 포인터를 dereferencing하는 것은, 주소 0을 터치합니다 기본적으로 모든 컴퓨터는 요즘 주소 0 당신이 만지고하지 말아야 메모리 있다고합니다. segfault의 NULL 포인터 결과를 dereferencing 그래서 그게. 당신은 포인터를 초기화하지 어떻게하면 다음은 쓰레기 값을 갖는다 그래서 당신이 역 참조하려고 할 때 그것은 모든 가능성에 메모리를 만지시 네요 그 곳의 한복판에 있어요. 당신은 운이와 쓰레기 값을 얻을 발생할 경우 스택 또는 뭔가 어딘가를 가리 키도록 일, 그리고 때 포인터를 초기화하지 않은 당신은 역 참조, 아무 것도 잘못되지 않습니다. 가 가리키는 건지, 어딘가에 스택과 힙 사이 말 아니면 그냥 어딘가, 아직 프로그램에서 사용되지 않은 해당 눈치입니다 그럼 당신은 당신이 만지고하지 말아야 메모리를 만지고 당신은 segfault. 당신은 재귀 함수를 작성하고 너무 여러 번 recurses 때 귀하의 스택은 일에 너무 크고 스택 충돌 증가 당신은 터치하지 말아야은 충돌해서는 안된다는, 당신은 메모리를 만지고, 그래서 당신은 segfault. 그게 무슨 segfault 방식입니다. 또한 같은 이유 당신이 같은 문자열이있을 경우 - 가 이전 프로그램에 다시 가자. 에서 hello.c - - 그냥 다른 뭔가를 만들려고. 숯불 * S = "여러분, 안녕하세요!"; 나는 사용하는 경우 * S = 무언가 또는 S [0] = 'X';주세요 이렇게 인사합니다. / 안녕하세요, 이유는 s​​egfault거야? 왜이 segfault 거죠? 어떻게 될 것으로 예상까요? 제가 printf 한 경우 ( "% s의 \ N", S), 너 뭐 인쇄 할 기대? [학생] X 안녕하세요. >> 그래. 문제는이 같은 문자열을 때 선언이다 S는 스택에 갈거야 포인터 과 s이 (가)을 가리키는 것은 읽기 전용 메모리에 포함되는이 문자열입니다. 단지 이름, 읽기 전용 메모리에 의해 그럼, 당신은 아이디어를 얻을합니다 당신이 읽기 전용 메모리에 어떤 변경하려고하는 경우, 당신은 메모리 짓을하지 말았어야 무언가를하고있는 당신은 segfault. 이와 같은 사실은 실제로 숯불 * s와 숯불 S [] 사이에 큰 차이가 있습니다. 따라서 숯불 님의 [], 이제이 문자열은 스택에 넣어 것입니다, 그리고 스택이 완벽하게 잘 작동합니다 즉, 읽기 전용이 아닙니다. 그리고하지 않습니다. 기억이 나는 숯불 할 때 * s은 (는) = "안녕하세요!"S 자체가 스택에 하지만 님의 다른 곳을 가리키는, 그 다른 곳 읽기 전용으로 발생합니다. 그러나 숯은 S []는 스택에 뭔가입니다. 그래서 그런 segfault가 발생의 또 다른 예입니다. 우리는 ./buggy1는 segfault의 결과 것을 보았다. 이론적으로, 당신은 즉시 buggy1.c 보면 안 되죠. 대신, 우리는 gdb를 통해 살펴 보겠습니다. 당신이 세그먼트 오류 (코어 버려진)을 때 그렇게주의, 여기라는 핵심으로이 파일을. 우리 LS-리터다면, 우리는 그 핵심은 일반적으로 매우 큰 파일입니다 볼 수 있습니다. 이 파일의 바이트 수이므로 250 뭔가를 킬로바이트 것 같은데. 그 이유는 코어 덤프가 실제로 무엇이라는 것입니다 이 때 프로그램 충돌, 프로그램의 메모리 상태 그냥 복사하고이 파일에 붙여 넣기됩니다. 그것은 그 파일에 버려진됩니다. 이 프로그램은, 그것이 실행하는 동안, 250 주변 킬로바이트의 메모리 사용량을 가지고 일 그리고 그렇게이 파일에 버려 졌어요거야. 우리는 gdb의 buggy1 코어를한다면 이제 당신은 그 파일을 볼 수 있습니다. 우리는 gdb에 buggy1을 할 수 있으며, 그, 그냥 정기적으로 gdb를 시작합니다 의 입력 파일로 buggy1을 사용합니다. 당신이 gdb를 buggy1 코어를한다면, 그것을 구체적으로 gdb를 시작하는거야 이 코어 파일을보고 추론하는 것이었다. 그리고 당신이 buggy1 의미 gdb를 말하는 것은 그 핵심 파일이 buggy1 프로그램에서 제공하는 알고 있습니다. 따라서 gdb를 buggy1 핵심은 바로 우리에게 가져다 것입니다 프로그램이 종료하기 일어난 곳이 있습니다. 우리는 프로그램 신호를 11 세그먼트 오류와 함​​께 종료 여기를 참조하십시오. 우리는 아마 매우 도움이되지 않습니다 조립, 한 줄을 볼 수있어. 당신은 BT 또는 역 추적을 입력한다면, 그 기능이 될거에요 그걸 가지고 우리가 현재 스택 프레임의 목록을 제공합니다. 그래서 추적 (backtrace). 우리는 두 스택 프레임을 가지고있는 것 같습니다. 첫 번째는, 우리의 주요 스택 프레임입니다 두 번째는, 우리가 할 일이 바로이 기능을 위해 스택기구입니다 우리가 만 어셈블리 코드가 같은있는 것으로 알고 있습니다. 따라서이 우리의 주요 기능으로 돌아 가자, 우리가 프레임 1을 할 수있는 일, 그리고 우리가 또한 다운 할 수 있다고 생각하기 위해, 위 -하지만 거의 다운 직전하지 않습니다. 그래. 위, 아래로. 최대 당신은 스택 프레임을 당신을 제공합니다 아래 하나의 스택 프레임을 제공합니다. 난 사용하지 않습니다하는 경향이 있습니다. 난 그냥 특별히 1이라는 프레임에 가고 프레임 1을 말한다. 프레임 1은 기본 스택 프레임에 우리를 가지고 것입니다 그리고 바로 여기에 우리가 집에있는 일이 코드 줄을 말한다. 우리가 코드의 몇 가지 행을 원한다면, 우리는 목록을 말할 수 그리고 우리에게 주변 코드의 모든 라인을 제공거야. 우리가에서 오류를 발생시키고 말았다 라인은 6 살 : 경우 (strcmp ( "CS50 바위", argv가 [1]) == 0). 그것은 아직 분명하지 않을 경우, 당신은이 오류를 발생시키고 말았다 이유를 생각하여 여기에서 직선을 얻을 수 있습니다. 하지만 우리는 한 걸음 더 나아가 볼까요 인사, "왜 변수는 argv [1] segfault거야?"할 수 있습니다 가자 인쇄 변수는 argv [1],하고 NULL 포인터 그건 0x0, 것 같습니다. 우리는 segfault거야 그게 그렇게 CS50 바위와 null을 strcmping, 그리고하고 있습니다. 왜이 변수는 argv [1] 널? [학생] 우리가 아무 명령 줄 인수를 제공하지 않았으므로. 그래. 우리는 아무 명령 줄 인수를 제공하지 않았습니다. 따라서 ./buggy1는 변수는 argv [0] ./buggy1 될 수 있습니다 것입니다. 이 변수는 argv가 [1]을 보낸다는 뜻이 아니라, segfault 것 인 것. 대신, 난 그저 CS50 그래요,한다면, 당신은 D를 말할거야 그는 예정된 일을 때문입니다. buggy1.c을 보면, 그것은 인쇄해야하는 "당신은 D를"- 변수는 argv는 [1] "CS50 바위"는 다른, "당신은 D를"하지 않는 경우 "당신이 기회를 놓치지 마세요!" 우리가 원하는면, 우리는 사실로 비교이 필요합니다 그 말은 0으로 비교 것을 의미합니다. 따라서 변수는 argv [1] "CS50 바위"있어야합니다. 당신은 커맨드 라인에서 해당 작업을 수행하려는 경우, 당신은 공간을 이스케이프 \를 사용해야합니다. 따라서 CS50 \ 바위와 당신이 기회를 놓치지 마세요! 당신은 백 슬래시하지 않으면, 왜이 작동하지 않는 이유는 무엇인가요? [학생] 그것은 두 개의 다른 인수입니다. >> 그래. 변수는 argv [1]은 CS50 될 것입니다, 그리고 변수는 argv가 [2] 바위가 될 것입니다. 좋아요. 지금 ./buggy2 다시 segfault 예정이다. 대신 핵심 파일을 열어 때문에, 우리가 직접 buggy2을 열어 gdb를 buggy2 그럼. 우리가 우리의 프로그램을 실행하는 경우 이제 다음은 프로그램 신호 SIGSEGV를받은 말거야 그 말은이 신호를 segfault이며, 어디서 무슨 일이 일어날 그 장소입니다. 우리의 추적 (backtrace)을 보면, 우리는 우리가 함수 oh_no에 있던 것을 볼 어떤은 함수 빙키에 의해 호출 된 함수가 작은에 의해 호출되었습니다 어떤은 주에 의해 호출되었습니다. 우리는 또한 이러한 기능에 대한 인수를 볼 수 있습니다. 작은와 빙키에 대한 인수는 1이었다. 우리가 기능 oh_no을 나열하면, 우리는 oh_no 그냥 숯불 ** S = NULL을 다하고 있습니다 것을 볼; * S = "붐"; 왜 실패까요? [학생] 당신은 역 참조 널 포인터를 수 없습니다? >> 그래. 그 숯불 **에서 일어나는 경우는 관계없이, s이 (가) null입니다 말한 당신이 그것을 해석하는 방법에 따라, 그것은 문자열에 대한 포인터에 대한 포인터 될 수있는 또는 문자열의 배열입니다. 그것은 s이 (가) NULL입니다, 그러니까 * S는 널 포인터를 dereferencing 있습니다 그래서이 충돌 것이다. 이렇게하면 가능한 segfault 수있는 가장 빠른 방법 중 하나입니다. 이건 그냥 NULL 포인터를 선언하고 즉시 segfaulting있어. 그래서 oh_no 무엇을하고 있는지입니다. 우리가 한 프레임을 이동한다면, 우리는 oh_no라는 함수로받을거야. 내가 내려 그렇게해야합니다. 당신이 명령을 입력하고하지 않으면 당신은 다시 Enter 키를 누르 그것은 당신이 실행하는 이전 명령을 반복합니다. 우리는 프레임 1에 있습니다. 이 프레임 목록, 여기서 우리의 기능을 참조하십시오. 다시 목록을 누르거나 목록 20 할 수 있으며 더 나열됩니다. 함수 작은 내가 한 경우 다음 oh_no 함수에 갈 수 있다고 다른 화끈 기능으로 이동합니다. 그리고 우리가 여기 볼 일 당신은 내가 1 알 그 작은은 인수 1 불렀습니다. 아니면 내가를 인쇄합니까 수 있으며 내가 1 말 것입니다. 우리는 작은 현재 있으며, 우리가 다른 프레임을 가면, 우리는 빙키에서 죽은 거예요. 최대. 이제 우리는 빙키에 있어요. 절반이 끼어되기 이전 목록 - -이 기능을 나열 내가 0이면대로 시작한 다음, 우리가 oh_no 전화를하고, 다른 작은 전화하십시오. 우리는 내가 한 줄 때문에 작은했다. 그리고 지금 우리는 주에 왔고, 주요는 INT I = 란드 () % 3이 될 것입니다; 그건 단지 당신에게 하나를 0, 1, 또는 2 인 임의의 숫자를 제공 할 수 있습니다. 그것은 그 번호와 빙키 전화를거야, 그것은 0을 반환합니다. 이걸 보면, 단, 즉시 실행하지 않고 수동으로 프로그램을 통해 도보 당신은 주에서 중단 점을 설정해야되는데,이 우리가 프로그램을 실행할 때 의미 이 브레이크 포인트에 도달 할 때까지 프로그램까지 실행됩니다. 프로그램을 실행 그래서, 그것은 실행됩니다 다음은 주요 기능을 누르고 실행을 중지합니다. 이제 우리는 주 안에하고 있으며, 단계 또는 다음 코드의 다음 줄에 저희를 데려 갈 수 있습니다. 당신은 단계 또는 다음을 수행 할 수 있습니다. 다음 타격, 이제 내가 란드 () % 3, 이제 내가의 가치를 인쇄 할 수 있습니다로 설정되었습니다 그리고 내가 1 말 것입니다. 이제 우리는 다음 또는 단계를 사용하는지 여부에 상관하지 않습니다. 나는 이전에 중요한 것, 그러나 우리는 다음에 사용할 수 있습니다. 우리는 단계를 사용하는 경우, 우리는 함수로 단계, 즉 실제 문제에 모습을 의미합니다 그 빙키의 내부 일어나고 있습니다. 우리가 다음에 사용하는 경우 다음이 기능을 통해 이동을 의미합니다 그리고 우리의 주요 기능에 코드의 다음 줄로 이동합니다. 여기이 줄에, 나는 란드 () % 3 전했다에 있었어요; I 단계 짓을한다면, 그것은 랜드의 구현에 갈거야 그리고 무슨 일이 일어나고 있는지보세요, 나는 RAND 함수를 통해 단계 수 있습니다. 하지만 RAND 함수에 대해 신경 쓰지 않습니다. 난 그냥 메인에 코드의 다음 줄에 가고 싶어, 그래서 다음 사용합니다. 하지만 지금은 빙키 함수에 대한 관리 작업을 수행, 그래서 그걸 한 단계 싶습니다. 지금은 빙키에있어. 코드의 첫 번째 줄은 (i == 0), 전 단계를 받아들이면 말 것입니다, 우리는 작은에 도착을 참조하십시오. 우리 목록 일들이, 우리는이 선택되는 경우 전 = 0입니다. , 난 0 같지 않음 때문에 다른 조건에 갔다 이는 작은을 (I)를 호출 할 수 있습니다. 당신은 혼란스러워 할 수 있습니다. 당신이 방금 직접이 줄을 보면, 당신은 생각할 수는 (i == 0)하는 경우 좋아, 그럼 내가 단계를했고 지금은 작은은 (i)에있어 당신은 내가 = 0 또는 무언가 의미합니다 생각할 수 있습니다. 아니, 그냥이 줄 작은은 (i)에 직접 넣을 수 알고 있다는 것을 의미합니다. 내가가 0이 아니기 때문에, 다음 단계는 다른에 종료하지 않을 수 있습니다. 다른이에서 멈출 거예요 선이 없습니다. 단지 실제로 어떤은 (i) 작은이며, 실행할 수있는 다음 줄에 시작합니다. 작은은 (i)에 스테핑, 우리는 볼 (I == 1)하는 경우. 우리는 우리가 단계 때 우리가 oh_no에 끝날 거라는 거 알아요, 내가 할 = 1 알 겠어 난 = 1은 한 단계 씩 할 수있는 기능 oh_no를 호출하기 때문에 설정하려고하는 문자 ** S = NULL 즉시 "꽝"할 수 있습니다. 그리고 사실, buggy2의 구현을보고 0, 1, 또는 2 - - 전화 빙키,이, 난 그냥 임의의 숫자를지고 제가이 0 인 경우가 oh_no 호출하는 다른 그 작은 호출되는데,이 여기에 있습니다. 제가 전화 oh_no 1이면 다른, 여기에 오는있는 화끈 전화 난 2 경우 oh_no를 호출합니다. 난 방법이 아닌 것 같아 - 사람이 segfault하지 않습니다 프로그램을 만드는 방법을 참조합니까? 내가 뭔가를 누락하지 않는 한 나는이 0 인 경우, 귀하는 즉시 segfault 드리 자면, 그렇지 않으면, 당신이 segfault 한 경우 함수로 이동 다른 당신은 내가 경우 2는 segfault 함수로 이동합니다. 더 당신이 뭘해도 상관 그래서, 당신은 segfault 없습니다. 난 그 대신 숯불 ** S = NULL를하는 것 고치는 방법 중 하나를 추측 그 문자열을위한 공간을 malloc 수 있습니다. sizeof 어떤 - 우리는 malloc (sizeof)을 할 수? [학생] (자) * 5? >>이 바로 보이는가? 나는 실제로 그것을 실행하는 경우이 문제가 해결됩니다 있으리라 믿고있어하지만 내가 원하는 건 그게 아니에요. s의 종류 좀 봐. 가 INT *를 추가 할 수 있도록, 그래서 정수 * X. 나는 (sizeof (int는)) malloc을 것입니다. 아니면 내가 5의 배열을 원한다면, 나는 (sizeof (int는) * 5) 할 것이다; 내가 INT **이 있다면? 내가 뭘 malloc 겠어? 포인터의 [학생] 크기입니다. >> 그래. (sizeof (int는 *)); 여기 그런 것 같아요. 나는 (sizeof (숯불 *)) 원, 이 "꽝"를 가리 포인터를위한 공간을 할당 할 것이다. "꽝"은 그 자체를위한 공간을 할당 할 필요가 없습니다 이게 내가 전에 말했듯이 내용과 기본적으로 동등한 때문에 숯불의 * X = "붐". "붐"이 (가) 이미 존재합니다. 이 메모리의 읽기 전용 지역에 존재하는 발생합니다. s이 (가) 숯불 **이 경우 그것은 이미, 코드이 줄을 즉, 존재 그리고 * s은 (는) 숯불 * 그리고 당신은 "꽝"을 가리 키도록이 숯불 *을 설정하고 있습니다. 나는 S에 "붐"을 복사하려고하면, 난 s에 대한 공간을 할당해야합니다. 제가 해드릴 게요 * S = malloc (sizeof (자) * 5); 왜 5? 왜 네? "붐"4 자입니다 것 같습니다. >> [학생] 널 문자입니다. 그래. 귀하의 문자열의 모든 널 (null) 문자를해야 할 것입니다. 지금은 strcat 같은 뭔가를 할 수 - 문자열을 복사하는 기능은 무엇입니까? [학생] cpy? >> strcpy. 남자 strcpy. 그래서 strcpy 나 strncpy. 지정할 수 있기 때문에 strncpy은 약간 안전 정확히 얼마나 많은 문자 우리가 알고 있기 때문에하지만 여기서 중요하지 않습니다. 그래서 strcpy와 인수를 봅니다. 첫 번째 인수는 우리의 목적지입니다. 두 번째 인자는 우리의 소스입니다. 우리는 대상 *에 복사 할거야하면 포인터가 "붐"S. 왜 전에 대신 우리가 가진 단지 무엇 strcpy와 함께이 작업을 수행 할 수도 있습니다 * s의 = "붐"? 가이 작업을 수행 할 수도 있습니다 이유이지만, 그 이유는 무엇입니까? [학생]는 당신이 "꽝"에서 뭔가를 변경하려면. >> 그래. 지금은 S와 같은 뭔가를 할 수 [0] = 'X'; 님의 포인트는 힙에 힙 그 공간에 s은 (는)를 가리키는 때문 "붐"을 저장하는 힙에 더 많은 공간에 대한 포인터입니다. 따라서 "꽝"이 사본은 힙에 저장되고 있습니다. 프로그램에서 "붐"의 두 사본은 기술적 있습니다. 그냥이 "꽝"은 문자열 상수에 의해 주어있어 첫 번째가 있어요 와 "붐"의 두 번째 복사본은 strcpy는 "붐"의 복사본을 만들었습니다. 그러나 "붐"의 복사본이 힙에 저장하고, 힙은 변경하실되고 있습니다. 힙은 읽기 전용이 아닙니다, 그래서 즉, S [0] 당신이 "꽝"의 값을 변경할 예정이다. 당신이 그 문자를 변경할거야. 질문이 있으십니까? 좋아요. , buggy3으로가 봅시다 gdb를 buggy3을 움직여. 우리는 단지 그것을 실행하고 우리는 segfault를 참조하십시오. 우리 추적 (backtrace) 경우, 두 기능이 있습니다. 우리는 main () 함수에 갈 경우, 우리는 우리가이 라인에서 오류를 발생시키고 말았다 것을 볼 수 있습니다. 그러므로 (에이 라인을보고 INT 라인 = 0; fgets이 물건 같지 않음 NULL을 수행; 라인 + +). 이전 프레임 _IO_fgets 불렀습니다. 당신은 내장 된 C 기능이있는 많은 볼 수 있습니다 당신이 segfault를받을 때, 정말 알 수없는 함수 이름이있을 것 이 _IO_fgets처럼. 그러나이 fgets 전화에 관한거야. 여기 어딘가 내부의, 우리는 segfaulting 있습니다. 우리는 fgets에 인수 보면, 우리는 버퍼를 인쇄 할 수 있습니다. 의 인쇄하자로 - 오, 이런. 인쇄 정확히 내가 원하는대로 작동하지 않을 수 있습니다. 가 실제 프로그램 살펴 보도록하겠습니다. 버퍼는 문자 배열입니다. 그것은 128 자 문자 배열입니다. 그래서 인쇄 버퍼라고 할 때, 그 128 문자를 인쇄 할거야 어떤 제 생각 엔이 예상됩니다. 내가 찾고 있었던 것은, 버퍼의 주소를 인쇄합니다 하지만 저 한테 정말 많은 얘기하지 않습니다. 그래서 여기에 X 버퍼 말하고 일어날 때, 그것은 나에게 0xbffff090를 보여줍니다 당신이 이전 또는 어떤 시점에서 기억하면 Oxbffff는 스택 틱 지역이 될 경향이있는. 스택은 0xc000 아래 어딘가에서 시작하는 경향이있다. 바로이 주소를 확인하여, 나는 버퍼가 스택에 것을 알고있다. 버퍼, 최대, 실행, 내 프로그램을 다시 시작 우리였다 문자의 순서를보고 그 방법이 정말 의미가 있습니다. 그런 다음 파일을 인쇄 어떤 파일처럼 보여? [학생] 널. >> 그래. , 파일 유형은 파일 *의이므로 포인터 그 포인터의 값은 null입니다. 그래서 fgets는 간접적 인 방법으로 그 포인터에서 읽을하려 할거야 하지만 포인터를 사용하기 위해서는, 그것은 역 참조를해야 돼. 아니면, 그것이 dereferences를,로 연결해야하는지에 액세스하기 위해 인치 그럼 NULL 포인터와 segfaults을 dereferencing있어. 내가 거기를 다시 시작 수 있습니다. 우리는 주요 지점에서 해제하고 실행하면은, 코드의 첫 번째 줄은 숯불 * 파일 이름 = "nonexistent.txt"이다; 그래서이 프로그램이 실패 이유에 꽤 큰 힌트를 제공해야합니다. 내가이 파일을 열 수있는 곳 옆에 입력하면, 다음 줄에 날을 제공 그리고 나서 바로 한번 다음엔 어디를 공격의 선에 들어가, 그것은 segfault거야. 사람이 우리가 segfaulting 될 수있는 이유를 던져할까요? [학생] 파일이 존재하지 않습니다. >> 그래. 이것은 힌트 있어야합니다 당신이 파일을 열하는 때마다이 파일이 실제로 존재하는지 확인해야. 그래서 여기, "nonexistent.txt"; 우리 읽기를위한 fopen 파일 이름, 우리는 말을해야 할 경우 경우 (파일 == NULL)와 printf ( "파일이 존재하지 않습니다!"라고 또는 - 아직 더 - 파일 이름); 반환 1; 이제 우리는 NULL 있는지 확인 전에 실제로 계속하고 해당 파일에서 읽는. 우리는 그 작품 그를 볼 수를 리메이크 할 수 있습니다. 나는 새 줄을 포함하기위한. 이제 nonexistent.txt가 존재하지 않습니다. 당신은 항상 이런 건에 대해 확인해야합니다. 당신은 항상 fopen은 NULL을 반환하는지 확인해야합니다. 당신은 항상 malloc이 NULL을 반환하지 않습니다 있는지 확인해야합니다 또는 다른 당신은 segfault. 지금 buggy4.c. 실행. 나는 입력 또는 가능성이 무한 반복을 기다리고 있습니다이 추측거야. 네, 무한 반복입니다. buggy4 그럼. 우리가 무한 반복중인 것 같습니다. 우리는 메인에 날릴 수 있지만, 프로그램을 실행합니다. gdb의에서, 만약 사용하는 약어가 모호하므로 또는 당신을 위해 제공하는 특별 약어, 다음 대신 다음에 모든 방법을 입력 할 필요의 옆에를 사용하는 n을 사용할 수 있습니다. 그리고 지금은 한 번 누르 N 한, 난 그냥 옆에 계속 입력을 칠 수 대신 누르 N 입력 N 입력 N 입력해야하는. 나는 [I]을 0으로 배열을 설정있어 루프에 대한 어떤 종류의에 있어요 것 같습니다. 내가 루프에 빠져 위반 절대 나처럼 보입니다. 난 내가를 인쇄, 그래서이 있다면, 다음 갈거야. 다음은 제가 갈 게요 그럼 난 3, 내가를 인쇄합니다. 난 내가를 인쇄합니다 그리고 난은 3입니다. 다음으로, 인쇄, 전 4입니다. 사실, 인쇄 sizeof (배열), 그래서 배열의 크기는 20입니다. 일부 특수 gdb의 명령은 무슨 일이 때까지 계속 거기에있는 것 그러나 같습니다. 이 변수의 값에 조건을 설정 같아요. 하지만 그게 뭔지 기억이 안나요. - 우리는 계속한다면 무슨 말을 했지? 무슨 얘기 했어? [학생] 표시 제가 추가합니까 - >> 예. 그래서 도움이 표시됩니다. 우리가 단지를 표시하면, 내가의 가치는 얼마입니까 여기에 넣어합니다 그래서 매번 그것을 인쇄 할 필요가 없습니다. 우리가 다음에 계속하면, 우리는 0, 1, 2, 3, 4, 5, 0, 1, 2, 3, 4, 5, 0, 1, 2, 3, 4, 5를 참조하십시오. 뭔가 심각하게 잘못된 것이다, 나는 0으로 재설정되고 있습니다. buggy4.c을 보면, 우리는 그런 일이 일어날 모든 정수 배열 [5]입니다 참조; (; 나는 <= sizeof (배열); 전 + + I = 0)에 대한 배열 [i] = 0; 우리가 그렇게 여기 뭐가 잘못 표시되는 이유는 무엇입니까? 힌트으로, gdb에 buggy4을 할 때 - 메인, 실행을 깰의 보자 - 나는 인쇄 sizeof (배열) 내가 드디어 탈출 위치를 상태가 무엇인지 볼 않았습니다. 여기가 어디야? 내가 도망나요? 아직 선언되지 않았습니다. 그래서, sizeof를 (배열) 인쇄하고는 20입니다 어떤은 내 배열의 크기 (5)의이기 때문에 기대하고 5 정수되는 것은 그래서 전체 것은 sizeof (INT)가 4 살이 경향이 5 * sizeof (int는) 바이트 있어야합니다. 그래서 sizeof (배열) 20입니다. 이것은 무엇을해야합니까? [학생] sizeof (int는)으로 나눈 값입니다. >> 네, / sizeof (int는). 문제가 아직 여기가있는 것 같습니다. 이 단지해야한다고 생각 < 가 거의 항상부터 <결코 <=. 지금의이가 부러 이유 생각해 보죠. 사람이 왜 루프의 각 반복을 통해 0으로 추측 재설정이 있습니까? 여기서 무슨 일이 있었 그 안에있는 유일한 방법은 [I]는 0으로 설정되고 그 배열입니다. 그래서 어떻게 든,이 코드 줄은 난을 0으로 설정 될 수 있도록 INT를 일으키는 것입니다. 이제 내가이 부분의 기억을 재정의하기 때문에 [학생] 혹시 그것이 배열의 다음 요소 야? 생각하면 >> [보덴] 예. 우리는 배열의 끝을 넘어 때, 우리가 재정의하고 있는지 어떻게 든 그 공간은 내가의 가치를 재정의하고 있습니다. 우리가 buggy4을 보면 그리고, 메인, 실행을 깰 의는 내가의 주소를 인쇄 보자. 이 bffff124 것 같은데. 이번에는 배열의 주소를 인쇄하게 [0​​]. 110. 무엇 [1]은 어때? 114. [2], 118. 11c, 120. 배열 [5] bfff124입니다. 배열 그래서 [5] 난, 그 배열 [5] 나는 것을 의미와 같은 주소가 있습니다. 이 동일한 주소를 가지고있는 경우, 그들은 같은 일입니다. 그래서 우리는 배열 [5]로 설정하면 0으로, 우리는 0으로 i를 설정합니다. 그리고 당신은 스택의 관점에서 생각해 경우, INT 난 내가 스택에 공간이 도착 즉, 먼저 선언되어 있습니다. 그런 다음 배열 [5] 그래서 20 바이트가 스택에 할당되며, 할당됩니다. 그래서 그 다음이 20 바이트가 할당받을 우선 할당됩니다. 그래서, 바로 배열하기 전에 발생 때문에 방법처럼 나는 기술적으로 스택이 아래로 증가 곳, 지난 주 말 배열로 할 때 인덱스, 우리는 보장됩니다 배열의 0번째 위치 항상 배열의 첫 번째 위치하기 전에 발생합니다. 이건 내가 지난 주에 그것을 그렸다 방법 종류입니다. 아래에 우리가 주소 0을 가지고 있고 상단에 우리가 주소 최대가납니다. 스택은 항상 아래로 성장하고있다. 자, 우리는 i를 할당 말한다. 우리는 정수 할당 전, 가자 그냥 여기서 정수 제가 할당됩니다 말하고 의미합니다. 그리고 우리는 그 아래에 그 의미 5 정수의 배열을, 할당 스택이 아래로 성장해 가고 있기 때문에, 그 다섯 정수가 할당받을. 그러나 배열을 사용하는 방법에 때문에, 우리는 보장하고 그 배열의 첫 번째 위치 항상 배열의 두 번째 이하 주소가 있습니다. 따라서 배열 위치 0 항상 메모리에 첫번째 일이 있습니다 배열의 위치 1 그 후에 발생하는 반면, 및 배열 위치 2, 그 이후 발생하는 이는 그 배열 위치 0, 거기에 어디 선가 무슨 일이 일어날 것을 의미 배열 위치 1은 위에서 무슨 일이 일어날 까지 옮기는 ​​것이 최대 주소가 여기에 있기 때문에 높은 주소를 의미합니다. 때문에 여기로 배열 [0] 지금, 배열 [1] 여기까지, 배열 [2] 여기까지, 배열 [3] 여기 요. 우리가이 모든 방법은, 정수를 할당하는 방법 전에 해당 내용을 미리 공지 우리는 배열에 추가 및 추가 이동, 우리는 점점 더 가까이 우리 정수 전을 받고 있습니다. 그건 아주, 그 우리의 배열보다 한 위치에 있으며, 그 배열 할 [5] 일 정확히 내가 할당 할 수 있었던 곳 정수입니다. 그럼 우리가 스택에 공간을 때리는 할 일이 핵심 이죠, 그는 정수 전에 할당되었고, 우리는 0으로 설정하고 있습니다. 그거 작동 방법은 다음과 같습니다. 질문이 있으십니까? 그래. [학생] 신경 쓰지 마. 좋아요. [학생] 어떻게 이러한 오류 종류를 방지합니까? 이러한 오류인가? 프로그래밍 언어로 C를 사용하지 마십시오. 확인 배열 경계가있는 언어를 사용합니다. 그 동안 조심스럽게 한, 당신은 당신의 배열의 범위를 넘어 가지 않기 위해 필요합니다. [학생] 그래서 여기에 우리가 배열의 범위를 넘어 갔을 때 - [보덴] 일이 잘못 갈 시작할 곳입니다. >> [학생] 아, 그래요. 그 동안 귀하의 배열에 할당 된 메모리 내에 있어야 한, 당신은 괜찮아요. 그러나 C는 오류 검사를 수행하지 않습니다. 제가 배열을 할 경우 [1000]은 기꺼이 단지 무슨 일이 생기면 수정됩니다 - 그것은 배열의 시작 부분에 갔다가 그 후 1000 위치를 간다하고 0으로 설정합니다. 그것은 오,이 실제로 1000 일이없는 한 검사를하지 않습니다. 1000, 방법 나는 변화해야하는지 넘어 자바 아님 당신이 범위를 인덱스의 배열을 나갈거야 반면, 또는 범위 예외의 색인 아웃. 높은 수준의 언어로 많은 일이 좀있어서 이유 당신이 배열의 범위를 넘어 가면 어디에서, 당신은 실패 당신은 수렁에서 일을 변경할 수 없습니다 있도록 그리고 이제 막 예외를 점점 것보다 훨씬 더 이동 당신은 배열의 끝 넘어 갔다고 말하는. [학생] 그리고 우리가 변경해야 <= 바로 > [보덴] 그래. 그것은 > [학생] 맞아. 더 질문? 좋아요. [학생] 질문이 있습니다. >> 그래. [학생] 실제 배열 변수는 무엇입니까? [보덴]처럼 배열 무엇입니까? 배열 자체는 상징입니다. 그것은 우리가 참조하고있는 20 바이트의 시작의 주소입니다. 당신은 포인터로 생각할 수 있지만 상수 포인터입니다. 가능한 한 빨리 일이 컴파일대로, 변수 배열은 더 이상 존재하지 않습니다. [학생] 그럼 어떻게 그 배열의 크기를 찾을 수 있습니까? 배열의 크기는 기호로 연결되는 것이 그 블록의 크기를 의미합니다. 나는 printf와 같은 무언가를 ( "% P \ N", 배열) 할 때, 한번 해보도록하지. 난 그냥 뭘 잘못 했어? 배열 '배열'여기를 선언했다. 아, 여기 요. 꽝은 똑똑하고, 내가 5 요소로 배열을 선언 알고들 어떻게 하지만 위치를 1000으로 색인을 생성 할거야. 이 단지 상수이기 때문에 그런게을 수행 할 수 있습니다. 이건 내가 배열의 범위를 넘어 갈이 없었죠에 지금까지 이동할 수 있습니다. 그러나, 우리는 내가 잘못했을 때 이전에 발견 그것은 아마도, 내가에 걸릴 수 있습니다 얼마나 많은 값을 확인할 수 없습니다 그래서 내가 배열의 끝 넘어가는 것으로 판단 할 수 없습니다. 그건 그냥 똑똑해 꽝입니다. 그러나 지금 buggy4을합니다. 그래서 잘못 다른 뭘하고있는 거지? 암시 적으로 라이브러리 함수가 'printf'선언. 나는 # 를 포함 할거야. 좋아요. 지금 buggy4를 실행 해보십시오. 같은 배열의 값을 인쇄 나는 포인터로 인쇄 솜씨가 과 같은 인쇄 뭔가 - bfb8805c - 일부 주소입니다 그 스택 틱 지역에 있어요. , 배열 자체는 포인터처럼이지만, 실제 포인터가 아닙니다 일반 포인터부터 우리는 변경할 수 있습니다. 배열은 그냥 상수입니다. 메모리의 20 블록 주소 0xbfb8805c부터 시작합니다. 이 주소를 통해 등록 bfb8805c +20- 또는 전 -20 생각에 - 이 배열에 할당 된 메모리의 전부입니다. 배열, 변수 자체는 저장되지 않습니다. 당신은 컴파일하고 컴파일러 - 그것을 손으로 파 - 이 배열로 알고하지만 어디 컴파일러는 사용합니다. 그 배열이 시작하는 위치는 알 그래서 항상 그 처음부터 오프셋의 관점에서 일을 할 수있다. 이 배열을 대표 할 수있는 변수 자체가 필요하지 않습니다. 하지만 INT * P = 배열​​과 같은 일을 할 때, 지금 P, 그 배열을 가리 키 포인터 지금 P는 실제로 스택에 존재 않습니다. 내가 P를 변경할 수입니다. 내가 P = malloc을 수행 할 수 있습니다. 그래서 원래 배열로 지적, 지금은 힙에서 여유 공간을 가리 킵니다. 나는 배열 =의 malloc을 수행 할 수 없습니다. 꽝이 똑똑하면 바로 박쥐에서 좀 지르지합니다. 사실, gcc가 너무 이런 짓을 했을까 확신합니다. 따라서 배열 유형 'int는 [5]의'양도하지 않습니다. 당신은 배열 유형에 무언가를 할당 할 수 없습니다 배열은 상수이기 때문이다. 그것은 어떤 참조 그 20 바이트 상징입니다. 난 변경할 수 없습니다. [학생] 그리고 배열의 크기가 어디에 저장됩니까? [보덴] 이것은 저장되지있어. 이 컴파일있어 때입니다. 따라서 배열의 크기는 어디에 저장됩니까? 귀하는 배열 자체를 선언하는 함수의 내부 sizeof를 (배열)를 사용할 수 있습니다. 좀 기능, 푸, 어떻게 내가 할면 (INT 배열 []) printf ( "% d 개 \ N", sizeof (배열)); 그리고 여기 제가 푸 (배열)를 호출; 이 기능의 내부 - 한번 실행합니다. 다시는 똑똑해 꽝입니다. 이 말은 그게 배열 함수 매개 변수에 sizeof 'int는 *'의 크기를 반환합니다. 이제 내가 일을하고 싶 아니라면이 오류가 될 것입니다. 의 실제 Werror을 해제 보자. 경고. 경고 잘 수 있습니다. 이 경고가로 아직도 오래 컴파일합니다. . / a.out의 4를 인쇄 할 것이다. 생성 된 경고는 무엇이 잘못되었는지에 대한 명확한 지표입니다. 이 정수 배열은 sizeof을 (INT *) 인쇄 할 것이다. 내가 여기에 배열 [5] 넣어하더라도, 여전히 단지 sizeof을 (INT *) 인쇄 할거야. 따라서 가능한 한 빨리 당신이 함수에 합격으로 배열과 포인터의 차이 존재하지 않는 것입니다. 이것은 스택에 선언 된 배열 할 일 하지만, 우리는 곧 그 가치를 전달로 그 0xbf, 어쩌구이 기능에 어쩌고 다음이 포인터가 스택에 그 배열을 가리 킵니다. sizeof는 배열이 선언 된 함수에서 적용되는 것을 의미하므로, 그 말은 당신이 기능을 컴파일 할 때 꽝이 기능을 통해가는 때, 배열의 크기는 5 정수 배열입니다보고있다. 그래서는 sizeof를 (배열)보고있다. 음, 20입니다. 그래서 sizeof는 기본적으로 거의 모든 경우에 작동 방법을 실제로입니다. Sizeof는 함수가 아니라 연산자입니다. 당신은 sizeof 함수를 호출하지 않습니다. Sizeof (INT)는 컴파일러는 그 4 변환합니다. 알았어? 좋아요. [학생] 지금 메인 및 foo는에서 sizeof (배열)의 차이점은 무엇입니까? 우리가 유형 INT의 *입니다 sizeof를 (배열), 말 때문입니다 배열 여기하지 않습니다 타입 int는 *의 반면, 그것은 정수 배열입니다. [학생] 그래서 당신은 배열 [] 대신 INT * 배열에서 매개 변수가 있다면, 그 지금은 포인터이기 때문에 아직도 배열을 변경할 수 있다는 의미? [보덴] 이렇게요? >> [학생] 그래. 이제 함수에서 배열을 변경할 수 있습니까? [보덴] 당신은 두 경우 모두에 배열을 변경할 수 있습니다. 이러한 경우 모두에서 당신은 배열 [4] = 0 말을 무료로 이용하실 수 있습니다. [학생]하지만 당신은 다른 뭔가를 배열 지점을 만들 수 있습니까? [보덴] 오. 그래. 두 경우 모두 - >> [학생] 그래. [보덴] 배열 []와 int는 * 배열 사이의 구분은 아무 것도 없습니다. 당신은 또한 여기에 몇 가지 다차원 배열을 얻을 수 있습니다 일부 편리한 구문에 대해,하지만 단지 포인터입니다. 이건 내가 배열을 할 자유임을 의미 = malloc (sizeof (int는)), 그리고 지금 다른 곳에서 지적한다. 그러나 단지이 영원히 항상 작동 방식 좋아 을하여이 배열을 변경하면 다른 뭔가를 가리 킵니다 가, 인수의 복사본이기 때문에 여기에이 배​​열을 변경하지 않습니다 그렇게 인수에 대한 포인터 없습니다. 그리고 사실, 그냥 똑같은 걸 더 표시 등 - 우리는 이미 인쇄 배열 프린트 무엇을 봤어 - 우리는 배열의 주소 또는 배열의 주소의 주소를 인쇄하는 경우 그 중 하나에? 의이 하나를 무시 보자. 좋아요. 이 유효합니다. 지금은. / a.out을 실행있어. 인쇄 배열 한 다음 배열의 주소를 인쇄 같은 것이다. 배열은 존재하지 않습니다. 당신이 배열을 인쇄 할 때, 당신은 그 20 바이트를 의미있는 기호를 인쇄하는 알고 있습니다. 배열의 주소를 인쇄, 잘, 배열이 존재하지 않습니다. 이 주소를 가지고 있지 않습니다, 그래서 그냥 그 20 바이트의 주소를 인쇄합니다. 최대한 빨리 아래로 컴파일으로, 당신의 컴파일 buggy4처럼. / a.out 배열 존재입니다. 포인터는 존재합니다. 배열은하지 않습니다. 배열을 대표하는 메모리의 블록은 여전히​​ 존재 하지만 변수 배열과 해당 유형의 변수가 존재하지 않습니다. 사람들은 배열과 포인터 사이의 주요 차이점과 같다 최대한 빨리 함수 호출을 따라서, 어떤 차이가 없습니다. 그러나 내부 배열 자체가 선언되어있는 함수의, sizeof는 다르게 작동 대신 타입의 크기의 블록의 크기를 인쇄하고 있기 때문에, 그 상징이기 때문에 당신은 그것을 변경할 수 없습니다. 일 것과 주소를 인쇄하면 같은 일을 인쇄합니다. 그리고 그 방법은 아주 많아요. [학생] 당신은 한 번 더 말을 할 수있어? 내가 뭔가를 놓친했을 수 있습니다. 배열의 인쇄 배열과 주소가 같은 일을 인쇄 당신은 포인터의 주소 대 포인터를 인쇄하는 경우 반면에, 하나는 가리키는하고있는 일의 주소를 인쇄, 다른 하나는 스택에있는 포인터의 주소를 인쇄합니다. 당신은 포인터를 변경할 수 있습니다, 당신은 배열 기호를 변경할 수 없습니다. 그리고 sizeof 포인터는 포인터 타입의 크기를 인쇄 할 것이다. 따라서 정수 * P sizeof (P)는 4를 인쇄 할 것입니다 하지만 INT 배열 [5] 인쇄 sizeof (배열) 20을 인쇄 할 것이다. [학생] 지금 INT 배열 [5] 20 인쇄됩니까? >> 예. 왜 내 buggy4의 IT sizeof (배열)로 사용 때입니다 이 내가 할 <20 일을 저지르고, 그게 바로 우리가 원하던 게 아니 잖아. 우리는 내가 <5 싶습니다. >> [학생] 좋아요. [보덴] 그리고 최대한 빨리 기능을 전달하기 시작, 우리가 그랬다면 INT * P = 어레이; 이 기능의 내부에, 우리는 기본적으로 동일 방법으로 P와 배열을 사용할 수 있습니다 sizeof 문제와 변화 문제에 대한 제외. 그러나 P는 [0] = 1; 배열 [0] = 1 말과 같은이다; 그리고 곧 우리가 foo는 (배열) 말대로, 또는 foo는 (P)을, foo는 기능의 내부에,이 두 번 같은 전화입니다. 이 두 통화 사이에 차이가 없습니다. 그에서 좋은 사람들? 좋아요. 우리는 10 분 있습니다. 우리는이 해커 Typer 프로그램을 통해 알아 보도록하겠습니다 작년이나 뭐 나온이 웹 사이트. 당신이 무작위로 입력하고 출력처럼 막 재밌을 거에요 - 간에 파일이로드에서 일어나는하면 입력하는 것처럼 생겼다. 그것은 운영 체제 코드의 어떤 것 같습니다. 우리가 구현하려는거야. 당신은 hacker_typer라는 이름의 바이너리 실행 파일이 있어야합니다 그에게 파일을 하나의 인수에 소요 "해커 입력하십시오." 실행 파일을 실행하면 화면을 삭제해야합니다 그리고 사용자가 누를 키를 때마다 전달 된 파일에서 한 문자를 인쇄 할 수 있습니다. 이 키를 눌러 어떤 키를 그래서, 그것은 버려야 대신 파일에서 문자를 인쇄해야합니다 그 인자입니다. 난 아주 우리가 알아야 할 거에요 일이 무엇인지 말해주지. 그러나 우리는 termios 라이브러리를 체크 아웃하고 싶습니다. 내 평생에이 라이브러리를 사용하지 않은, 그래서 아주 최소한의 목적이 있습니다. 그러나 우리는 너희가 턴 문자를 멀리 던져하는 데 사용할 수있는 라이브러리가 될 것입니다 당신은 인치 표준에 입력하는 경우 따라서 hacker_typer.c, 우리는 # 를 포함 할거야. termios의 man 페이지를보고 - 난 그게 단말기 OS라도 추측 - 내가 읽는 방법을 모르겠어요. 이를 살펴보면, 이러한 2 파일을 포함 말합니다, 그래서 우리는 그렇게 할 수 있습니다. 우선 먼저, 우리는 우리가 열립니다 파일입니다 하나의 인수에 받고 있습니다. 그래서 어떻게할까요? 어떻게 내가 단일 인자를 확인합니까? [학생] argc가 동일합니다. >> [보덴] 그래. 그래서, 만약 (argc = 2!) printf ( "사용법 : % s의 [파일 열려면]"). 내가 두 번째 인수를 제공하지 않고 실행하는 경우 이제 - 오, 내가 새 줄이 필요합니다 - 당신이 말하는 사용이 표시됩니다. / hacker_typer, 그리고 두 번째 인자는 I 열려는 파일이어야합니다. 지금은 어떻게해야 하죠? 이 파일에서 읽을 수 있습니다. 어떻게 파일에서 읽습니까? [학생] 먼저 엽니 다. >> 그래. 그래서 fopen. fopen은 어떻게 생겼어요? [학생] 파일 이름. >> [보덴] 파일 이름 변수는 argv는 [1]가 될 것입니다. [학생] 그리고 당신이 그것으로 뭘하려는, 그래서 - >> [보덴] 그래. 기억하지 않은 경우 그럼, 사람 fopen을 할 단지 수 이 경로는 파일 이름입니다 const 숯불 * 경로 될거야 곳 const 숯불 * 모드. 이 모드가 무엇인지 기억하지 발생할 경우에는 모드에 볼 수 있습니다. 맨 페이지의 내부, 슬래시 문자는 당신이 일을 검색하는 데 사용할 수 있습니다. 그래서 모드를 검색 할 수 / 모드를 입력합니다. N과 N은 검색 검색을 통해주기에 사용할 수 있습니다. 여기가 문자열로 인자 모드 점을 말한다 다음 시퀀스 중 하나가 시작. 읽기에 대한 R 자, 열기 텍스트 파일입니다. 우리가하고 싶은거야. 읽기, 난 저장할하십시오. 문제는 파일 *가 될 것입니다. 지금은 뭘하고 싶어요? 잠시만 요. 좋아요. 지금은 뭘하고 싶어요? [학생]가 NULL이라면 확인합니다. >> [보덴] 그래. 당신은 파일을 열 때마다, 당신이 성공적으로 열어 할 수 있는지 확인하십시오. 처음 현재 설정을 읽을 수있는 지금은 그 termios 일을하고 싶어 무언가에 그 내용을 저장 한 후 내 설정을 변경하려면 내가 입력하는 모든 문자를 버릴 그리고 난 그 설정을 업데이트하고 싶습니다. 그리고 프로그램의 끝 부분에, 내 원래 설정으로 다시 변경하고 싶습니다. 따라서 구조체 유형은 termios이 될 것입니다, 나는 그 중 두 가지를하려는거야. 첫 번째는 내 current_settings 될 것입니다 그리고 그들은 내 hacker_settings 될거야. 첫째, 내 현재 설정을 저장하려면 겠어 그럼 내가, hacker_settings를 업데이트하려는거야 그리고 내 프로그램의 끝에서 저쪽 현재 설정으로 되돌리려하고 싶습니다. 그럼, 우리 사람 termios를 작동하는 방법은 현재 설정을 저장할 수 있습니다. 우리는 우리가이 INT tcsetattr, INT tcgetattr하신 것으로 알고 있습니다. 나는 그것의 포인터로 termios 구조체를 전달합니다. 이 표시됩니다 방법입니다 - 키이스, 이미 함수가 호출 된 것을 잊어. 복사하고 붙여 넣습니다. tcgetattr 그래서, 그럼 내가의 정보를 저장한다는 구조체에 전달하려는 이는, current_settings이 될 것입니다 그리고 첫 번째 인수는 내가의 특성을 저장하고자하는 것은에 대한 파일 설명입니다. 어떤 파일 설명이되어 당신이 파일을 열 언제든지처럼, 그것은 파일 설명자를 얻을 수 있습니다. 언제 fopen 변수는 argv [1], 당신이 참조하는 파일 설명자를 도착 당신이을 읽거나 기록 할 때마다. 그래서 제가 여기 사용하려는 파일 설명 없습니다. 당신은 기본적으로 세 건 파일 설명이 있습니다 이는에 표준 아웃 및 표준 오류 표준입니다. 기본적으로, 나는 0, 표준 출력은 1이고, 표준 오차은 2입니다의 표준 것 같아요. 그래서 나는의 설정을 변경하려면 어떻게해야합니까? 내가 문자를 누르 때마다의 설정을 변경하려면 나는 대신 화면에 출력을 멀리 그 문자를 던져하고 싶습니다. 무엇 스트림 - - 표준 아웃, 또는 표준 오류의 표준 나는 키보드에 입력 할 때 일에 응답? >> >> 예 인치 [학생] 표준. 그러니 난 영을 할 수 아니면 표준 입력을 수행 할 수 있습니다. 나는 인치 표준의 current_settings를 받고 지금은 그 설정을 업데이트하려면 그래서 일단 내 current_settings가 무엇 hacker_settings에 복사됩니다. 그리고 structs 작업이 얼마나 그냥 복사됩니다. 당신이 기대하는대로이 모든 분야 복사합니다. 지금은 필드의 일부를 업데이트하고 싶습니다. termios을 보면,이 많은을 읽어해야 당신이 찾도록 할 것입니다 볼하려면, 하지만 당신이보고 싶지 나갈 수있는 플래그는, 에코 아르 그래서 에코 입력 문자가 포착 됐습니다. 우선 설정하려면 - 필드가 무엇인지 이미 잊어 했어요. 이 구조체의 모양입니다. 입력 모드 그래서 나는 우리가 변경하고자하는 생각합니다. 우리가 그렇게 우리가 바꾸고 싶습니다 있는지 확인하기 위해 솔루션을 살펴 보겠습니다. 우리 모두를 볼 필요 방지하기 위해 lflag를 변경하고 싶습니다. 우리는 지역의 모드를 변경하고 싶습니다. 당신은 최선을 다가 있어야 할 곳 이해이 모든 게 읽어해야 우리가 변경하고자하는. 그러나 우리가 그를 변경하려면 거예요 현지 모드의 내부입니다. 따라서 hacker_settings.cc_lmode은이란이다. c_lflag. 우리는 비트 연산자로 얻을 곳입니다. 우린 시간이 좀 만, 우리는 진정한 빠르게 통과합니다. 우리가 비트 연산자에 들어가 곳입니다 내 생각은 어디 한 번 오래 전에 말한 당신이 플래그를 처리 시작할 때마다, 당신은 비트 연산자를 많이 사용거야. 플래그의 각 비트는 행동을 일종의에 해당합니다. 그래서 여기,이 플래그는 모두 다른 일을 의미 여러 가지의 무리가 있습니다. 하지만 내가보고 싶은 것만 메아리에 해당하는 비트를 해제합니다. 그럼 방향으로 회전 내가 어떻게에서 & = ¬ 에코. 사실,이 수첩 같은 거 같아요. 난 그냥 다시 확인해거야. 난 termios 할 수 있습니다. 단지 에코있어. 에코는 단일 비트가 될 것입니다. ¬ 에코는 모든 플래그가 true로 설정되어 즉, 모든 비트가 1로 설정되어 의미 것입니다 에코 비트를 제외하고. 이걸 내 로컬 플래그를 종료함으로써, 현재 true로 설정되어있는 모든 플래그를 의미 여전히 true로 설정됩니다. 내 에코 플래그가 true로 설정되어있는 경우, 이것은 반드시 에코 플래그를 false로 설정되어 있습니다. 따라서이 코드 라인은 에코 플래그를 해제합니다. 코드의 다른 라인은, 단지 그것들 시간에 관심을 복사 한 다음이를 설명 할 것이다. 솔루션에서 그는 0 밝혔다. 그것은 명시 적으로 표준 입력을 말 낫겠 네요. 여기 ICANON | 나 또한 반향을하고있는 것을 확인할 수 있습니다. ICANON는 표준 모드를​​ 의미합니다 별도의 뭔가를 의미합니다. 당신이 명령 줄을 입력 할 때 어떤 표준 모드 수단은, 보통이다 당신은 줄 바꿈 나오기 전까지의 표준은 아무것도 처리하지 않습니다. 그래서 당신은 GetString 않는 경우, 당신은 줄 바꿈 공격 후, 물건의 무리를 입력합니다. 이 인치 표준에 전송 때입니다 그 기본입니다. 당신이 키를 눌러 지금 모든 단일 문자를 표준 모드를​​ 해제하면 어떻게, 이런 일을 처리 할 속도가 느린이기 때문에 보통 나쁜 거라고되며, 처리 치기 이 전체 라인에를 버퍼링하는 것이 좋은 이유입니다. 하지만 각 문자를 처리하고 싶어 저 한테 개행를 공격 할 것이 싫은부터 이 모든 문자를 처리 전에 입력 된습니다. 이 표준 모드를​​ 해제합니다. 실제로 문자를 처리 할 때이 물건은 그냥 의미합니다. 최대한 빨리 그들을 입력있어로를 처리,이 즉시 처리 의미합니다. 그리고이에 표준 내 설정을 업데이트하는 기능입니다 그리고 TCSA 수단은 지금 해. 스트림에 현재 모든이 처리 될 때까지 다른 옵션은 기다릴 수 있습니다. 그건 정말 중요하지 않습니다. 그냥 지금 내 설정이 hacker_typer_settings 현재 무엇이든 할 변경합니다. 내가 그것을 hacker_settings라고 추측 있으니, 그걸를 변경 보자. hacker_settings에 이르기까지 모든을 변경합니다. 지금 우리의 프로그램의 끝에서 우리는 되돌릴 싶을 거예요 normal_settings의 내부 현재 무엇을, 이는 단지 및 normal_settings 같이 예정이다. 제가 원래 발생 이후 내 normal_settings 중 하나를 변경하지 않은 확인합니다. 그런 다음 그들을 다시 변경, 내가 말을 다시 전달합니다. 이 업데이트했습니다. 좋아요. 내부 여기 지금이 시간에 관심의 코드를 설명 할 것이다. 그렇게 많은 코드가 없습니다. 우리는 파일에서 문자를 읽을 참조하십시오. 우리는 F했다. 이제 남자 fgetc 할 수 있습니다,하지만 어떻게 fgetc 일 것입니다 그냥 당신이 방금 읽거나 EOF하는 문자를 반환하는거야 있으며, 이는 파일이나 일부 오류 일어나고의 마지막에 해당합니다. 우리는 파일의 단일 문자를 읽을 계속, 루프 아르 우리는 읽을 문자가 부족까지. 우리가 그렇게하는 동안, 우리는 인치 표준에서 단일 문자를 기다려 매번 당신은 명령 줄에서 뭔가를 입력 인치 표준에서 캐릭터 읽는 그 그런 다음 putchar은 우리가 파일의 표준 출력을 여기에 읽기 숯불을 넣어 것입니다. 당신은 남자 putchar 할 수 있지만, 그냥 일반에게 태우고, 그 문자를 인쇄있어. 같은 생각, 당신은 또한 단지 printf ( "% C", C)를 할 수 있습니다. 그게 우리 작품의 대량을 할거야. 우리가 원하는거야 마지막 것은 우리의 파일을 fclose입니다. 당신은 fclose하지 않은 경우에는 메모리 누수입니다. 우리는 우리가 원래 열 파일을 fclose하려면, 그게 그건 생각합니다. 우리가 할 경우, 이미 문제가 생겼. 어디 봅시다. 그것은 무엇을 불평 했지? 예상 'INT'는 주장 유형 '구조체 _IO_FILE *'입니다. 그이 성공한다면 우리는 볼 수 있습니다. 만 C99에서 허용. Augh. 좋아요, hacker_typer을합니다. 이제 우리는보다 유용한 설명을. 그래서 선언하지 않은 식별자 'normal_settings'중 하나를 사용하십시오. 나는 normal_settings 전화하지 않았어. 나는 current_settings했다. 그럼 그 모든 변경 보자. 지금 인수를 전달. 지금은이 공을드립니다. 좋아요. . / hacker_typer cp.c. 나는 또한 처음에 화면을 지우 없습니다. 하지만 당신은 화면을 삭제 방법에 대해 알아 보려면 마지막 문제 세트로 볼 수 있습니다. 단지 일부 문자를 인쇄 할거야 이게 내가하고 싶었던 일을하고있는 동안. 좋아요. 그리고이 대신 표준 입력 0이되기 위해 필요한 이유에 대한 생각 어떤 #, 0를 정의해야합니다 이 그렇게 불평 - I 파일 설명가 있다고하지만이 또한 FILE *을있을 때하기 전에, 파일 설명은 단지 하나의 정수입니다 FILE *는 그와 관련된 물건을 왕창 가지고 반면. 우리가 대신 표준 입력 0 말을 할 필요가있는 이유 그 표준 입력 파일 설명자 0 참조하는 이야기로 가리키는 파일 *입니다. 그래서, 여기까지 제가 fopen을 할 때 (변수는 argv [1], 내가 다시 FILE *를 발생합니다. 하지만 어느 해당 파일 *에서 해당 파일에 대한 파일 설명자에 해당하는 일입니다. 당신이 열려있는 동안 man 페이지를 보면 나는 당신이 남자 3 공개해야 할 것 같아요 - 아뇨 - 사람이 오픈 - 예. 당신은 열린의 페이지를 보면, 오픈은 낮은 수준의 fopen 같다 그리고 실제 파일 설명을 반환있어. fopen이 열려 위에 물건을 많이 수행, 대신 파일 기술자가 전체 파일에 * 포인터를 반환 그냥 반환하는 내부에있는 우리의 작은 파일 설명입니다. FILE의 *들 이야기로 의미에서 너무 표준 0 자체가 단지 파일 설명자 표준을 의미합니다 반면. 질문이 있으십니까? [웃음]은 꺼졌습니다. 괜찮아요. 우리는 끝났어. [웃음] [CS50.TV]