Here is a proposed canonical structure for functions/procedures.  Clearly in some cases some sections would not be present.  What’s important is to understand the basic phasing of the work to be done and the separation of tasks.

 

int foo(

     char *StringIn, // “in” parameter

     size_t BufferLength, // “in” parameter

     char Buffer[], // “out” parameter, max length governed by BufferLength

     size_t *CharsWritten // “out” parameter, must be <= BufferLength

     ) {

     // Phase 1: Initialize out parameters

     *CharsWritten = 0;

 

     // Phase 2: Capture and validate parameters

     const size_t StringInLength = strlen(StringIn);

     if ((BufferLength != 0) && (Buffer == NULL))

return ERR_INVALID_PARAMETER;

 

     // Phase 3: do work

if (BufferLength <= StringInLength)

     return ERR_BUFFER_TOO_SMALL;

     memcpy(Buffer, StringIn, StringInLength);

     Buffer[StringInLength] = ‘\0’;

 

     // Phase 4: copy data out

     *CharsWritten = StringInLength + 1; // safe because BufferLength is > StringInLength so “+1” won’t overflow

 

     // Phase 5: goodbye

     return ERR_SUCCEEDED;

}

 

There may be other phases and the example’s perhaps kind of dumb but I think it works well to call out what kinds of operations should happen in which phases and even more so what doesn’t have to happen later on given work that occurred earlier.