<?xml version="1.0" encoding="UTF-8"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
    <title></title>
    <link href="https://nost15459.net/atom.xml" rel="self" type="application/atom+xml"/>
    <link href="https://nost15459.net"/>
    <generator uri="https://www.getzola.org/">Zola</generator>
    <updated>2023-08-04T00:00:00+00:00</updated>
    <id>https://nost15459.net/atom.xml</id>
    <entry xml:lang="en">
        <title>C標準でasprintfを実装する</title>
        <published>2023-08-04T00:00:00+00:00</published>
        <updated>2023-08-04T00:00:00+00:00</updated>
        <author>
          <name>Unknown</name>
        </author>
        <link rel="alternate" href="https://nost15459.net/blog/stdc-asprintf/" type="text/html"/>
        <id>https://nost15459.net/blog/stdc-asprintf/</id>
        
        <content type="html">&lt;h2 id=&quot;asprintf_って何ぞや&quot;&gt;&lt;code&gt;asprintf&lt;&#x2F;code&gt; って何ぞや&lt;a class=&quot;anchor&quot; aria-hidden=&quot;true&quot; href=&quot;#asprintf_って何ぞや&quot; hidden=&quot;&quot;&gt;#&lt;&#x2F;a&gt;
&lt;&#x2F;h2&gt;
&lt;p&gt;man asprintfより一部を引用&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;code&gt;int asprintf(char **strp, const char *fmt, ...);&lt;&#x2F;code&gt;&lt;&#x2F;p&gt;
&lt;p&gt;The functions &lt;code&gt;asprintf()&lt;&#x2F;code&gt; and &lt;code&gt;vasprintf()&lt;&#x2F;code&gt; are analogs of &lt;code&gt;sprintf(3)&lt;&#x2F;code&gt; and &lt;code&gt;vsprintf(3)&lt;&#x2F;code&gt;, except that they allocate a string large enough to hold the output including the terminating null byte (&#x27;\0&#x27;), and return a pointer to it via the first argument. This pointer should be passed to &lt;code&gt;free(3)&lt;&#x2F;code&gt; to release the allocated storage when it is no longer needed.&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;まあつまり、&lt;code&gt;sprintf&lt;&#x2F;code&gt; やら &lt;code&gt;snprintf&lt;&#x2F;code&gt; やらだとこちら側でよしなにバッファを確保してやる必要があるところを、関数側が勝手に確保してくれるといった感じだ。これによって &lt;code&gt;snprintf&lt;&#x2F;code&gt; で &lt;code&gt;n&lt;&#x2F;code&gt; が十分に大きくなく、出力内容が切り捨てられたり、あるいは &lt;code&gt;sprintf&lt;&#x2F;code&gt; でバッファオーバーランが発生、なんて事だ、もう助からないゾ♡みたいなことにはならないというわけだ。&lt;&#x2F;p&gt;
&lt;p&gt;しかし、こいつには一つ問題がある。それはこいつがGNU拡張であるということだ。C標準やPOSIXにはこいつはいない。そこで、こいつをC標準(C99)の範囲で実装していこうのコーナーです。&lt;&#x2F;p&gt;
&lt;h2 id=&quot;実装する&quot;&gt;実装する&lt;a class=&quot;anchor&quot; aria-hidden=&quot;true&quot; href=&quot;#実装する&quot; hidden=&quot;&quot;&gt;#&lt;&#x2F;a&gt;
&lt;&#x2F;h2&gt;
&lt;p&gt;さて、 &lt;code&gt;asprintf&lt;&#x2F;code&gt; の肝は出力文字列を格納するメモリを勝手に確保してくれるところである。逆に、その他は単に &lt;code&gt;vsnprintf&lt;&#x2F;code&gt; や &lt;code&gt;malloc&lt;&#x2F;code&gt; に投げつければ終わる仕事だ。&lt;&#x2F;p&gt;
&lt;p&gt;しかし、出力文字列を書き込むメモリを確保するためにはフォーマット結果の文字数を知る必要がある。これには &lt;code&gt;snprintf&lt;&#x2F;code&gt; (実際に使うのは &lt;code&gt;vsnprintf&lt;&#x2F;code&gt; であるが、引数の渡し方の違いでしかないので真にそこは引っかからなくていい)を使う。実は &lt;code&gt;snprintf&lt;&#x2F;code&gt; は &lt;code&gt;n&lt;&#x2F;code&gt; を &lt;code&gt;0&lt;&#x2F;code&gt; にして呼ぶと &lt;code&gt;s&lt;&#x2F;code&gt; に何も書き込まないうえに、&lt;code&gt;s&lt;&#x2F;code&gt; はヌルポインタで良い。そして、 &lt;code&gt;snprintf&lt;&#x2F;code&gt; は &lt;code&gt;n&lt;&#x2F;code&gt; が十分大きかった場合に書き込まれるはずだった文字数、つまり、フォーマットされた後の文字数を返す

