int와 같은 typedef'ing 기본 유형을 사용하는 거리


14

나는 많은 다음과 같은 C ++ 코드를 보았습니다 typedef.

typedefC ++ 프리미티브를 사용하는 대신 이와 같은 많은 것을 사용하면 어떤 이점 이 있습니까? 이러한 이점을 얻을 수있는 다른 접근 방법이 있습니까?

결국, 데이터는 모두 메모리에 저장되거나 와이어를 통해 비트와 바이트로 전송됩니다. 정말로 중요합니까?

types.h:

typedef int16_t Version;
typedef int32_t PacketLength;
typedef int32_t Identity;
typedef int32_t CabinetNumber;
typedef int64_t Time64;
typedef int64_t RFID;
typedef int64_t NetworkAddress;
typedef int64_t PathfinderAddress;
typedef int16_t PathfinderPan;
typedef int16_t PathfinderChannel;
typedef int64_t HandsetSerialNumber;
typedef int16_t PinNumber;
typedef int16_t LoggingInterval;
typedef int16_t DelayMinutes;
typedef int16_t ReminderDelayMinutes;
typedef int16_t EscalationDelayMinutes;
typedef float CalibrationOffset;
typedef float AnalogValue;
typedef int8_t PathfinderEtrx;
typedef int8_t DampingFactor;
typedef int8_t RankNumber;
typedef int8_t SlavePort;
typedef int8_t EventLevel;
typedef int8_t Percent;
typedef int8_t SensorNumber;
typedef int8_t RoleCode;
typedef int8_t Hour;
typedef int8_t Minute;
typedef int8_t Second;
typedef int8_t Day;
typedef int8_t Month;
typedef int16_t Year;
typedef int8_t EscalationLevel;

오버플로를 피하기 위해 특정 유형에 항상 동일한 유형이 사용되도록하는 것이 논리적으로 보이지만, "int"가 거의 모든 곳에서 사용 된 코드를 자주 볼 수 있습니다. typedef자주 생각처럼 조금 보이는 코드에 리드를 수행 보내고 :

DoSomething(EscalationLevel escalationLevel) {
    ...
}

그러면 어떤 토큰이 매개 변수를 실제로 설명하고 있는지 궁금합니다 : 매개 변수 유형 또는 매개 변수 이름?


2
IMHO는 꽤 무의미한 운동처럼 보이지만 다른 사람들이 동의하지 않을 것이라고 확신합니다.
Nim

1
이러한 유형은 변수 이름처럼 보입니다.
기린 선장

11
이것은 type-safe라는 인상을 주지만, typedef는 별명을 만들지 만, 예를 들어 a Minute로 type으로 선언 된 인수가있는 함수에 전달하는 것을 막을 수는 없습니다 Second.
Jesper

2
@ 마크 : 다른 방법으로보세요. 정수 유형을 결정하는 실수를 범하거나 미래에 새로운 요구 사항이 발생하여 변경하려는 경우 단일 typedef를 변경하거나 1 년 동안 조작하는 모든 함수에 대해 코드를 검색하려고합니다. 서명을 바꾸시겠습니까? 640k는 누구에게나 충분합니다. typedef의 단점은 사람들이 Year가 정확히 16 비트라는 사실에 의존하여 실수로 또는 고의로 코드를 작성하면 변경되고 코드가 중단된다는 것입니다.
Steve Jessop 2016 년

1
@Steve Jessop : 좋은 생각인지 나쁜 생각인지 결정할 수 없습니다 :-) 첫 번째 부분은 유리한 것으로 보입니다. 나는 그것이 장단점이 있다고 생각합니다.

답변:


13

매개 변수의 이름은 의미에 대해 설명해야합니다 (이 경우 에스컬레이션 레벨). 유형은 값이 표현되는 방식입니다. 예제에서 typedef를 추가하면 함수 서명의이 부분이 난독 화되므로 권장하지 않습니다.

Typedef는 템플리트에 유용하거나 32 비트에서 64 비트 플랫폼으로 마이그레이션 할 때와 같이 특정 매개 변수에 사용되는 유형을 변경하려는 경우에 유용합니다.


