Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    primarykey
    data
    text
    <p>Let's consider a simplified example of your <code>get_property</code> function which is the same in all the important ways:</p> <pre><code>void get_property_hostname(config* c, void* target) { char * hostname = (char *) target; *hostname = c-&gt;hostname; } </code></pre> <p>On the first line of the function, you are making a "char *" pointer which points to the same location as "target". On the second line of the function, when you write <code>*hostname = ...</code>, you are writing to the <code>char</code> that hostname points at, so you are writing to the first byte of memory that <code>target</code> points to. This is not what you want; you are only giving one byte of data to the caller of the function. Also, the compiler complains because the the left-hand side of the assignment has type "char" while the right-hand side has the type "char *".</p> <p><em>There are at least three correct ways to return a string in C:</em></p> <p><strong>1) Return a pointer to the original string</strong></p> <p>If you do this, the user will have access to the string and could modify it if he wanted to. You must tell him not to do that. Putting the const qualifier on it will help achieve that.</p> <pre><code>const char * get_property_hostname(config* c) { return c-&gt;hostname; } </code></pre> <p><strong>2) Duplicate the string and return a pointer to the duplicate</strong></p> <p>If you do this, the caller of the function must pass the duplicate string to <code>free()</code> when he is done using it. See the <a href="http://pubs.opengroup.org/onlinepubs/009695399/functions/strdup.html" rel="nofollow">documentation of strdup</a>.</p> <pre><code>const char * get_property_hostname(config * c) { return strdup(c-&gt;hostname); } </code></pre> <p><strong>3) Write the string to a buffer that the caller has allocated</strong></p> <p>If you do this, then it is up to the caller of the function when and how he wants to allocate and free the memory. This is what a lot of APIs in the Microsoft Windows operating system do because it offers the most flexibility to the caller of the function.</p> <pre><code>void get_property_hostname(config * c, char * buffer, int buffer_size) { if (strlen(c-&gt;hostname)+1 &gt; buffer_size) { // Avoid buffer overflows and return the empty string. buffer[0] = 0; } else { strcpy(buffer, c-&gt;hostname); } } </code></pre> <p>Then to use this function, you can do something like:</p> <pre><code>void foo(){ char buffer[512]; get_property_hostname(c, buffer, sizeof(buffer)); ... // buffer is on stack, so it gets freed automatically when foo returns } </code></pre> <p><strong>EDIT 1:</strong> I will leave it as an exercise for you to figure out how to integrate the ideas presented here back into your generic <code>get_property</code> function. If you take the time to understand what is going on here, it shouldn't be too hard, but you may have to add some extra parameters.</p> <p><strong>EDIT 2:</strong> Here's how you would adapt method 1 to use a void pointer that points to a char * instead of using a return value:</p> <pre><code>void get_property_hostname(config* c, void * target) { *(char **)target = c-&gt;hostname; } </code></pre> <p>Then you would call it like this:</p> <pre><code>void foobar() { char * name; get_property_hostname(c, &amp;name); ... } </code></pre>
    singulars
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload