const int, enum 또는 #define이 훨씬 더 의미가있는 경우 핀에 int 변수를 사용하는 이유


24

코드 실행 중에 핀이 변경되지 않을 때 사람들이 변수를 사용하여 핀 번호를 지정하는 이유는 무엇입니까?

여러 번 int핀 정의에 사용되는 것을 보았습니다.

int led = 13;

때 사용 const int

const int led = 13;

또는 enum, 또는#define

#define LED 13

훨씬 더 의미가 있습니다.

예를 들어 대부분의 사람들이 실행하는 첫 번째 자습서 인 Blink 와 같은 Arduino 사이트의 자습서에도 있습니다.

나는 선호하는 const int 습니다 #define. 사람들이 처음부터 나쁜 습관을들이도록 허용하는 것이 아니라 처음부터 올바르게 권장되지 않는 이유는 무엇입니까? 나는 얼마 전에 그것을 알아 차 렸지만 최근에 나를 자극하기 시작했다.

메모리 / 처리 / A는 현명한 계산 const int, enum또는 그 문제에 대해 #define더 일반에 비해 int, 즉 저장 메모리를 적게 차지 다른 메모리 (플래시, EEPROM, SRAM), 빠른 실행을 더 빠르게 컴파일?


이것은 복제본처럼 보일 수 있습니다. 상수에 #define 또는 const int를 사용하는 것이 더 낫습니까? 그러나 사람들이 변수를 사용하는 이유와 상수 유형이 더 나은 것이 아니라 변수가 아닌 경우 성능이 어떻게 향상되는지에 대한 질문을 다루고 있습니다.


9
끔찍한 것이 끔찍하기 때문에. 대부분의 애호가들은 노련한 프로그래머가 아니므로 다른 애호가에게 나쁜 습관을 가르치십시오.
Ignacio Vazquez-Abrams

1
특히 핀, digitalWrite 같은 기본 아두 이노 API 함수의 단순한 형태는 적절한 임베디드 설계, 즉 사용 마스크와 전체 포트의 단일 메모리 주소를 권장하지 않습니다
crasic

답변:


20
const int led = 13;

이것이 올바른 방법입니다. 또는:

const byte led = 13;

핀이 몇 개입니까?

일부 자습서는 품질 관리를 제대로 수행하지 못했습니다.

성능은 컴파일러 const byte와 비교 하여 더 잘 사용할 수 int있지만 컴파일러는 현명한 작업을 실현할 수 있습니다.

당신이 할 수있는 일은 사람들이 자신의 코드에서보다 효율적인 기술을 사용하도록 부드럽게 격려하는 것입니다.


의견에 대한 답변

  1. 한 의견 제안자는 byte표준 C가 아니라고 제안했습니다 . 이것은 맞지만 이것이 Arduino StackExchange 사이트이며 Arduino IDE에서 제공하는 표준 유형을 사용하는 것이 허용됩니다.

    Arduino.h에는 다음 줄이 있습니다.

    typedef uint8_t byte;

    이와 정확히 동일하지는 않습니다 unsigned char. 참조 서명 숯불 대 uint8_t때 uint8_t ≠ 서명 숯불입니까? .

  2. 다른 의견 제시자는 바이트보다 작은 숫자 int가 승격 되기 때문에 바이트를 사용한다고해서 반드시 성능이 향상되는 것은 아니라고 제안했습니다 int(더 자세한 내용은 정수 승격 규칙 참조).

    그러나 const 식별자와 관련하여 컴파일러는 어떤 경우에도 효율적인 코드를 생성합니다. 예를 들어, "깜박임"을 분해하면 원래 형태로 나타납니다.

    00000086 <loop>:
      86:   8d e0           ldi r24, 0x0D   ; 13
      88:   61 e0           ldi r22, 0x01   ; 1
      8a:   1b d1           rcall   .+566       ; 0x2c2 <digitalWrite>

    실제로 다음과 같은 경우 동일한 코드를 생성합니다 13.

    • 리터럴
    • 입니다 #define
    • 입니다 const int
    • 입니다 const byte

컴파일러는 숫자를 하나의 레지스터에 넣을 수있는 시점과 실패 할 수있는 시점을 알고 있습니다. 그러나 의도 를 나타내는 코딩을 사용 하는 것이 좋습니다 . 이 만들기 는 번호가 변경되지 않습니다 취소 만들고, 그것을 만드는 것은 (나 ) 당신이 소수를 기대하고 있음을 삭제합니다.constbyteuint8_t


혼란스러운 오류 메시지