이것은 일반적인 합의 인 것 같습니다. 일반적으로 "int"를 고수 하시겠습니까? 데이터를 전송할 때이 응용 프로그램에서 매우 효율적이어야하므로 직렬화 중에 int16_t (또는 특정 요소에 필요한 가장 큰 표현 유형)로 변환하는 경우입니까?

@ 마크 : 그렇습니다. 그렇게해야합니다. typedef를 사용하여 사용 된 데이터 유형의 크기를 나타내지 만 다른 컨텍스트에서 사용되는 동일한 유형을 구별하지는 마십시오.
Björn Pollex 2016 년

고마워-그리고 분명히하기 위해, 일반적으로 코드에서 int 대신 int8_t를 사용하는 것을 귀찮게하지 않을 것입니다. 내 주요 걱정은 실제로 데이터베이스에 의해 생성 된 ID 인 "Identity"와 같은 것이라고 생각합니다. 현재 32 비트이지만 최종적으로 64 비트가 될지 확실하지 않습니다. 또한 int32_t 대 int는 어떻습니까? int는 일반적 으로 int32_t와 동일하지만 항상 다른 플랫폼에서 추측하지는 않습니까? 나는 일반적으로 "int", 그리고 "int64_t"를 필요로하는 곳에 집중해야한다고 생각한다 .. thanks :-)

@Mark : typedef에 관한 중요한 점은 int32_t다른 플랫폼에서 컴파일 할 때 그것들이 올바른지 확인해야한다는 것입니다. Identity어느 시점에서 범위 가 변경 될 것으로 예상되는 경우 영향을받는 모든 코드에서 직접 변경하는 것이 좋습니다. 그러나 특정 디자인에 대해 더 알아야하기 때문에 확실하지 않습니다. 별도의 질문을 할 수도 있습니다.
Björn Pollex 2016 년

17

처음에는 "왜 안 돼?"라고 생각했지만 그런 길이로 갈 때 그와 같은 유형을 분리하려는 경우 언어를 더 잘 사용한다는 것이 나에게 일어났습니다. 별명을 사용하는 대신 실제로 유형을 정의하십시오.

class AnalogueValue
{
public:
    // constructors, setters, getters, etc..
private:
    float m_value;
};

다음과 같은 성능 차이는 없습니다.

typedef float AnalogueValue;
AnalogValue a = 3.0f;
CallSomeFunction (a);

과:

AnalogValue a (3.0f); // class version
CallSomeFunction (a);

또한 매개 변수 유효성 검사 및 유형 안전성을 추가 할 수 있다는 이점이 있습니다. 예를 들어, 기본 유형을 사용하여 돈을 처리하는 코드를 고려하십시오.

float amount = 10.00;
CallSomeFunction(amount);

반올림 문제 외에도 플로트로 변환 할 수있는 모든 유형을 허용합니다.

int amount = 10;
CallSomeFunction(amount);

이 경우 큰 문제는 아니지만 암시 적 변환은 찾기 어려운 버그의 원인이 될 수 있습니다. typedef여기서는 별칭 일 뿐이므로 a를 사용하면 도움이되지 않습니다.

새로운 유형을 사용한다는 것은 캐스팅 연산자를 코딩하지 않는 한 암시 적 변환이 없다는 것을 의미합니다. 이는 암시 적 변환을 허용하기 때문에 특히 나쁜 생각입니다. 추가 데이터를 캡슐화 할 수도 있습니다.

class Money {
  Decimal amount;
  Currency currency;
};

Money m(Decimal("10.00"), Currency.USD);
CallSomeFunction(m);

우리가 코드를 작성하지 않으면 그 함수에 맞는 것은 없습니다. 실수로 변환 할 수 없습니다. 번거 로움없이 필요에 따라 더 복잡한 유형을 작성할 수도 있습니다.


1
당신은 당신을 위해이 클래스 생성을 모두하기 위해 끔찍한 매크로를 작성할 수도 있습니다. (Skizz 어서 당신은 당신이 원하는 것을 알고있다..)

