Este artículo proporciona información básica acerca de las estructuras en la programación C incrustada.
Después de introducir estructuras, echaremos un vistazo a algunas de las aplicaciones importantes de este poderoso objeto de datos. Luego, examinaremos la sintaxis del lenguaje C para declarar una estructura. Finalmente, presentaremos brevemente el requisito de alineación de datos. Veremos que podemos reducir el tamaño de una estructura simplemente reorganizando el orden de sus miembros.
Una serie de variables del mismo tipo que están relacionadas lógicamente entre sí se pueden agrupar como una matriz. Trabajar en un grupo en lugar de una colección de variables independientes nos permite organizar los datos y usarlos de manera más conveniente. Por ejemplo, podemos definir la siguiente matriz para almacenar las últimas 50 muestras de un ADC que digitaliza una entrada de voz:
voz uint16_t[50];
Tenga en cuenta que uint16_t es un tipo entero sin signo con un ancho de exactamente 16 bits. Esto se define en la biblioteca estándar de C stdint.h, que proporciona tipos de datos de una longitud de bit específica independientemente de las especificaciones del sistema.
Las matrices se pueden usar para agrupar una serie de variables que son del mismo tipo de datos. ¿Qué pasa si hay una conexión entre las variables de diferente ¿tipos de datos? ¿Podemos tratar estas variables como un grupo en nuestro programa? Por ejemplo, supongamos que necesitamos especificar la frecuencia de muestreo del ADC que genera el voz matriz arriba Podemos definir una variable flotante para almacenar la frecuencia de muestreo:
float sample_rate;
Aunque las variables voz y sample_rate Están relacionados entre sí, se definen como dos variables independientes. Para asociar estas dos variables entre sí, podemos usar una poderosa construcción de datos del lenguaje C llamada estructura. Las estructuras nos permiten agrupar diferentes tipos de datos y tratarlos como un único objeto de datos. Una estructura puede incluir diferentes tipos de tipos de variables, como otras estructuras, punteros a funciones, punteros a estructuras, etc. Para el ejemplo de voz, podemos usar la siguiente estructura:
registro de estructura {
voz uint16_t[50];
float sample_rate;
};
En este caso, tenemos una estructura llamada grabar que tiene dos miembros o campos diferentes: el primer miembro es una matriz de uint16_t Elementos, y el segundo miembro es una variable de tipo float. La sintaxis comienza con la palabra clave. estructura. La palabra después de la palabra clave struct es un nombre opcional que se usa para hacer referencia a la estructura más adelante. Discutiremos otros detalles de la definición y el uso de estructuras en el resto del artículo.
El ejemplo anterior señala una importante aplicación de estructuras, es decir, la definición de objetos de datos dependientes de la aplicación que pueden asociar variables individuales de diferentes tipos entre sí. Esto no solo conduce a una forma eficiente de manipular los datos, sino que también nos permite implementar estructuras especializadas denominadas estructuras de datos.
Las estructuras de datos se pueden usar para diversas aplicaciones, como la mensajería entre dos sistemas integrados y el almacenamiento de datos recopilados de un sensor en ubicaciones de memoria no contiguas.
Además, las estructuras son objetos de datos útiles cuando el programa necesita acceder a los registros de un periférico de microcontrolador mapeado en memoria. Vamos a echar un vistazo a las aplicaciones de estructura en el siguiente artículo.
Para usar estructuras, primero necesitamos especificar una plantilla de estructura. Considere el siguiente código de ejemplo:
registro de estructura {
voz uint16_t[4];
float sample_rate;
};
Esto especifica un diseño o plantilla para crear las futuras variables de este tipo. Esta plantilla incluye una matriz de uint16_t y una variable de tipo float. El nombre de la plantilla es grabar, y esto viene después de la palabra clave estructura. Vale la pena mencionar que no hay una asignación de memoria para almacenar una plantilla de estructura. La asignación de memoria se produce solo después de definir una variable de estructura basada en este diseño. El siguiente código declara la variable mic1 de la plantilla anterior:
struct record mic1;
Ahora, se asigna una sección de memoria para la variable. mic1. Tiene espacio para almacenar los cuatro. uint16_t Elementos de la matriz y una variable float.
Se puede acceder a los miembros de una estructura utilizando el operador miembro (.). Por ejemplo, el siguiente código asigna 100 al primer elemento de la matriz y copia el valor de sample_rate al fs Variable (que debe ser de tipo float).
mic1.voice[0]= 100;
fs = mic1.sample_rate;
Vimos una forma de declarar estructuras en la sección anterior. El lenguaje C es compatible con algunos otros formatos que se revisarán en esta sección. Probablemente te mantendrás en un formato a lo largo de tus programas, pero estar familiarizado con los otros puede ser útil a veces.
La sintaxis general para declarar la plantilla de una estructura es:
struct tag_name {
tipo_1 miembro_1;
type_2 member_2;
...
tipo_n miembro_n;
} nombre de la variable;
los nombre de etiqueta y nombre de la variable Son identificadores opcionales. Por lo general, veremos al menos uno de estos dos identificadores, pero hay casos en los que podemos eliminarlos.
Sintaxis 1: Cuando ambos nombre de etiqueta y nombre de la variable están presentes, estamos definiendo la variable de estructura justo después de la plantilla. Usando esta sintaxis, podemos reescribir el ejemplo anterior de la siguiente manera:
registro de estructura {
voz uint16_t[4];
float sample_rate;
} mic1;
Ahora, si necesitamos definir otra variable (mic2), podemos escribir
struct record mic2;
Sintaxis 2: Solamente nombre de la variable está incluido. Usando esta sintaxis, podemos reescribir el ejemplo en la sección anterior de la siguiente manera:
estructura {
voz uint16_t[4];
float sample_rate;
} mic1;
En este caso, debemos definir todas nuestras variables justo después de la plantilla y no podemos definir ninguna otra variable más adelante en nuestro programa (porque la plantilla no tiene un nombre y no podemos referirnos más adelante).
Sintaxis 3: En este caso, no hay nombre de etiqueta o nombre de la variable. Las plantillas de estructura definidas de esta manera se conocen como estructuras anónimas. Una estructura anónima se puede definir dentro de otra estructura o unión. A continuación se da un ejemplo:
prueba de estructura {
// Estructura anónima
estructura {
flotar f;
char a
};
} test_var;
Para acceder a los miembros de la estructura anónima anterior, podemos utilizar el operador miembro (.). El siguiente código asigna 1.2 al miembro F.
test_var.f = 1.2;
Como la estructura es anónima, accedemos a sus miembros utilizando el operador miembro solo una vez. Si tuviera un nombre como en el siguiente ejemplo, tendríamos que usar el operador miembro dos veces:
prueba de estructura {
estructura {
flotar f;
char a
} anidado;
} test_var;
En este caso, deberíamos usar el siguiente código para asignar 1.2 a F:
test_var.nested.f = 1.2;
Como puede ver, las estructuras anónimas pueden hacer que el código sea más legible y menos detallado. También es posible utilizar la palabra clave typedef junto con una estructura para definir un nuevo tipo de datos. Veremos este método en un artículo futuro.
El estándar C garantiza que los miembros de una estructura se ubicarán en la memoria uno tras otro en el orden en que los miembros se declararán dentro de la estructura. La dirección de memoria del primer miembro será la misma que la dirección de la propia estructura. Considere el siguiente ejemplo:
struct Test2 {
uint8_t c;
uint32_t d;
uint8_t e;
uint16_t f;
} MyStruct;
Se asignarán cuatro ubicaciones de memoria para almacenar las variables c, d, e y f. El orden de las ubicaciones de memoria coincidirá con el de declarar a los miembros: la ubicación para c tendrá la dirección más baja, luego d, e, y finalmente, f aparecerá. ¿Cuántos bytes necesitamos para almacenar esta estructura? Teniendo en cuenta el tamaño de las variables, sabemos que, al menos, se requieren 1 + 4 + 1 + 2 = 8 bytes para almacenar esta estructura. Sin embargo, si compilamos este código para una máquina de 32 bits, observaremos sorprendentemente que el tamaño de MyStruct es de 12 bytes en lugar de 8! Esto se debe al hecho de que un compilador tiene ciertas restricciones al asignar memoria a diferentes miembros de una estructura. Por ejemplo, un entero de 32 bits se puede almacenar solo en ubicaciones de memoria cuya dirección es divisible por cuatro. Tales restricciones, conocidas como requisitos de alineación de datos, se implementan para permitir que el procesador acceda a las variables de manera más eficiente. La alineación de los datos conduce a un espacio perdido (o relleno) en el diseño de la memoria. Este tema sólo se introduce aquí; Repasaremos los detalles en el siguiente artículo de esta serie.
Al estar al tanto de los requisitos de alineación de datos, es posible que podamos reorganizar el orden de los miembros dentro de una estructura y hacer que el uso de la memoria sea más eficiente. Por ejemplo, si reescribimos la estructura anterior como se indica a continuación, su tamaño disminuirá a 8 bytes en una máquina de 32 bits.
struct Test2 {
uint32_t d;
uint16_t f;
uint8_t c;
uint8_t e;
} MyStruct;
Para un sistema integrado con limitaciones de memoria, es un ahorro significativo reducir el tamaño de un objeto de datos de 12 bytes a 8 bytes, particularmente cuando un programa requiere muchos de estos objetos de datos.
El siguiente artículo discutirá la alineación de los datos con mayor detalle y examinará algunos ejemplos del uso de estructuras en sistemas integrados.
Para ver una lista completa de mis artículos, visite esta página.
ga('create', 'UA-1454132-1', 'auto'); ga('require', 'GTM-MMWSMVL'); ga('require', 'displayfeatures'); ga('set',{'dimension1':'computing,memory,embedded,embedded,engineering-consulting'}); ga('set',{'contentGroup1':'computing,memory,embedded,embedded,engineering-consulting'});
ga('set',{'dimension3':"May 01, 2019"});
ga('set',{'dimension4':"Steve Arar"});
ga('send', 'pageview');
!function(f,b,e,v,n,t,s){if(f.fbq)return;n=f.fbq=function(){n.callMethod? n.callMethod.apply(n,arguments):n.queue.push(arguments)};if(!f._fbq)f._fbq=n; n.push=n;n.loaded=!0;n.version='2.0';n.queue=[];t=b.createElement(e);t.async=!0; t.src=v;s=b.getElementsByTagName(e)[0];s.parentNode.insertBefore(t,s)}(window, document,'script','https://connect.facebook.net/en_US/fbevents.js'); fbq('init', '1808435332737507'); // Insert your pixel ID here. fbq('track', 'PageView'); fbq('track', 'ViewContent', { content_ids: ['computing','memory','embedded','embedded','engineering-consulting'], content_type: 'category'});
_linkedin_data_partner_id = "353081"; (function(){var s = document.getElementsByTagName("script")[0]; var b = document.createElement("script"); b.type = "text/javascript";b.async = true; b.src = "https://snap.licdn.com/li.lms-analytics/insight.min.js"; s.parentNode.insertBefore(b, s);})(); } if(jstz.determine().name().indexOf("Europe") === -1) { showSocialCode(); // NOT EU } else { showSocialCode(); window.addEventListener("load", function () { window.cookieconsent.initialise({ "palette": { "popup": { "background": "#252e39" }, "button": { "background": "#14a7d0" } }, "type": "opt-out", "content": { "message": "This website uses tracking cookies to ensure you get the best experience on our website.", "href": "https://www.allaboutcircuits.com/privacy-policy/", "dismiss": "OK, GOT IT" }, onInitialise: function (status) { var type = this.options.type; var didConsent = this.hasConsented(); if (type == 'opt-out' && didConsent) { console.log("eu"); //showSocialCode(); } },
onStatusChange: function (status, chosenBefore) { var type = this.options.type; var didConsent = this.hasConsented(); if (type == 'opt-out' && didConsent) { console.log("eu"); //showSocialCode(); } },
onRevokeChoice: function () { var type = this.options.type; if (type == 'opt-out') { console.log("eu"); //showSocialCode(); } },
}) }); }
Los días felices de la PDA y Blackberry han quedado definitivamente atrás, pero el factor…
Tutorial sobre cómo pronosticar usando un modelo autorregresivo en PythonFoto de Aron Visuals en UnsplashForecasting…
Si tienes un iPhone, los AirPods Pro son la opción obvia para escuchar música, ¡aunque…
Ilustración de Alex Castro / The Verge Plus nuevos rumores sobre el quinto Galaxy Fold.…
Se rumorea que los auriculares premium de próxima generación de Apple, los AirPods Max 2,…
El desarrollador Motive Studio y el editor EA han lanzado un nuevo tráiler de la…