C programming notes

From Wiki at Neela Nurseries
Revision as of 20:41, 12 April 2024 by Ted (talk | contribs) (Add section "Printf Family Functions".)
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

^ C Qualifiers and Type Casting


^ 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:


^ 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


^ 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).


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

^ 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: