new 연산자에 의해 동적 생성된 메모리 공간은 쓰레기 값garbage value이라고 부르는 임의의 값들이 들어가 있다. 만약 2차원 배열을 동적 생성하면서 그 내부의 값을 모두 0으로 초기화하고자 한다면 다음과 같은 형태로 코드를 작성해야 한다.
#include <memory.h> ... unsigned char** p; p = new unsigned char*[h]; for (int i = 0; i < h; i+ +) { p[i] = new unsigned char[w]; memset(p[i], 0, sizeof(unsigned char)*w); }
위 코드에서 for 루프 안에 memset이라는 함수 호출이 한 줄 추가되었다. memset 함수는 특정 메모리 주소부터 일정 크기만큼 메모리 공간의 값을 설정하는 함수이며 원형은 아래와 같다.
void *memset(void *dest, int c, size_t count);
그러므로 memset(p[i], 0, sizeof(unsigned char)*w); 코드의 의미는 p[i]가 가리키는 메모리 공간으로부터 sizeof(unsigned char)*w에 해당하는 크기의 메모리 공간을 모두 0으로 채우라는 의미이다. 그러므로 위의 코드로 생성된 2차원 동적 배열은 모두 초깃값 0을 가지게 된다. memset 함수를 사용하려면 memory.h 또는 string.h 파일을 포함(#include)해야 한다.
그러면 동적 생성된 2차원 배열의 원소에 접근하는 방법에 대하여 알아보자. 2차원 배열의 원소는 for 루프 2개를 중첩하여 사용하는 이중 for 루프를 이용하여 접근한다. 예를 들어 앞에서 생성한 2차원 동적 배열 p의 모든 원소의 값을 1씩 증가하는 기능을 C/C++ 코드로 작성하면 다음과 같다.
for (int j = 0; j < h; j+ +) { for (int i = 0; i < w; i+ +) { p[j][i] = p[j][i] + 1; } }
앞의 코드에서 w는 배열의 가로 크기이고, h는 세로 크기를 나타낸다. 이중 for 루프에서 바깥쪽 for 루프는 y축에 대한 for 루프이고, 안쪽 for 루프는 x축에 대한 for 루프이다. y축에 대한 for 루프의 인덱스는 j를 주로 사용하고, x축에 대한 for 루프의 인덱스는 i를 사용함에 주의하기 바란다. 이 책에서는 배열의 인덱스에서 i는 x축의 좌표를 의미하고, j는 y축의 좌표를 나타낼 것이다.
앞의 코드에서 한 가지 주의할 점은 p[j][i]에 저장할 수 있는 값의 범위는 0부터 255 사이라는 점이다. 이는 앞에서 동적 배열 p를 생성할 때, 자료형을 unsigned char로 설정하였기 때문이다. 이 범위를 벗어난 값을 저장하려고 할 경우, 자동으로 0부터 255 사이의 값으로 변환되어 저장된다. 예를 들어 현재 p[j][i]에 들어 있는 값이 255인 경우, (p[j][i] + 1)에 해당하는 값은 256이지만 실제 p[j][i] = p[j][i] + 1; 코드에 의해 새로 변경되는 p[j][i]의 값은 0으로 바뀌어 저장된다. 그러므로 실제 영상 처리 알고리즘 구현에서는 이러한 예외 상황에 대한 처리도 고려해주어야 한다. 이에 대한 자세한 사항은 실제 영상의 픽셀 값을 처리하는 6장에서 자세히 설명할 것이다.