산업 제조
산업용 사물 인터넷 | 산업자재 | 장비 유지 보수 및 수리 | 산업 프로그래밍 |
home  MfgRobots >> 산업 제조 >  >> Industrial Internet of Things >> 임베디드

임베디드 C 이해:구조란?

구조를 소개한 후 이 강력한 데이터 개체의 몇 가지 중요한 응용 프로그램을 살펴보겠습니다. 그런 다음 C 언어 구문을 조사하여 구조를 선언합니다. 마지막으로 데이터 정렬 요구 사항을 간략하게 소개합니다. 단순히 멤버의 순서를 재배열하여 구조체의 크기를 줄일 수 있음을 알 수 있습니다.

이 기사는 임베디드 C 프로그래밍의 구조에 대한 몇 가지 기본 정보를 제공합니다.

구조를 소개한 후 이 강력한 데이터 개체의 몇 가지 중요한 응용 프로그램을 살펴보겠습니다. 그런 다음 C 언어 구문을 조사하여 구조를 선언합니다. 마지막으로 데이터 정렬 요구 사항을 간략하게 소개합니다. 단순히 멤버의 순서를 재배열하여 구조체의 크기를 줄일 수 있음을 알 수 있습니다.

구조

서로 논리적으로 관련된 동일한 유형의 여러 변수를 배열로 그룹화할 수 있습니다. 독립변수의 집합이 아닌 그룹으로 작업하면 데이터를 정리하고 더 편리하게 사용할 수 있습니다. 예를 들어 음성 입력을 디지털화하는 ADC의 마지막 50개 샘플을 저장하기 위해 다음 배열을 정의할 수 있습니다.

uint16_t 음성[50]; 

uint16_t 너비가 정확히 16비트인 부호 없는 정수 유형입니다. 이것은 C 표준 라이브러리 stdint.h에 정의되어 있습니다. , 시스템 사양에 관계없이 특정 비트 길이의 데이터 유형을 제공합니다.

배열을 사용하여 데이터 유형이 동일한 여러 변수를 그룹화할 수 있습니다. 다른 변수 사이에 연결이 있는 경우 데이터 유형? 우리 프로그램에서 이러한 변수를 그룹으로 처리할 수 있습니까? 예를 들어, 음성을 생성하는 ADC의 샘플링 속도를 지정해야 한다고 가정합니다. 위의 배열. 샘플 레이트를 저장하기 위해 float 변수를 정의할 수 있습니다:

float sample_rate; 

변수가 음성 sample_rate 서로 관련이 있으므로 두 개의 독립 변수로 정의됩니다. 이 두 변수를 서로 연결하기 위해 구조라고 하는 C 언어의 강력한 데이터 구성을 사용할 수 있습니다. 구조를 사용하면 서로 다른 데이터 유형을 그룹화하고 단일 데이터 개체로 처리할 수 있습니다. 구조는 다른 구조, 함수에 대한 포인터, 구조에 대한 포인터 등과 같은 다양한 종류의 변수 유형을 포함할 수 있습니다. 음성 예제의 경우 다음 구조를 사용할 수 있습니다.

구조체 레코드 { uint16_t 음성[50]; float sample_rate;}; 

이 경우 레코드라는 구조가 있습니다. 두 개의 서로 다른 멤버 또는 필드가 있습니다. 첫 번째 멤버는 uint16_t 배열입니다. 요소이고 두 번째 멤버는 float 유형의 변수입니다. 구문은 struct 키워드로 시작합니다. . struct 키워드 뒤의 단어는 나중에 구조를 참조하는 데 사용되는 선택적 이름입니다. 이 기사의 나머지 부분에서 구조 정의 및 사용에 대한 다른 세부사항을 논의할 것입니다.

구조가 왜 중요한가요?

위의 예는 구조의 중요한 적용, 즉 서로 다른 유형의 개별 변수를 연결할 수 있는 애플리케이션 종속 데이터 개체를 정의하는 것을 지적합니다. 이를 통해 데이터를 효율적으로 조작할 수 있을 뿐만 아니라 데이터 구조라고 하는 특수 구조를 구현할 수도 있습니다.

데이터 구조는 두 임베디드 시스템 간의 메시징 및 센서에서 수집한 데이터를 비연속 메모리 위치에 저장하는 것과 같은 다양한 애플리케이션에 사용할 수 있습니다.

그림 1. 구조를 사용하여 연결 목록을 구현할 수 있습니다.

