Languages/C/SplitCH

(Difference between revisions)
Jump to: navigation, search
(Source and header file split)
Line 14: Line 14:
 
* (6) The header SHOULD be commented enough so there is no need to open the source file.
 
* (6) The header SHOULD be commented enough so there is no need to open the source file.
 
* (7) The source file MUST include the header, preferably first
 
* (7) The source file MUST include the header, preferably first
** This will ensure consistency
+
** This will ensure consistency and (4)
 
* (8) All symbols not exported by the header SHOULD be static (functions and variables)
 
* (8) All symbols not exported by the header SHOULD be static (functions and variables)
 
** Do not pollute the linker namespace
 
** Do not pollute the linker namespace

Revision as of 12:34, 16 October 2014

Contents

Source and header file split

The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in this document are to be interpreted as deescribed in RFC 2119.

It is sometimes complicated to split the header and the source file, here are some hints:

  • (1) The header MUST contain what is necessary from the outside of the source file.
  • (2) The header SHOULD NOT contain, what is not necessary.
    • There is no reason to pollute the namespace of the whole project.
    • Keeping the interface small and as clean as possible will make team work simpler.
  • (3) The header file MUST prevent multiple inclusion
  • (4) A header file SHOULD be complete (it defines or includes all it needs).
    • Example, if you use a uint32_t parameter in a function, the header should include <stdint.h>
  • (5) A header file SHOULD not include files only used in source file
  • (6) The header SHOULD be commented enough so there is no need to open the source file.
  • (7) The source file MUST include the header, preferably first
    • This will ensure consistency and (4)
  • (8) All symbols not exported by the header SHOULD be static (functions and variables)
    • Do not pollute the linker namespace
    • Free benefit: the compiler can do better optimization (automatic inline, ...)

Temperature sensor example

Here is a small example, using main.c, temp_sensor.h, and temp_sensor.c

main.c

#include <stdio.h>
#include "temp_sensor.h"
 
int main(int argc, char *argv[])
{
	return printf("temperature is : %d", temp_sensor_get());
}

temp_sensor.h

/**
 * \file temp_sensor.h
 *
 * \brief Temperature sensor driver
 */
#ifndef TEMP_SENSOR_H // (3) prevent multiple inclusion, see the #endif at the end
#define TEMP_SENSOR_H
 
#include <stdint.h> // (4) We use stdint in the interface !
 
// (6) Full comments, no need to open temp_sensor.c
// (1) This function is needed in main
/**
 * \brief Get the temperature
 *
 * \return the temperature in K.
 *
 * \warning the value will be 0 if the sensor read fails.
 */
uint16_t temp_sensor_get(void);
 
#endif /* TEMP_SENSOR_H */

temp_sensor.c

/**
 * \file temp_sensor.c
 *
 * \brief Temperature sensor driver implementation
 */
 
#include "temp_sensor.h" // (7) Include the header for compile-time checks
#include <super_os/i2c.h> // (2) The i2c bus is not used in main
 
// (2) These defines are private, we don't want to see them in main
#define SENSOR_ADDRESS 0x12
#define SENSOR_REG 0x33
 
// (8) this function is not exported -> static
// (6) this function MUST be commented here
/**
 * \brief Do the real work here
 * \param chip, the i2c address of the chip
 * \param address, the address in the chip
 * \param value, where to store the value
 * \return 0 for no problem
 */
static uint8_t read(uint8_t chip, uint8_t address, uint16_t *value)
{
	if (i2c_read(chip, address, value, 2) != 0)
	{
		return 0;
	}
 
	return 1;
}
 
// (6) This function is already commented in the header
uint16_t temp_sensor_get(void)
{
	uint16_t temp;
	uint8_t status = read(SENSOR_ADDRESS, SENSOR_REG, &temp);
 
	// Do what is said in temp_sensor.h
	if (status)
	{
		temp = 0;
	}
 
	return temp;
}
Personal tools
Namespaces
Variants
Actions
Navigation
Browse
Toolbox