피해야 할 또 다른 주요 이유 #define는 실수를했을 때 나타나는 오류 메시지입니다. 오류가있는이 "깜박임"스케치를 고려하십시오.

#define LED = 13;

void setup() {
  pinMode(LED, OUTPUT);      // <---- line with error
}

void loop() {
  digitalWrite(LED, HIGH);   // <---- line with error 
  delay(1000);             
  digitalWrite(LED, LOW);    // <---- line with error
  delay(1000);              
}

표면에는 문제가 없지만 다음과 같은 오류 메시지가 생성됩니다.

Blink.ino: In function ‘void setup()’:
Blink:4: error: expected primary-expression before ‘=’ token
Blink:4: error: expected primary-expression before ‘,’ token
Blink:4: error: expected `;' before ‘)’ token
Blink.ino: In function ‘void loop()’:
Blink:8: error: expected primary-expression before ‘=’ token
Blink:8: error: expected primary-expression before ‘,’ token
Blink:8: error: expected `;' before ‘)’ token
Blink:10: error: expected primary-expression before ‘=’ token
Blink:10: error: expected primary-expression before ‘,’ token
Blink:10: error: expected `;' before ‘)’ token

첫 번째 강조 표시된 행 (4 행)을 보고 "="기호도 표시하지 않습니다 . 또한 선이 잘 보입니다. 이제 문제가 무엇인지 분명히 알 수 있지만 ( = 13대체되고 있음 LED) 코드에서 줄이 400 줄 더 떨어져 있으면 LED가 정의되는 방식에 문제가 있는지 확실 하지 않습니다.

나는 사람들이 이것에 여러 번 넘어지는 것을 보았다.


핀이 몇 개입니까? 대부분의 보드 만 수십의 범위에 가지고있는 아주 좋은 지적 닉은하지 수백 (즉, 255보다 큰), 그래서이다 int아두 이노가 마지막으로 나올 때까지입니다 ... 잔인한 테라 보드 ... :-)
Greenonline

2
C byte타입 이 없습니다 . 당신은 의미 unsigned char합니다.
Kevin

대부분의 상황에서보다 작은 유형의 정수 값 이로 승격 되기 때문에 성능이 byte반드시을 대신하여 더 나은 것은 아닙니다 . intintint
피트 베커

1
C doesn't have a byte type. You mean unsigned char.-내 대답은 이것을 가진 Arduino 컨텍스트에 typedef uint8_t byte;있었습니다. 따라서 Arduino의 경우 사용 byte은 정상입니다.
Nick Gammon

Performance won't necessarily be better with byte instead of int-수정 된 게시물을 참조하십시오.
Nick Gammon

19

이그나시오 (Ignacio)는 올바른 상태를 가지고 있기 때문에 기본적으로 더 잘 알지 못하기 때문입니다. 그리고 그것들을 가르친 사람들 (또는 그들이 배울 때 사용한 자료)이 더 잘 알지 못했기 때문에 그들은 더 잘 알지 못합니다.

대부분의 Arduino 코드와 튜토리얼은 프로그래밍에 대한 교육을받은 적이없는 사람들이 작성했으며 프로그래밍에 대한 적절한 교육을받지 않고 스스로를 많이 배우는 사람들이 제공하는 리소스를 통해 "자체 교육"을 받았습니다.

시험장에 표시하면 많은 부분의 튜토리얼 코드 스 니펫 (특히 YouTube 비디오에서만 사용할 수있는 것)이 실패 표시가됩니다.

예, a const는 비 const, 심지어 a보다 선호됩니다 #define.

  • const( #define비 const와 달리 A 와 같은 )는 RAM을 할당하지 않습니다
  • A const(비 const와 같지만 a와 달리 #define)는 값에 명시 적 유형을 제공합니다

두 번째 요점은 특히 관심이 있습니다. 포함 된 형식 캐스팅 ( (long)3) 또는 형식 접미사 ( 3L) 또는 소수점 ( 3.0) 이있는 경우 특별히 다르게 말하지 않는 #define한 숫자는 항상 정수가되고 해당 값에서 수행되는 모든 수학은 마치 정수. 대부분의 경우 문제는 아니지만 #define정수보다 큰 값을 저장할 때 흥미로운 시나리오가 발생할 수 있습니다. 예를 들어 #define COUNT 70000다른 int값 을 사용하여 수학 연산을 수행 하십시오. 를 사용 const하면 컴파일러에게 "이 값은이 변수 유형으로 취급됩니다"라고 알려주므로 대신 다음을 사용 const long count = 70000;하면됩니다. 모두 예상대로 작동합니다.

또한 장소 주변의 값을 전달할 때 유형을 확인하는 노크 효과가 있습니다. const long를 기대하는 함수에 a 를 전달 int하면 변수 범위를 좁히는 것에 대해 불평 할 수 있습니다 (또는 시나리오에 따라 완전히 컴파일하지 못함). a를 사용하면 #define자동으로 잘못된 결과를 얻을 수 있으며 몇 시간 동안 머리를 긁적 거리게됩니다.


7
• 그래도 주목할 그것은의 가치가 const변수가 수도 가 아닌 constexpr 함수의 반환 값을 사용하여 초기화 않다면 상황에 맞는 예에 따라, RAM이 필요합니다.
피터 블룸필드

마찬가지로 const int foo = 13; bar(&foo);컴파일러가에 대한 실제 메모리를 할당해야합니다 foo.
Ilmari Karonen

3
int컴파일러에 맞지 않는 값으로 확장되는 매크로를 정의 하면 컴파일러가 값을 가장 작은 유형 (사인 vs. 부호없는 모듈 규칙)으로 취급합니다. 당신이 시스템에있는 경우 int16 비트, #define count 70000발생합니다 count유사한보고 long가로 정의되었던 것처럼, const long count = 70000;. 또한 해당 버전 중 하나를 count기대하는 함수에 전달하면 int정상적인 컴파일러가 동일한 버전을 처리합니다.
피트 베커

1
@PeteBecker에 동의합니다-같은 구조 #define COUNT 70000는 int로 잘리지 않지만 컴파일러는이 숫자를 보유하기에 충분히 큰 유형으로 처리합니다. 그것이 COUNTint가 아니라는 것을 사용할 때 분명하지 않을 수도 있지만 const long어쨌든 같은 것을 말할 수 있습니다.
Nick Gammon

2
"#define은 항상 정수입니다." 사실이 아닙니다. 정수 리터럴 규칙을 사용하여이를 전 처리기 매크로에 적용합니다. 사과와 팝 음악을 비교하는 것과 같습니다. 표현 COUNT당신의 예는 식으로 컴파일하기 전에 대체 70000처럼 리터럴의 규칙에 의해 정의 된 유형이, 2또는 13L또는 4.0리터럴의 규칙에 의해 정의됩니다. #define해당 표현식의 별명을 지정하는 데 사용한다는 사실 은 관련이 없습니다. 원하는 #define경우 C 코드의 임의 청크의 별칭을 지정할 수 있습니다 .
Monica와의 가벼움 경주

2

Arduino의 2 주 초보자 인 저는 프로그래머가 아닌 사람들이 Arduino를 점유하고 있다는 일반적인 아이디어를 얻었습니다. Arduino 사이트의 스케치를 포함하여 내가 조사한 대부분의 스케치는 작동하지 않고 일관된 의견을 거의 나타내지 않는 스케치와 함께 순서가 부족합니다. 순서도는 존재하지 않으며 "라이브러리"는 검토되지 않은 혼란입니다.


0

내 대답은 ... 작동하기 때문에 그렇게합니다. "왜 '잘못된'이어야합니까?"와 같은 질문에 대답하지 않는 데 어려움을 겪고 있습니다.


3
좋은 프로그래머의 특징 중 하나는 코드가 항상 의도를 반영한다는 것입니다.
Ignacio Vazquez-Abrams

1
우리는 여전히 Arduinos에 대해 이야기하고 있습니다. ;)
linhartr22

3
Arduino는 이미 커뮤니티가 내놓은 평범한 하드웨어 디자인으로 인해 대규모 EE 커뮤니티에서 나쁜 평판을 얻었습니다. 우리는 무언가 에 대해 sh * t를 주려고 시도해서는 안 됩니까?
이그나시오 바스케스-아 브람스

2
"대부분의 프로젝트는 생명이나 재정의 위험과 관련이 없습니다 ..." 커뮤니티를 크게 본 후 위험이있는 곳에서 Arduino를 참여 시키려는 사람 .
이그나시오 바스케스-아 브람스

2
특정 상황에서 작동하지 않기 때문에 '잘못되지 않습니다.'를 '올바르게'수행하는 것과 비교하여 작동 하지 않는 상황이 더 많기 때문 입니다. 이렇게하면 코드가 깨지기 쉽습니다. 코드를 변경하면 디버깅 시간을 소모하는 신비한 오류가 발생할 수 있습니다. 컴파일러의 유형 검사 및 오류 메시지는 나중에 이러한 오류를 미리 파악하는 데 도움이됩니다.
커트 J. 샘슨
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.