또한 구조는 프로그램이 메모리 매핑된 마이크로 컨트롤러 주변 장치의 레지스터에 액세스해야 할 때 유용한 데이터 개체입니다. 다음 기사에서 구조 응용 프로그램을 살펴보겠습니다.

그림 2. STM32 MCU의 메모리 맵. ARM이 포함된 임베디드 시스템의 이미지 제공

구조 선언

구조를 사용하려면 먼저 구조 템플릿을 지정해야 합니다. 아래 예제 코드를 고려하십시오.

구조체 레코드 { uint16_t 음성[4]; float sample_rate;}; 

이것은 이 유형의 미래 변수를 생성하기 위한 레이아웃 또는 템플릿을 지정합니다. 이 템플릿에는 uint16_t 배열이 포함됩니다. 그리고 float 유형의 변수. 템플릿 이름은 레코드입니다. , 키워드 struct 뒤에 옵니다. . 구조 템플릿을 저장하기 위한 메모리 할당이 없다는 점을 언급할 가치가 있습니다. 메모리 할당은 이 레이아웃을 기반으로 하는 구조 변수가 정의된 후에만 발생합니다. 다음 코드는 mic1 변수를 선언합니다. 위 템플릿:

구조체 레코드 mic1; 

이제 메모리 섹션이 mic1 변수에 할당됩니다. . 4개의 uint16_t를 저장할 공간이 있습니다. 배열의 요소와 하나의 부동 변수.

구조체의 멤버는 멤버 연산자(.)를 사용하여 액세스할 수 있습니다. 예를 들어 다음 코드는 배열의 첫 번째 요소에 100을 할당하고 sample_rate 값을 복사합니다. fs 변수(float 유형이어야 함).

mic1.voice[0]=100;fs=mic1.sample_rate; 

구조를 선언하는 다른 방법

이전 섹션에서 구조체를 선언하는 한 가지 방법을 살펴보았습니다. C 언어는 이 섹션에서 검토할 몇 가지 다른 형식을 지원합니다. 프로그램 전반에 걸쳐 한 가지 형식을 고수할 것이지만 다른 형식에 익숙해지면 때때로 도움이 될 수 있습니다.

구조의 템플릿을 선언하는 일반적인 구문은 다음과 같습니다.

구조체 tag_name { type_1 member_1; 유형_2 구성원_2; … type_n member_n;} variable_name; 

tag_name 변수 이름 선택적 식별자입니다. 일반적으로 이 두 식별자 중 하나 이상을 볼 수 있지만 두 식별자를 모두 제거할 수 있는 경우도 있습니다.

구문 1: 둘 다 tag_name일 때 변수 이름 존재하는 경우 템플릿 바로 뒤에 구조 변수를 정의하고 있습니다. 이 구문을 사용하여 이전 예제를 다음과 같이 다시 작성할 수 있습니다.

구조체 레코드 { uint16_t 음성[4]; float sample_rate;} mic1; 

이제 다른 변수(mic2 ), 우리는 쓸 수 있습니다

구조체 레코드 mic2; 

구문 2: 변수 이름 포함되어 있습니다. 이 구문을 사용하여 이전 섹션의 예를 다음과 같이 다시 작성할 수 있습니다.

struct { uint16_t 음성[4]; float sample_rate;} mic1; 

이 경우 템플릿 바로 뒤에 모든 변수를 정의해야 하며 나중에 프로그램에서 다른 변수를 정의할 수 없습니다(템플릿에 이름이 없고 나중에 참조할 수 없기 때문입니다).

구문 3: 이 경우 tag_name이 없습니다. 또는 변수 이름 . 이러한 방식으로 정의된 구조 템플릿을 익명 구조라고 합니다. 익명 구조는 다른 구조 또는 공용체 내에서 정의할 수 있습니다. 아래에 예가 나와 있습니다.

