... 할당 된 범위 밖에서 포인터를 간단히 감소시키는 것은 저에게 매우 스케치적인 것 같습니다. C에서 이것이 "허용 된"동작입니까?
허용 되었습니까? 예. 좋은 생각? 보통은 아닙니다.
C는 어셈블리 언어의 약자이며 어셈블리 언어에는 포인터가 없으며 메모리 주소 만 있습니다. C의 포인터는 산술을 할 때 지시하는 크기만큼 증가 또는 감소하는 측면 동작을 갖는 메모리 주소입니다. 이것은 구문 관점에서 다음을 잘 만듭니다.
double *p = (double *)0xdeadbeef;
--p; // p == 0xdeadbee7, assuming sizeof(double) == 8.
double d = p[0];
C에서는 배열이 실제로 중요하지 않습니다. 그것들은 배열처럼 동작하는 연속적인 메모리 범위에 대한 포인터 일뿐입니다. []
연산자이므로 포인터 연산을하고 간접 참조에 대한 속기 a[x]
실제로 수단 *(a + x)
.
등의 커플 일부 I / O 장치로 위의 작업을 수행하는 타당한 이유가 있습니다 double
에 매핑들 0xdeadbee7
과 0xdeadbeef
. 그렇게해야하는 프로그램은 거의 없습니다.
&
연산자 를 사용 하거나을 호출 하는 등의 주소를 만들 때 malloc()
원래 포인터를 그대로 유지하여 가리키는 포인터가 실제로 유효한 것을 알 수 있습니다. 포인터를 줄이면 잘못된 코드 비트가이를 역 참조하여 잘못된 결과를 얻거나 무언가를 방해하거나 환경에 따라 세그먼트 위반을 저지를 수 있습니다. 이것은 특히 가치가 있습니다. 왜냐하면 malloc()
전화 free()
를 건 사람 이 원래 값을 전달하도록 기억해야하며 변경 된 버전이 아니라 모든 지옥이 풀릴 수 있기 때문입니다.
C에 1 기반 배열이 필요한 경우 절대 사용하지 않는 하나의 추가 요소를 할당하는 대신 안전하게 사용할 수 있습니다.
double *array_create(size_t size) {
// Wasting one element, so don't allow it to be full-sized
assert(size < SIZE_MAX);
return malloc((size+1) * sizeof(double));
}
inline double array_index(double *array, size_t index) {
assert(array != NULL);
assert(index >= 1); // This is a 1-based array
return array[index];
}
이것은 상한을 초과하는 것을 방지하기 위해 아무것도하지 않지만 처리하기 쉽습니다.
추가:
C99 초안의 일부 장과 구절 (죄송합니다. 링크 만하면됩니다) :
§6.5.2.1.1에 따르면 첨자 연산자와 함께 사용되는 두 번째 ( "other") 표현식은 정수 유형입니다. -1
는 정수 p[-1]
이므로 유효하므로 포인터도 &(p[-1])
유효합니다. 이것은 해당 위치에서 메모리에 액세스하는 것이 정의 된 동작을 생성한다는 것을 의미하지는 않지만 포인터는 여전히 유효한 포인터입니다.
§6.5.2.2 포인터에 요소 수를 첨가하는 등가의 배열 첨자 운영자가 평가하여, 따라서 말한다 p[-1]
동등하다 *(p + (-1))
. 여전히 유효하지만 바람직한 동작을 생성하지 못할 수 있습니다.
§6.5.6.8에서는 다음과 같이 말합니다 (강조 광산).
정수 유형이있는 표현식이 포인터에 더하거나 뺄 때 결과에는 포인터 피연산자의 유형이 있습니다.
... 식 경우 P
받는 점 i
번째 배열 객체 표현의 요소 (P)+N
(등가 N+(P)
) 및 (P)-N
(여기서 N
값을 갖고 n
, 행) 지점은 각각 i+n
번째 및
i−n
배열 객체의 번째 요소는 그들이 존재 구비 .
이는 포인터 산술 결과가 배열의 요소를 가리켜 야 함을 의미합니다. 산술은 한 번에 수행되어야한다고 말하지 않습니다. 따라서:
double a[20];
// This points to element 9 of a; behavior is defined.
double d = a[-1 + 10];
double *p = a - 1; // This is just a pointer. No dereferencing.
double e = p[0]; // Does not point at any element of a; behavior is undefined.
double f = p[1]; // Points at element 0 of a; behavior is defined.
이런 식으로 일하는 것이 좋습니다? 나는하지 않으며 내 대답은 이유를 설명합니다.