역사적으로 (아마도 일부를 다시 작성하여), 그 반대였습니다. 1970 년대 초반 (아마도 PDP-11 ) 프로토 타입 배아 C (아마도 BCPL )를 실행하는 최초의 컴퓨터 에는 MMU 와 메모리 보호 기능 이 없었습니다 (대부분의 오래된 IBM / 360 메인 프레임 에 존재 함 ). (리터럴 스트링 또는 기계 코드를 처리하는 것을 포함) 메모리의 모든 바이트가 잘못된 프로그램이 덮어 쓰기 할 수 있도록 (일부 변경 프로그램 상상 %
에 /
A의 printf와 (3) 형식 문자열). 따라서 리터럴 문자열과 상수를 쓸 수있었습니다.
1975 년 십대, I 메모리 보호없이 오래된 1960 년대 시대의 컴퓨터에서 파리의 팔레 드 라 메디 테라 박물관 코딩 : / 1620 IBM은 여러 수십 입력했다, 그래서 키보드를 통해 초기화 할 수 있습니다 - 어떤 단지 코어 메모리를했다 펀치 테이프의 초기 프로그램을 읽을 수있는 자릿수; CAB / 500 에는 자기 드럼 메모리가있었습니다. 드럼 근처의 기계식 스위치를 통해 일부 트랙을 쓰지 못하게 할 수 있습니다.
나중에 컴퓨터에는 메모리 보호 기능이있는 메모리 관리 장치 (MMU)가 있습니다. CPU가 어떤 종류의 메모리를 덮어 쓰지 못하게하는 장치가있었습니다. 따라서 일부 메모리 세그먼트, 특히 코드 세그먼트 (일명 .text
세그먼트)는 읽기 전용이되었습니다 (디스크에서로드 한 운영 체제 제외). 컴파일러와 링커에서 리터럴 문자열을 해당 코드 세그먼트에 넣는 것이 자연스럽고 리터럴 문자열은 읽기 전용이되었습니다. 당신의 프로그램이 그것들을 덮어 쓰려고 시도했을 때, 그것은 정의되지 않은 행동 이었습니다. 가상 메모리에 읽기 전용 코드 세그먼트가 있으면 동일한 장점을 제공합니다 . 동일한 프로그램을 실행하는 여러 프로세스 가 동일한 RAM ( 실제 메모리)을 공유합니다.해당 코드 세그먼트에 대한 페이지) ( Linux의 mmap (2) 에 MAP_SHARED
대한 플래그 참조 ).
오늘날 저렴한 마이크로 컨트롤러 에는 읽기 전용 메모리 (예 : 플래시 또는 ROM)가 있으며 코드 (및 리터럴 문자열 및 기타 상수)를 유지합니다. 또한 태블릿, 랩톱 또는 데스크탑과 같은 실제 마이크로 프로세서에는 정교한 메모리 관리 장치와 가상 메모리 및 페이징에 사용되는 캐시 장치가 있습니다. 의 코드 세그먼트 그래서 실행 프로그램 (예에서 ELF가 ) 메모리 읽기 전용, 공유, 그리고에 의해 실행 가능한 세그먼트 (로 매핑됩니다 의 mmap (2) 또는 에서 execve (2) 리눅스, BTW 당신을 지시 줄 수있는 신분증을정말로 원한다면 쓰기 가능한 코드 세그먼트를 얻으려면). 쓰기 또는 악용은 일반적으로 세그먼테이션 오류 입니다.
따라서 C 표준은 바로크 식입니다. 법적으로 (역사적 이유로 만) 리터럴 문자열은 const char[]
배열이 아니라 char[]
덮어 쓸 수 없는 배열입니다.
BTW, 현재 사용 가능한 언어 중 문자열 리터럴을 덮어 쓸 수있는 언어는 거의 없습니다 (역사적으로 쓸 수있는 리터럴 문자열이 최근 4.02에서 동작이 변경되어 현재 읽기 전용 문자열을 갖는 Ocaml조차도).
현재 C 컴파일러는 마지막 5 바이트 (종료 널 바이트 포함) 를 최적화하고 보유 "ions"
하고 "expressions"
공유 할 수 있습니다.
파일에 C 코드를 컴파일하려고 foo.c
으로 gcc -O -fverbose-asm -S foo.c
생성 된 어셈블러 파일 내부 및 모양을 foo.s
하여 GCC
마지막 으로 C 의 의미론 은 충분히 복잡 하며 (캡처하려는 CompCert & Frama-C 에 대해 자세히 읽어보십시오 ) 쓰기 가능한 상수 리터럴 문자열을 추가하면 프로그램이 더 약하고 덜 안전 해지며 더 약해집니다. 정의 된 동작)으로 인해 향후 C 표준이 쓰기 가능한 리터럴 문자열을 허용 할 가능성은 거의 없습니다. 반대로 const char[]
그들은 도덕적으로해야 할 것처럼 배열을 만들 것 입니다.
또한 여러 가지 이유로, 가변 데이터는 상수 데이터보다 컴퓨터 (캐시 일관성), 개발자가 코딩, 이해하기가 어렵습니다. 따라서 대부분의 데이터 (특히 리터럴 문자열)를 변경하지 않는 것이 좋습니다. 함수형 프로그래밍 패러다임 에 대해 자세히 알아보십시오 .
IBM / 7094의 이전 Fortran77 일에서 버그는 상수 를 변경할 수도 있습니다 .2를 참조하여 전달 된 인수를 수정 한 CALL FOO(1)
경우 FOO
구현이 다른 발생을 1로 2로 변경했을 수 있습니다. 나쁜 버그, 찾기가 매우 어렵습니다.