C programming notes

From Wiki at Neela Nurseries
Revision as of 23:39, 12 July 2024 by Ted (talk | contribs) (Add link to Blackberry / QNX online documentation on errno codes.)
Jump to: navigation, search

programming notes   ::   coding style

^ Overview

This page to hold notes and links to C programming resources and reference materials. A language standards document is available at https://www.open-std.org/jtc1/sc22/WG14/www/docs/n1256.pdf.

A good tool to aid writing C code is the indexing utility known as `ctags`:


^ Data Type and Limits

See the following C library headers for important data type definitions, such as the definition of `uint32_t` and CHAR_BIT.

  • zephyr/lib/libc/minimal/include/stdint.h
  • zephyr/lib/libc/minimal/include/limits.h

Two important C data types worth noting include size_t and ssize_t. These are unsigned, and signed types respectively.

The signed type of these two allows for a variable to hold both positive values and negative values, which is useful when variables are changed during function calls. This signed-ness permits a function to return a valid value, and also an error code which may be encoded in the negative range of integer values.

^ C pointer and file size types

From Madagascar Programming Reference Manual, first a link to this documentation's node 44:

Node 43 and node 1 respectively:


^ C Qualifiers and Type Casting


^ C structures

C structures can be referenced using differing syntax. To do: investigate and test following psuedo-code . . .

struct a {
   char element_a;
   size_t element_b;
};

struct a structure_a_1;

structure_a_1.element_a = 'M';
structure_a_1.element_b = 100;

printf("Test:  %c, %u\n", structure_a_1.element_a, structure_a_1.element_b);

// Note may need a C cast following assignment operator in next line:

structure_a_1 = {
   .structure_a_1.element_a = 'L';
   .structure_a_1.element_b = 8585;
}

printf("Test:  %c, %u\n", structure_a_1.element_a, structure_a_1.element_b);


^ C Macros

This section likely to grow as C macros have a development history somewhat separate from the development of C language itself, and extensive use being both powerful and prone to pitfalls.

Articles on the use of C language 'do while(0)' construct in macros. The do while(0) construct is the only C syntax which expands correctly from C macros regardless of the use of curly braces and semicolons around the given macro.

A useful macro pair, and this must be a macro pair, is the following set of defines. These defines will accept a string and put double quotes around it:

  #define MAKE_STRING_QUOTED(string) #string
  #define WRAPPER_NEEDED_TO_QUOTE_STRING(token) MAKE_STRING_QUOTED(string)

One Guy Rutenberg explains this C pre-processor pattern:

This C macro pattern is explained a number of other places as well.


The `__fallthrough()` macro appears to be a C++ macro. It may be found among Zephyr RTOS 3.4.0 source tree contents. An article on the concept of "fall through" in C switch statements:


^ C Pointers and dereference syntax

This section the beginning of references, links and personal notes on some of the most difficult and important C language constructs, often used in schedulers and RTOS implementations:

Arrays of strings and arrays of pointers to strings:


  - - - - -   - - - - -   - - - - -   - - - - -   - - - - -   - - - - -   - - - - -   - - - - -   - - - - -   - - - - -

^ Printf Family Functions

C functions printf, snprintf and vprintf and related make use of variadic function signatures. That is, these functions accepts arbitrary arguments which they do not know at compile time. Useful infomation on C library's variadic function macros and C standard argument `stdarg.h` framework can be found via manual pages:

    $ man 3 printf
    $ man 3 stdarg

