[C#] 기본 자료형 정리 + 참조 정리 + 인코딩 정리

RisingJade의 개발기록·2022년 3월 14일
0

기본 자료형

C 자료형과 다른 점1

  • 옛날옛적 c에서는 char가 아스키 코드에 있는 문자와 짧은 숫자를 모두 표현했기 때문에, 0~255의 범위를 가졌었다.
    따라서, 이때 char는 아스키에 대응되는 숫자였다. 그 숫자를 아스키에 맞는 문자로 표현하기 위해 %c라는 서식문자를 넣었던 것이다.
    하지만 C#으로 오면서, bytechar이 분리되고, byte도 0~255의 범위를 갖습니다.
    char는 이제 순수하게 문자만 표시하고 이에 대응되는 숫자는 byte가 담당하게 됩니다.

  • 따라서 byte는 음수를 갖지 못할 이유가 사라지고(아스키 코드에 음수에 매핑되는게 없었으니...)signed byte, 즉 부호가 있는 byte 자료형인 sbyte가 탄생했다
    (sbyte는 -128~127의 범위를 갖는다.)
    또한, C가 나올때에 비해서는 컴퓨터의 성능이 향상됐기 때문에, 좀더 큰 자료형을 언어 단위에서 정의한다.

  • 예를 들어,
    C에서는 4바이트 짜리였던 long이 8바이트 자료형으로 커졌고
    무려! 16바이트 자료형인 decimal이 추가되었다.(저 크기를 다 쓸순 있나...)
    1바이트에 귀여웠던 우리 char는 무려 2배인 2바이트가 되어 C# 기준 UTF-16인코딩을 사용한다.

    추가: C# 인코딩에 대하여
    C#에서 한 문자는 항상 2바이트를 차지하는가?
    C# string 객체는 코드페이지에 따라 다른 인코딩을 가질 수 있는가? 하나의 C# string 변수는 동일한 메모리에 여러 번 다른 문자열을 가질 수 있는가?
    C#에서 한 문자는 메모리상에서 항상 2바이트를 차지한다.
    C#의 string은 모든 문자들을 유니코드로 저장한다. 좀 더 정확히 말하면 문자들을 UTF-16으로 인코딩하여 저장한다.
    유니코드는 본래 1바이트를 차지하는 영어권 ASCII 문자들의 한계를 극복하고, 전세계 모든 문자들을 포함하기 위해 2바이트 안에 각 문자별로 하나의 Code Point를 갖도록 한 것이다.
    이러한 초기의 유니코드는 UCS-2 (Universal Character Set)이라 불리었는데, 이 UCS-2는 곧이어 65536 문자의 한계에 부딪히게 되었다. 아주 드물게 쓰이는 문자들까지 따지면 65536 문자를 훨씬 넘는 것이었다. 다행히 UCS-2의 U+0000 ~ U+FFFF 중 U+D800 ~ U+DFFF 영역은 어떤 문자도 할당되지 않았었는데, 이를 이용해서 4바이트 Unicode를 만들 수 있었다. UCS-2의 2바이트 유니코드는 기본적인 자주 사용되는 문자들로서 BMP (Basic Multilingual Plane)이라 불렀고, UTF-16은 2바이트의 BMP를 기본적으로 지원하면서 또한 나머지 Rare 문자들을 Lead (U+D800 ~ U+DFFF) + Trail 형태로 4바이트로 표현하였다 (이를 Surrogate Pair라 부른다). 따라서, C#의 string 문자열은 대부분 2바이트를 차지하지만 특별히 Rare 문자를 표현할 경우 4바이트를 차지할 수 있다.

참고:
https://pubul.tistory.com/14 [푸불로그]
https://www.csharpstudy.com/DevNote/Article/24 (여기 정말 글 좋으니 읽어보세요!)
https://docs.microsoft.com/ko-kr/dotnet/csharp/language-reference/

참조

ref

  • ref 키워드는 값이 참조로 전달됨을 나타냅니다. 다음 네 가지 컨텍스트에서 사용됩니다.

  • 메서드 시그니처 및 메서드 호출에서 인수를 메서드에 참조로 전달합니다. 자세한 내용은 참조로 인수 전달을 참조하세요.

  • 메서드 시그니처에서 값을 호출자에게 참조로 반환합니다. 자세한 내용은 참조 반환 값을 참조하세요.

  • 멤버 본문에서 참조 반환 값이 호출자가 수정하려는 참조로 로컬에 저장됨을 나타냅니다. 또는 지역 변수가 참조로 다른 값에 액세스함을 나타냅니다. 자세한 내용은 ref 로컬을 참조하세요.

  • struct 선언에서 ref struct 또는 readonly ref struct를 선언합니다. 자세한 내용은 구조체 형식 문서의 구조체 섹션을 참조하세요.

    예시:

    void Method(ref int refArgument)
    {
        refArgument = refArgument + 44;
    }
    int number = 1;
    Method(ref number);
    Console.WriteLine(number);
    // Output: 45

주의사항

  • ref 또는 in 매개 변수로 전달하는 인수는 전달 전에 초기화해야 합니다. 이 요구 사항은 인수를 전달하기 전에 명시적으로 초기화할 필요가 없는 out 매개 변수와는 다릅니다.

  • 클래스의 멤버는 ref, in 또는 out만 다른 서명을 포함할 수 없습니다. 특정 형식의 두 멤버가 하나는 ref 매개 변수를 포함하고 다른 하나는 out 또는 in 매개 변수를 포함한다는 것 외에는 차이가 없으면 컴파일러 오류가 발생합니다. 예를 들어 다음 코드는 컴파일되지 않습니다.

class CS0663_Example
{
    // Compiler error CS0663: "Cannot define overloaded
    // methods that differ only on ref and out".
    public void SampleMethod(out int i) { }
    public void SampleMethod(ref int i) { }
}

out

  • out 키워드는 인수를 참조로 전달하는 데 사용됩니다. 이는 ref 키워드와 비슷하지만 ref의 경우 변수를 전달하기 전에 초기화해야 한다는 점에서 차이가 있습니다. out 매개 변수를 사용하려면 메서드 정의와 호출하는 메서드에서 모두 out 키워드를 명시적으로 사용해야 합니다. 예를 들면 다음과 같습니다.
class OutExample
{
    static void Method(out int i)
    {
        i = 44; //이런식으로 out붙은 매개변수는 무조건 초기화를 시켜줘야함
    }
    static void Main()
    {
        int value;
        Method(out value);
        // value is now 44
    }
}

주의사항

  • out 인수로 전달되는 변수는 이를 전달하기 전에 초기화할 필요가 없지만 호출하는 메서드는 메서드 반환 이전에 값을 할당해야 합니다.

  • ref 및 out 키워드는 런타임에 서로 다르게 취급되지만 컴파일 타임에는 동일하게 취급됩니다. 따라서 한 메서드는 ref 인수를 사용하고 다른 메서드는 out 인수를 사용하는 경우 메서드를 오버로드할 수 없습니다.

in

  • ref인데 읽기 전용이다.

다음과 같은 종류의 메서드에는 ref, in 및 out 키워드를 사용할 수 없습니다.

  • async 한정자를 사용하여 정의하는 비동기 메서드
  • yield return 또는 문을 포함하는 반복기 메서드
profile
언제나 감사하며 살자!

0개의 댓글