1
이들 중 일부의 경우 유형 안전 단위 라이브러리가 각각에 대한 사용자 정의 클래스를 작성하는 것보다 도움이 될 수 있습니다 ( tuoml.sourceforge.net/html/scalar/scalar.html ).
Steve Jessop 2016 년

@Chris-확실히 매크로는 아니지만 템플릿 클래스 일 수 있습니다. Steve가 지적했듯이 해당 클래스는 이미 작성되었습니다.
케빈 클라인

4
@Chris : 매크로는 BOOST_STRONG_TYPEDEF실제로 호출됩니다 ;)
Matthieu M.

3

이와 같은 기본 유형에 typedef를 사용하면 C 스타일 코드와 비슷합니다.

C ++에서는 for, say EventLevel및에 대한 함수를 오버로드하려고하면 흥미로운 오류가 발생합니다 Hour. 이것은 여분의 타입 이름을 쓸모 없게 만듭니다.


2

우리 회사에서는 C ++로 많은 일을합니다. 코드 이해 및 유지 관리에 도움이됩니다. 사람들을 팀간에 옮기거나 리팩토링을 할 때 좋습니다. 예:

typedef float Price;
typedef int64_t JavaTimestmap;

void f(JavaTimestamp begin, JavaTimestamp end, Price income);

표현 유형에서 치수 이름으로 typedef를 작성하는 것이 좋습니다. 이 새로운 이름은 소프트웨어에서 일반적인 역할 을 나타냅니다 . 매개 변수의 이름은 로컬 역할 입니다. 에서처럼 User sender, User receiver. 어떤 곳에서는과 같이 중복 될 수 void register(User user)있지만 문제라고 생각하지 않습니다.

나중에 float예약의 특수 반올림 규칙으로 인해 가격을 표현하기에 가장 적합하지 않다는 생각을 가질 수 있으므로 BCDFloat(이진 코드 10 진수) 유형을 다운로드하거나 구현 하고 typedef를 변경합니다. 더가 검색하지 않으며에서 작업을 대체됩니다 floatBCDFloat 코드에서 가능한 많은 수레가 있다는 사실에 의해 강화 될 것이다.

그것은 총알이 아니며 자체 경고가 있지만 사용하지 않는 것이 훨씬 낫습니다.


또는 Skizz의 게시물에서 Mathieu M.이 제안한 것처럼으로 갈 수 BOOST_STRONG_TYPEDEF(float, Price)는 있지만 평균 프로젝트에서는 그렇게하지 않을 것입니다. 아니면 어쩌면 나는 잠을 자야한다. :-)
Notinlist

1

typedef기본적으로에 대한 별칭을 제공 할 수 있습니다 type.
오랫동안 타이핑을 피하고 유연성을 제공하는 유연성을 type names제공합니다.type 더 쉽게 읽을 수있게 여기서 별명 이름은의 의도 나 목적을 나타냅니다 type.

typedef프로젝트에서 더 읽기 쉬운 이름을 원한다면 선택의 여지가 있습니다 .
일반적으로 typedef형식이 너무 길지 않으면 기본 형식을 사용하지 않습니다. 매개 변수 이름을 더 잘 나타냅니다.


0

나는 이런 식으로 절대로하지 않을 것입니다. 그것들이 모두 같은 크기인지 확인하는 것은 하나의 일이지만 당신은 그것들을 완전한 타입으로 지칭하기 만하면됩니다.


0

누구든지 이것들을 사용하는 사람이 기본 표현에 대해 아무것도 알 필요가없는 한 이와 같은 typedef를 사용하는 것은 좋습니다. 예를 들어 PacketLength객체를 printf또는 에 전달 scanf하려면 올바른 변환 지정자를 선택할 수 있도록 실제 유형을 알아야합니다. 그런 경우 typedef는 대가로 아무것도 사지 않고 난독 화 수준을 추가합니다. 객체를로 정의했을 수도 있습니다 int32_t.

각 유형에 고유 한 의미 (예 : 허용 범위 또는 값)를 적용해야하는 경우 typedef를 작성하는 대신 추상 데이터 유형 및 해당 유형에서 작동 할 함수를 작성하는 것이 좋습니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.