&lt;sup class=&quot;footnote-reference&quot; id=&quot;fnref:1&quot;&gt;&lt;a href=&quot;#fndef:1&quot;&gt;1&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;
。&lt;&#x2F;p&gt;
&lt;p&gt;C99(N1256) 7.19.6.5 The snprintf functionより一部を引用&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;code&gt;int snprintf(char * restrict s, size_t n, const char * restrict format, ...);&lt;&#x2F;code&gt;&lt;&#x2F;p&gt;
&lt;p&gt;The &lt;code&gt;snprintf&lt;&#x2F;code&gt; function is equivalent to &lt;code&gt;fprintf&lt;&#x2F;code&gt;, except that the output is written into an array (specified by argument &lt;code&gt;s&lt;&#x2F;code&gt;) rather than to a stream. If &lt;code&gt;n&lt;&#x2F;code&gt; is zero, nothing is written, and &lt;code&gt;s&lt;&#x2F;code&gt; may be a null pointer. (snip)&lt;&#x2F;p&gt;
&lt;p&gt;The &lt;code&gt;snprintf&lt;&#x2F;code&gt; function returns the number of characters that would have been written had &lt;code&gt;n&lt;&#x2F;code&gt; been sufficiently large, not counting the terminating null character, or a negative value if an encoding error occurred.&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;これを利用するわけだ。あとはフォーマット後の文字数 &lt;strong&gt;+1&lt;&#x2F;strong&gt; バイトのメモリを確保して、そこに書き込んでやればよい。&lt;&#x2F;p&gt;
&lt;p&gt;これをコードにすると例えば下記のようになる&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;c&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-c &quot;&gt;&lt;code class=&quot;language-c&quot; data-lang=&quot;c&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;int &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;myasprintf&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;char &lt;&#x2F;span&gt;&lt;span&gt;**&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;bufp&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;const char &lt;&#x2F;span&gt;&lt;span&gt;* &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;restrict &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;format&lt;&#x2F;span&gt;&lt;span&gt;,...){
&lt;&#x2F;span&gt;&lt;span&gt;    va_list arg;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;va_start&lt;&#x2F;span&gt;&lt;span&gt;(arg, format);
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;int&lt;&#x2F;span&gt;&lt;span&gt; len = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;vsnprintf&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;NULL&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;,format,arg);
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;va_end&lt;&#x2F;span&gt;&lt;span&gt;(arg);
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;if &lt;&#x2F;span&gt;&lt;span&gt;(len &amp;lt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;) &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;return &lt;&#x2F;span&gt;&lt;span&gt;-&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;    len++; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; &amp;#39;\0&amp;#39;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;    *bufp = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;malloc&lt;&#x2F;span&gt;&lt;span&gt;(len);
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;if&lt;&#x2F;span&gt;&lt;span&gt;(!*bufp) &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;return &lt;&#x2F;span&gt;&lt;span&gt;-&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;;
&lt;&#x2F;span&gt;&lt;span&gt;    
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;va_start&lt;&#x2F;span&gt;&lt;span&gt;(arg, format);
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;int&lt;&#x2F;span&gt;&lt;span&gt; ret = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;vsnprintf&lt;&#x2F;span&gt;&lt;span&gt;(*bufp,len,format,arg);
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;va_end&lt;&#x2F;span&gt;&lt;span&gt;(arg);
&lt;&#x2F;span&gt;&lt;span&gt;    
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;if &lt;&#x2F;span&gt;&lt;span&gt;(ret &amp;lt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;) &lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;free&lt;&#x2F;span&gt;&lt;span&gt;(*bufp);
&lt;&#x2F;span&gt;&lt;span&gt;    
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;return&lt;&#x2F;span&gt;&lt;span&gt; ret;
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;FreeBSDの実装だとエラーの際には &lt;code&gt;strp&lt;&#x2F;code&gt; (この実装における &lt;code&gt;bufp&lt;&#x2F;code&gt; )を &lt;code&gt;NULL&lt;&#x2F;code&gt; にセットするらしい