Related to this, Zephyr RTOS printk header [file https://docs.zephyrproject.org/apidoc/latest/printk_8h_source.html printk.h] calls on a macro named __printf_like(a, b).

More about C standard library variadic function support can be learned via `main va_start`.


^ Co-routines

Interesting article by Simon Tatham on co-routines and a couple ways of implementing them in C language; accessible good style of writing:

Quote from the article:

    <! -- not intended use for ul tag --> "Any coding standard which insists on syntactic clarity at the expense of algorithmic clarity should be rewritten."  - Simon Tatham


^ Errno dot h

Error codes for Unix and Linux operating systems, and C library based projects such as RTOS Zephyr are often defined in a header file named errno.h. Versions of this file from system to system and environment to environment often vary, leading to compatibility issues. This section a starting point to address benefits and challenges, and hopefully some answers on the challenge side of using errno.h for project error codes.

Interesting, as of 2024-07-12 a few websites are still made public via non-secure http protocol. Link to Blackberry / QNX online documentation on errno codes:


  - - - - -   - - - - -   - - - - -   - - - - -   - - - - -   - - - - -   - - - - -   - - - - -   - - - - -   - - - - -

^ Simple C examples

Program 1 - use of C comma operator, a binary operator:

#include <stdio.h>
#include <stdlib.h>

// Compile with:
//
//    $ gcc -Wall main.c
//
// As of 2022-06-09 Builds with 'gcc (Ubuntu 9.4.0-1ubuntu1~20.04.1) 9.4.0'

int main(int argc, char *argv[])
{
    int z = 3;

    int y[(z++, (z + 1))];

    y[0] = 1;

    if ( z == y[0] ) { } 

#define SIZE_OF_160_BYTES (160)
    char lbuf[SIZE_OF_160_BYTES] = { 0 };
    snprintf(lbuf, SIZE_OF_160_BYTES, "2022-06-09 main.c test of C comma operator\narray y[] has size of %lu\n",
      sizeof(y));
    printf("%s", lbuf);

    return 0;
}

^ Serial Port Use in C

// Example 3.2 code from https://tldp.org/HOWTO/Serial-Programming-HOWTO/x115.html

#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <termios.h>
#include <stdio.h>

#include <stdlib.h>                //echo "z" >> /dev/ttyS1 to provide exit()

// https://man7.org/linux/man-pages/man3/bzero.3.html
#include <strings.h>               // to provide bzero()

// https://man7.org/linux/man-pages/man2/read.2.html
// https://linux.die.net/man/3/read
#include <unistd.h>                // to provide read()


    
#define BAUDRATE B38400
//#define MODEMDEVICE "/dev/ttyS1"
#define MODEMDEVICE "/dev/ttyUSB0"
#define _POSIX_SOURCE 1 /* POSIX compliant source */
#define FALSE 0
#define TRUE 1
    
volatile int STOP=FALSE; 
    
int main(void)
{
        int fd, c, res;
        struct termios oldtio,newtio;
        char buf[255];
    
    printf("Starting,\nopening serial device '%s' . . .\n", MODEMDEVICE);

        fd = open(MODEMDEVICE, O_RDWR | O_NOCTTY );  
        if (fd <0) {perror(MODEMDEVICE); exit(-1); }

        tcgetattr(fd,&oldtio); /* save current port settings */

        bzero(&newtio, sizeof(newtio));
//        newtio.c_cflag = BAUDRATE | CRTSCTS | CS8 | CLOCAL | CREAD;
        newtio.c_cflag = BAUDRATE | CS8 | CLOCAL | CREAD;
        newtio.c_iflag = IGNPAR;
        newtio.c_oflag = 0;

        /* set input mode (non-canonical, no echo,...) */
        newtio.c_lflag = 0;

        newtio.c_cc[VTIME]    = 0;   /* inter-character timer unused */
        newtio.c_cc[VMIN]     = 5;   /* blocking read until 5 chars received */

        tcflush(fd, TCIFLUSH);
        tcsetattr(fd,TCSANOW,&newtio);


    printf("looping to read from serial port . . .\n");
        while (STOP==FALSE) {       /* loop for input */
          res = read(fd,buf,255);   /* returns after 5 chars have been input */
          buf[res]=0;               /* so we can printf... */
          printf(":%s:%d\n", buf, res);
          if (buf[0]=='z') STOP=TRUE;
        }
        tcsetattr(fd,TCSANOW,&oldtio);

    return 0;
}


  - - - - -   - - - - -   - - - - -   - - - - -   - - - - -   - - - - -   - - - - -   - - - - -   - - - - -   - - - - -

^ References


Floating point convert and notes on-line, Javascript converter: