HOWTO · Arduino
Arduino `memset()` 함수
Arduino에서 `memset()`으로 지정한 메모리 범위에 같은 바이트 값을 채우고, 배열 요소에는 언제 직접 대입해야 하는지 알아봅니다.
이 페이지의 내용
memset()은 지정한 메모리 주소부터 정해진 바이트 수만큼 같은 바이트 값을 반복해 채웁니다. 배열을 다룰 때는 sizeof로 바이트 수를 계산하고, 숫자 요소마다 값을 대입하려면 자료형에 맞는 대입을 사용하세요.
Arduino에서 memset() 함수 소개
Arduino C++에서 memset()은 연속된 바이트 범위에 하나의 바이트 값을 반복해서 씁니다. 바이트 버퍼나 문자 배열을 채울 때 유용하지만, 여러 바이트로 이루어진 값을 배열의 각 요소에 복사하지는 않습니다. 세 번째 인수는 요소 수가 아니라 바이트 수이므로, 실제로 채우려는 저장 공간을 기준으로 계산해야 합니다.
표준 함수 선언은 <string.h>에 있으며, C++ 헤더인 <cstring>으로도 사용할 수 있습니다. 형식은 memset(destination, value, byte_count)입니다. destination은 첫 바이트를 가리키고, value는 부호 없는 바이트 값으로 변환되며, byte_count는 쓸 바이트 수를 지정합니다. 함수는 변환된 바이트 하나를 반복해서 씁니다. 전달한 원래 값의 바이트들을 가져와 복사하는 것은 아닙니다.
Arduino에서 memset() 사용하기
다음 C++ 예제는 문자 배열을 채운 다음 배열 안의 일부 범위를 바꿉니다. 보드별 직렬 연결 없이 바이트 작업을 보여 주기 위해 표준 출력을 사용합니다.
#include <cstring>
#include <iostream>
int main() {
char letters[] = "hello";
std::memset(letters, '.', sizeof(letters) - 1);
std::memset(letters + 1, 'a', 2);
std::cout << letters << '\n';
return 0;
}
.aa..
배열에는 다섯 글자와 문자열 끝을 표시하는 널 문자를 저장할 공간이 있습니다. 첫 번째 호출은 화면에 보이는 문자 다섯 개만 채우므로 널 종료 문자는 그대로 남습니다. 두 번째 호출은 인덱스 1에서 시작해 바이트 두 개를 쓰므로 인덱스 1과 2의 문자가 바뀝니다. Arduino 스케치에서도 같은 배열 연산을 memset()으로 수행할 수 있으며, 결과 문자 배열은 Serial.print()로 출력하면 됩니다.
요소 자료형이 다른 배열은 배열 자체의 크기를 이용해 바이트 수를 구하세요. 예를 들어 memset(values, 0, sizeof(values))는 values의 모든 바이트를 채웁니다. 전체 요소 중 일부 범위를 채우려면 요소 수만큼 시작 위치를 이동하고 요소 크기를 곱합니다. 예: memset(values + start, byte_value, count * sizeof(values[0])). 배열 인덱스는 0부터 시작하며, 선택한 범위가 배열 저장 공간을 벗어나지 않아야 합니다.
정수 배열을 바이트 값 2로 채워도 각 요소에 정수 2가 대입되는 것은 아닙니다. 16비트 리틀 엔디안 int를 사용하는 대상에서는 각 요소의 두 바이트가 0x0202가 되어 514를 나타낼 수 있습니다. 정수 너비나 표현 방식이 다른 대상에서는 결과도 달라질 수 있습니다. 각 요소에 자료형이 있는 값 2를 대입하려는 목적이라면 for (int i = 0; i < count; ++i) values[i] = 2;와 같은 반복문을 사용하세요.
Arduino의 String에서 문자를 바꾸려면 text[i] = '.';처럼 인덱스로 직접 대입할 수 있습니다. 이는 문자를 직접 대입하는 방법이며 memset()을 사용하는 것은 아닙니다.
중요 고려 사항
대상이 쓰기 가능한 저장 공간을 가리키는지, 바이트 수가 그 공간의 크기를 넘지 않는지 항상 확인하세요. 배열 자체를 가리키는 식에서 sizeof(array)를 사용하면 전체 바이트 크기를 구할 수 있습니다. 하지만 배열로 선언한 함수 매개변수는 포인터이므로, 길이를 별도로 전달하거나 계산해야 합니다. 바이트 수가 0이면 아무 바이트도 쓰지 않지만, 함수의 계약에 따라 대상 포인터는 여전히 유효해야 합니다.
반복 바이트 패턴은 객체의 값을 일반적으로 대입하는 방법이 아닙니다. 문자 버퍼를 채우거나 바이트를 지우는 것처럼 해당 바이트 표현 자체가 의도된 경우에 적합합니다. 리소스를 관리하거나 생성자와 불변 조건에 의존하는 객체 등 비단순 C++ 객체를 초기화하는 데 사용하지 마세요. 일반 값과 객체에는 자료형에 맞는 대입, 값 초기화 또는 객체가 제공하는 API를 사용하세요.
결론
정해진 바이트 범위에 같은 바이트를 반복해서 써야 할 때 memset()을 사용하세요. 범위 크기는 바이트 단위로 계산하고, 배열에서는 요소 너비를 고려하며, 모든 쓰기가 대상 저장 공간 안에 들도록 해야 합니다. 정수 값, 문자열, 객체에는 반복 바이트 패턴이 꼭 필요한 경우가 아니라면 자료형에 맞는 대입이나 적절한 초기화 방법을 선택하세요.