struct test { // 익명 구조체 struct { float f; 문자 a; };} test_var; 

위의 익명 구조의 멤버에 액세스하려면 멤버 연산자(.)를 사용할 수 있습니다. 다음 코드는 f 구성원에게 1.2를 할당합니다. .

test_var.f=1.2; 

구조가 익명이므로 멤버 연산자를 한 번만 사용하여 해당 멤버에 액세스합니다. 다음 예와 같이 이름이 있는 경우 멤버 연산자를 두 번 사용해야 합니다.

struct test { struct { float f; 문자 a; } 중첩;} test_var; 

이 경우 다음 코드를 사용하여 f에 1.2를 할당해야 합니다. :

test_var.nested.f=1.2; 

보시다시피 익명 구조는 코드를 더 읽기 쉽고 장황하게 만들 수 있습니다. typedef 키워드를 구조와 함께 사용하여 새 데이터 유형을 정의하는 것도 가능합니다. 이 방법은 다음 기사에서 살펴보겠습니다.

구조물의 메모리 레이아웃

C 표준은 구조체의 멤버가 구조체 내에서 선언된 멤버 순서대로 메모리에 하나씩 위치하도록 보장합니다. 첫 번째 멤버의 메모리 주소는 구조체 자체의 주소와 동일합니다. 다음 예를 고려하십시오.

구조체 Test2{ uint8_t c; uint32_t d; uint8_t e; uint16_t f;} MyStruct; 

변수 c, d, e 및 f를 저장하기 위해 4개의 메모리 위치가 할당됩니다. 메모리 위치의 순서는 멤버를 선언하는 순서와 일치합니다. c의 위치는 가장 낮은 주소를 가지며 d, e, 마지막으로 f가 나타납니다. 이 구조를 저장하려면 몇 바이트가 필요합니까? 변수의 크기를 고려할 때 이 구조를 저장하려면 최소한 1+4+1+2=8 바이트가 필요하다는 것을 알고 있습니다. 그러나 32비트 시스템용으로 이 코드를 컴파일하면 놀랍게도 MyStruct 크기가 8이 아닌 12바이트입니다! 이는 컴파일러가 구조체의 다른 멤버에 메모리를 할당할 때 특정 제약 조건이 있기 때문입니다. 예를 들어, 32비트 정수는 주소가 4로 나눌 수 있는 메모리 위치에만 저장할 수 있습니다. 데이터 정렬 요구 사항이라고 하는 이러한 제약 조건은 프로세서가 변수에 보다 효율적으로 액세스할 수 있도록 구현됩니다. 데이터 정렬은 메모리 레이아웃에서 낭비되는 공간(또는 패딩)으로 이어집니다. 이 주제는 여기에서만 소개됩니다. 이 시리즈의 다음 기사에서 자세한 내용을 살펴보겠습니다.

그림 3. 데이터 정렬로 인해 메모리 레이아웃에서 일부 공간(또는 패딩)이 낭비됩니다.

데이터 정렬 요구 사항을 알고 있으면 구조 내에서 멤버의 순서를 재정렬하고 메모리 사용을 보다 효율적으로 만들 수 있습니다. 예를 들어 위의 구조를 아래와 같이 다시 작성하면 32비트 시스템에서는 크기가 8바이트로 줄어듭니다.

구조체 Test2{ uint32_t d; uint16_t f; uint8_t c; uint8_t e;} MyStruct; 

메모리가 제한된 임베디드 시스템의 경우 특히 프로그램에 이러한 데이터 개체가 많이 필요한 경우 데이터 개체의 크기를 12바이트에서 8바이트로 줄이는 것이 상당한 비용 절감 효과가 있습니다.

다음 기사에서는 데이터 정렬에 대해 더 자세히 논의하고 임베디드 시스템에서 구조를 사용하는 몇 가지 예를 검토할 것입니다.

요약

<울>
  • 구조를 사용하면 서로 다른 유형의 개별 변수를 연결할 수 있는 애플리케이션 종속 데이터 개체를 정의할 수 있습니다. 이를 통해 데이터를 효율적으로 조작할 수 있습니다.
  • 데이터 구조라고 하는 특수 구조는 두 임베디드 시스템 간의 메시징, 센서에서 수집한 데이터를 비연속 메모리 위치에 저장하는 등 다양한 애플리케이션에 사용할 수 있습니다.
  • 구조는 메모리 매핑된 마이크로컨트롤러 주변기기의 레지스터에 액세스해야 할 때 유용합니다.
  • 구조 내에서 멤버의 순서를 재정렬하여 메모리 사용을 보다 효율적으로 만들 수 있습니다.
  • 내 기사의 전체 목록을 보려면 이 페이지를 방문하십시오.


    임베디드

    1. 내화 금속이란 무엇입니까?
    2. 데크 나사 란 무엇입니까?
    3. 스프링 에너자이즈드 씰이란?
    4. 나무 나사란 무엇입니까?
    5. 강 합금이란 무엇입니까?
    6. 데이터로 무엇을 해야 합니까?!
    7. 자바 - 데이터 구조
    8. IIoT란 무엇입니까?
    9. 유지보수 데이터란 무엇입니까?
    10. 목공의 이해