.NET의 \0(U + 0000) 과 String
Unity3D/C# 2020. 12. 2. 03:15
자다 깨서... 새벽 3시 -_-;;
docs.microsoft.com/ko-kr/dotnet/csharp/language-reference/builtin-types/char
docs.microsoft.com/ko-kr/dotnet/csharp/programming-guide/strings/
using System;
namespace Study07
{
public class App
{
public App()
{
string a = "'abc'".Replace('\'', default(char));
Console.WriteLine("a: {0}, length: {1}", a, a.Length);
string a1 = "'abc'".Replace('\'', default(char)).Trim();
Console.WriteLine("a1: {0}, length: {1}", a1, a1.Length);
string a2 = "'abc'".Replace('\'', default(char)).Trim('\0');
Console.WriteLine("a2: {0} (Length: {1})", a2, a2.Length);
}
}
}
.NET은 문자열을 다루는 데 있어서 C, C++, 혹은 파스칼과 비슷한 듯 다른 면이 있습니다. 그리고 이번 아티클에서는 사소하지만 큰 오류를 내포하게 될 가능성이 있는 부분을 잠시 소개하려고 합니다.
http://msdn.microsoft.com/ko-kr/library/ms228362.aspx 에서는 .NET의 String에 대해 이렇게 소개하고 있습니다.
문자열은 값이 텍스트인 String 형식의 개체입니다. 내부적으로 텍스트는 Char 개체의 순차적 읽기 전용 컬렉션으로 저장됩니다. C# 문자열 끝에는 null 종결 문자가 없습니다. 따라서 C# 문자열은 포함된 null 문자(‘\0′)를 제한 없이 포함할 수 있습니다. 문자열의 Length 속성은 유니코드 문자의 수가 아니라 포함된 Char 개체의 수를 나타냅니다. 문자열에서 개별 유니코드 코드 포인트에 액세스하려면 StringInfo 개체를 사용합니다.
굵게 강조 표시한 부분의 내용에 오늘 아티클의 핵심 내용이 모두 들어있습니다. 하지만 꼼꼼하게 기억해두지 않으면 허술하게 다루어질 가능성도 있는 부분이라고 생각합니다.
위의 내용을 상기하면서, 아래의 코드들이 각각 어떻게 실행될지 예상해보면 흥미롭습니다.
string a = "'abc'".Replace('\'', default(char));
Console.WriteLine("a: {0} (Length: {1})", a, a.Length);
string b = "'abc'".Replace('\'', Char.MinValue);
Console.WriteLine("b: {0} (Length: {1})", b, b.Length);
string c = "'abc'".Replace('\'', (char)0);
Console.WriteLine("c: {0} (Length: {1})", c, c.Length);
string d = "'abc'".Replace('\'', '\0');
Console.WriteLine("d: {0} (Length: {1})", d, d.Length);
Replace로 한 글자만 제거하고 싶어서 위와 같은 코드를 작성하기 쉬운데, 위의 결과에서 원래 의도는 ‘abc’ 라는 다섯 글자를 abc라는 세 글자로 만드는 것이지만, 실제로는 여전히 다섯 글자가 됩니다. 그런데 여기서 한 가지 더 중요한 것은, Trim() 메서드가 앞 뒤로 붙는 null character를 제거해 주지는 않는다는 점입니다.
string a = "'abc'".Replace('\'', default(char)).Trim();
Console.WriteLine("a: {0} (Length: {1})", a, a.Length);
string b = "'abc'".Replace('\'', Char.MinValue).Trim();
Console.WriteLine("b: {0} (Length: {1})", b, b.Length);
string c = "'abc'".Replace('\'', (char)0).Trim();
Console.WriteLine("c: {0} (Length: {1})", c, c.Length);
string d = "'abc'".Replace('\'', '\0').Trim();
Console.WriteLine("d: {0} (Length: {1})", d, d.Length);
앞/뒤로 붙은 null character를 제거하려면 null character를 명시하는 작업이 필요합니다. 그리고 이것은 Replace 메서드에 대해서도 동일하게 적용됩니다.
</pre>
<pre>string a = "'abc'".Replace('\'', default(char)).Trim('\0');
Console.WriteLine("a: {0} (Length: {1})", a, a.Length);
string b = "'abc'".Replace('\'', Char.MinValue).Trim('\0');
Console.WriteLine("b: {0} (Length: {1})", b, b.Length);
string c = "'abc'".Replace('\'', (char)0).Trim('\0');
Console.WriteLine("c: {0} (Length: {1})", c, c.Length);
string d = "'abc'".Replace('\'', '\0').Trim('\0');
Console.WriteLine("d: {0} (Length: {1})", d, d.Length);
이런 맥락에서 보았을 때, 외부로부터 들어오는 입력 문자열에 대해 엄격하게 이야기하자면, null character에 대한 것을 String.Empty로 치환하는 작업도 필요할 수 있다고 볼 수 있겠습니다.
www.damirscorner.com/blog/posts/20160207-StringsInNetAreNotNullTerminated.html
'Unity3D > C#' 카테고리의 다른 글
IComparable.CompareTo(Object) 메서드 (0) | 2021.03.16 |
---|---|
c# async await (0) | 2021.03.10 |
C# bitwise (0) | 2020.11.27 |
C# 확률을 적용한 랜덤값 선택하기 (cumulative) (0) | 2020.11.26 |
디버거에서 변수에 대한 메모리 (0) | 2020.11.24 |