Quick Reference
길이가 n인 배열의 유효 인덱스는 0부터 n - 1입니다. arr + n은 끝 비교에만 쓰고 역참조하지 않습니다.
for (size_t i = 0; i < n; i++) {
arr[i] = 0;
}
for (int *p = arr; p != arr + n; p++) {
*p = 0; /* arr + n 자체는 역참조하지 않는다. */
}
char name[8];
snprintf(name, sizeof name, "%s", source); /* 마지막 한 칸은 '\0' */i <= n과 *(arr + n)은 마지막 다음 원소를 건드립니다. 문자열 buffer에는 문자 수와 별도로 널 종료 문자 한 칸이 필요합니다.
문법
배열은 같은 타입 원소가 연속 메모리에 놓인 블록입니다. arr[i]는 시작 주소에서 i * sizeof(arr[0])만큼 이동한 원소를 읽는 표현이라서, 인덱스 하나가 곧 주소 계산입니다.
int values[4] = {10, 20, 30, 40};
size_t n = sizeof(values) / sizeof(values[0]);
for (size_t i = 0; i < n; i++) {
printf("%d\n", values[i]);
}반대로 아래처럼 <=를 쓰면 마지막 반복에서 values[4]를 읽게 됩니다.
for (size_t i = 0; i <= n; i++) {
printf("%d\n", values[i]); // 마지막 반복에서 경계 초과
}경계 이해
포인터로는 마지막 다음 위치를 가리키는 것까지는 허용됩니다. 하지만 그 위치를 실제 원소처럼 읽거나 쓰면 안 됩니다.
int *end = values + n; // 가능
// int x = *end; // 불가문자열 버퍼도 같은 규칙을 따릅니다. 문자열은 문자 수뿐 아니라 널 종료 문자 '\0'를 위한 한 칸이 더 필요합니다.
char name[5];
strncpy(name, "abcd", sizeof(name));
name[4] = '\0';strncpy는 source가 count 이상 길면 널 종료 문자를 붙이지 않습니다. 위처럼 마지막 칸을 직접 0으로 만들 때는 destination이 0보다 큰지와, 복사 뒤 잘림을 허용하는지까지 호출 규약에 넣어야 합니다. 일반 문자열 복사는 destination capacity를 먼저 받고 반환값으로 잘림을 알 수 있는 방식을 선택하는 편이 명확합니다.
빠른 점검
- 길이
n배열의 유효 인덱스는0..n-1입니다. - 순회의 기본은 거의 항상
i < n입니다. arr + n은 만들 수 있지만*(arr + n)은 읽으면 안 됩니다.- 문자열 버퍼는 문자 수와
'\0'공간을 같이 계산해야 합니다. - 함수로 넘긴 뒤에는 길이 정보가 자동으로 따라가지 않으므로 별도 길이 인자를 같이 봐야 합니다.
size_t i = n - 1은n == 0일 때 매우 큰 값으로 underflow합니다. 마지막 인덱스가 필요하면 먼저 빈 배열을 처리합니다.
주의할 점
경계 초과는 바로 크래시가 나지 않을 때 더 위험합니다. "지금은 돌아가지만 옆 메모리를 조용히 덮어쓰는" 경우가 가장 흔하므로, 배열 코드는 로직보다 먼저 반복 범위와 길이 계산을 확인하는 습관이 중요합니다.
참고 링크
2 sources