title: Is concatenating arbitrary number of strings with nested function calls in C undefined behavior?
body: <p>I have an application that builds file path names through a series of string concatenations using pieces of text to create a complete file path name.</p>
  
  <p>The question is whether an approach to handle concatenating a small but arbitrary number of strings of text together depends on <em>Undefined Behavior</em> for success.</p>
  
  <p>Is the order of evaluation of a series of nested functions guaranteed or not?</p>
  
  <p>I found this question <a href="https://stackoverflow.com/questions/833882/nested-function-calls-order-of-evaluation">Nested function calls order of evaluation</a> however it seems to be more about multiple functions in the argument list rather than a sequence of nesting functions.</p>
  
  <p>Please excuse the names in the following code samples. It is congruent with the rest of the source code and I am testing things out a bit first.</p>
  
  <p>My first cut on the need to concatenate several strings was a function that looked like the following which would concatenate up to three text strings into a single string.</p>
  
  <pre><code>typedef wchar_t TCHAR;
  
  TCHAR *RflCatFilePath(TCHAR *tszDest, int nDestLen, TCHAR *tszPath, TCHAR *tszPath2, TCHAR *tszFileName)
  {
      if (tszDest &amp;&amp; nDestLen &gt; 0) {
          TCHAR *pDest = tszDest;
          TCHAR *pLast = tszDest;
  
          *pDest = 0;   // ensure empty string if no path data provided.
  
          if (tszPath) for (pDest = pLast; nDestLen &gt; 0 &amp;&amp; (*pDest++ = *tszPath++); nDestLen--) pLast = pDest;
          if (tszPath2) for (pDest = pLast; nDestLen &gt; 0 &amp;&amp; (*pDest++ = *tszPath2++); nDestLen--)  pLast = pDest;
          if (tszFileName) for (pDest = pLast; nDestLen &gt; 0 &amp;&amp; (*pDest++ = *tszFileName++); nDestLen--)  pLast = pDest;
      }
  
      return tszDest;
  }
  </code></pre>
  
  <p>Then I ran into a case where I had four pieces of text to put together.</p>
  
  <p>Thinking through this it seemed that most probably there would also be a case for five that would be uncovered shortly so I wondered if there was a different way for an arbitrary number of strings.</p>
  
  <p>What I came up with is two functions as follows.</p>
  
  <pre><code>typedef wchar_t TCHAR;
  
  typedef struct {
      TCHAR *pDest;
      TCHAR *pLast;
      int    destLen;
  } RflCatStruct;
  
  RflCatStruct RflCatFilePathX(const TCHAR *pPath, RflCatStruct x)
  {
      TCHAR *pDest = x.pLast;
      if (pDest &amp;&amp; pPath) for ( ; x.destLen &gt; 0 &amp;&amp; (*pDest++ = *pPath++); x.destLen--)  x.pLast = pDest;
      return x;
  }
  
  RflCatStruct RflCatFilePathY(TCHAR *buffDest, int nLen, const TCHAR *pPath)
  {
      RflCatStruct  x = { 0 };
  
      TCHAR *pDest = x.pDest = buffDest;
      x.pLast = buffDest;
      x.destLen = nLen;
  
      if (buffDest &amp;&amp; nLen &gt; 0) {   // ensure there is room for at least one character.
          *pDest = 0;   // ensure empty string if no path data provided.
          if (pPath) for (pDest = x.pLast; x.destLen &gt; 0 &amp;&amp; (*pDest++ = *pPath++); x.destLen--)  x.pLast = pDest;
      }
      return x;
  }
  </code></pre>
  
  <p>Examples of using these two functions is as follows.  This code with the two functions appears to work fine with Visual Studio 2013.</p>
  
  <pre><code>TCHAR buffDest[512] = { 0 };
  TCHAR *pPath = L"C:\\flashdisk\\ncr\\database";
  TCHAR *pPath2 = L"\\";
  TCHAR *pFilename = L"filename.ext";
  
  RflCatFilePathX(pFilename, RflCatFilePathX(pPath2, RflCatFilePathY(buffDest, 512, pPath)));
  printf("dest t = \"%S\"\n", buffDest);
  
  
  printf("dest t = \"%S\"\n", RflCatFilePathX(pFilename, RflCatFilePathX(pPath2, RflCatFilePathY(buffDest, 512, pFilename))).pDest);
  
  
  RflCatStruct  dStr = RflCatFilePathX(pPath2, RflCatFilePathY(buffDest, 512, pPath));
  //   other stuff then
  printf("dest t = \"%S\"\n", RflCatFilePathX(pFilename, dStr).pDest);
  </code></pre>