&lt;sup class=&quot;footnote-reference&quot; id=&quot;fnref:2&quot;&gt;&lt;a href=&quot;#fndef:2&quot;&gt;2&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;
が、これは恐らくエラーの際に &lt;code&gt;strp&lt;&#x2F;code&gt; を通して渡したポインタを &lt;code&gt;free&lt;&#x2F;code&gt; に突っ込めるようにするためであろうから、今回はエラーが起きたときには確保したメモリを関数側で開放しておくこととした。あと、 &lt;code&gt;malloc&lt;&#x2F;code&gt; の部分で &lt;code&gt;char&lt;&#x2F;code&gt; のサイズをかけ忘れているように見えるかもしれないが、 &lt;code&gt;sizeof(char)&lt;&#x2F;code&gt; は常に1であるから

&lt;sup class=&quot;footnote-reference&quot; id=&quot;fnref:3&quot;&gt;&lt;a href=&quot;#fndef:3&quot;&gt;3&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;
、これで問題ない。この点を明示的に &lt;code&gt;len * sizeof(char)&lt;&#x2F;code&gt; とするかだとか、 &lt;code&gt;malloc&lt;&#x2F;code&gt; の返り値をキャストするかだとか、ifの後をブロックにするかなどは各自の思想に合わせて調整していただきたい。上記コードはCC0とする。&lt;&#x2F;p&gt;
&lt;hr &#x2F;&gt;


&lt;div class=&quot;footnote-definition&quot; id=&quot;fndef:1&quot;&gt;
    &lt;p&gt;
        &lt;span class=&quot;footnote-definition-label&quot;&gt;1&lt;&#x2F;span&gt;
        &lt;span&gt;:&lt;&#x2F;span&gt;
        &lt;span&gt;終端ヌル文字は含まれていないことに注意されたい &lt;a href=&quot;#fnref:1&quot;&gt;↩︎&lt;&#x2F;a&gt;&lt;&#x2F;span&gt;
    &lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;


&lt;div class=&quot;footnote-definition&quot; id=&quot;fndef:2&quot;&gt;
    &lt;p&gt;
        &lt;span class=&quot;footnote-definition-label&quot;&gt;2&lt;&#x2F;span&gt;
        &lt;span&gt;:&lt;&#x2F;span&gt;
        &lt;span&gt;man asprintfより一部を引用&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;The FreeBSD implementation sets &lt;code&gt;strp&lt;&#x2F;code&gt; to NULL on error.&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
 &lt;a href=&quot;#fnref:2&quot;&gt;↩︎&lt;&#x2F;a&gt;&lt;&#x2F;span&gt;
    &lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;


&lt;div class=&quot;footnote-definition&quot; id=&quot;fndef:3&quot;&gt;
    &lt;p&gt;
        &lt;span class=&quot;footnote-definition-label&quot;&gt;3&lt;&#x2F;span&gt;
        &lt;span&gt;:&lt;&#x2F;span&gt;
        &lt;span&gt;C99(N1256) 6.5.3.4 The sizeof operatorより一部を引用&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;When applied to an operand that has type &lt;code&gt;char&lt;&#x2F;code&gt;, &lt;code&gt;unsigned char&lt;&#x2F;code&gt;, or &lt;code&gt;signed char&lt;&#x2F;code&gt;,
(or a qualified version thereof) the result is 1. &lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
 &lt;a href=&quot;#fnref:3&quot;&gt;↩︎&lt;&#x2F;a&gt;&lt;&#x2F;span&gt;
    &lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>個人サイトを作った</title>
        <published>2023-08-02T00:00:00+00:00</published>
        <updated>2023-08-02T00:00:00+00:00</updated>
        <author>
          <name>Unknown</name>
        </author>
        <link rel="alternate" href="https://nost15459.net/blog/create-my-own-website/" type="text/html"/>
        <id>https://nost15459.net/blog/create-my-own-website/</id>
        
        <summary type="html">&lt;p&gt;ZolaというSSGでこのサイトを作った。&lt;&#x2F;p&gt;
</summary>
        
    </entry>
    <entry xml:lang="en">
        <title>プロフィール</title>
        <published>2023-07-16T00:00:00+00:00</published>
        <updated>2023-07-16T00:00:00+00:00</updated>
        <author>
          <name>Unknown</name>
        </author>
        <link rel="alternate" href="https://nost15459.net/about/" type="text/html"/>
        <id>https://nost15459.net/about/</id>
        
        <content type="html">&lt;p&gt;&lt;code&gt;&#x2F;&#x2F;おまじない&lt;&#x2F;code&gt;&lt;&#x2F;p&gt;
</content>
        
    </entry>
</feed>
