Note that there are some explanatory texts on larger screens.

plurals
  1. POUsing void pointers in generic accessor function with ANSI C
    primarykey
    data
    text
    <p>I have a working example of a piece of C code that I'm using to teach myself about using pointers effectively in a non-trivial application. (I have a dream to contribute a missing feature to a C library which I'm relying on.)</p> <p>My sample code loo like this:</p> <pre><code>#include &lt;stdio.h&gt; #include &lt;stdlib.h&gt; struct config_struct { int port; char *hostname; }; typedef struct config_struct config; void setup(config*); void change(config*); void set_hostname(config*, char*); void get_hostname_into(config*, char**); void teardown(config*); void inspect(config*); int main() { char* hostname; config* c; c = calloc( 1, sizeof(config)); setup(c); inspect(c); change(c); inspect(c); set_hostname(c, "test.com"); inspect(c); get_hostname_into(c, &amp;hostname); inspect(c); printf("retrieved hostname is %s (%p)\n", hostname, &amp;hostname); teardown(c); printf("retrieved hostname is %s (%p) (after teardown)\n", hostname, &amp;hostname); return EXIT_SUCCESS; } void setup(config* c) { c-&gt;port = 9933; c-&gt;hostname = "localhost"; } void change(config* c) { c-&gt;port = 12345; c-&gt;hostname = "example.com"; } void set_hostname(config* c, char* new_hostname) { c-&gt;hostname = new_hostname; } void get_hostname_into(config* c, char** where) { *where = c-&gt;hostname; } void teardown(config* c) { free(c); } void inspect(config* c) { printf("c is at %p\n", c); printf("c is %ld bytes\n", sizeof(*c)); printf("c:port is %d (%p)\n", c-&gt;port, &amp;(c-&gt;port)); printf("c:hostname is %s (%p)\n", c-&gt;hostname, &amp;(c-&gt;port)); } </code></pre> <p>It's required by the nature of the library (the function is <code>get_session_property(session*, enum Property, void*)</code> - thus I'm looking for a way to dereference a void pointer; I was able to successfully implement this for an <code>int</code>, but have been kicking my heels trying to figure out how to do it for a <code>char*</code> (something about a <code>void*</code> to <code>int</code> making some sense, but I can't fathom how to do it for <code>void* to char*</code>.</p> <p>My successful implementation (with tests) for the library is on my Github fork of the project, <a href="https://github.com/leehambley/libssh/commit/208a0df74075889a5fd1f6a72d82e5903ee527d2" rel="nofollow">here</a>.</p> <p>The closest I have come is:</p> <pre><code>enum Property { Port, Hostname }; void get_property(config*, enum Property, void*); void get_property(config* c, enum Property p, void* target) { switch(p) { case Port: { int *port; port = (int *) target; *port = c-&gt;port; } break; case Hostname: { char *hostname; hostname = (char *) target; *hostname = c-&gt;hostname; } break; } } </code></pre> <p>Which mercifully doesn't segfault, but also leaves <code>char *get_hostname_into_here</code> <code>null</code>, raising the warning (which I can't figure out:)</p> <pre><code>untitled: In function ‘get_property’: untitled:33: warning: assignment makes integer from pointer without a cast </code></pre> <p>Full source code of my contrived example here; please when answering explain, or recommend any reading you have on using void pointers and/or good C style, it seems like everyone has a different idea, and a couple of people I know in the real world simply said "the library is doing it wrong, don't use void pointers) - whilst it would be nice if the library would make the struct public; for encapsulation and other good reasons, I think the void pointers, generic function approach is perfectly reasonable in this case.</p> <p><strong>So, what am I doing wrong in my <code>hostname</code> branch of the <code>get_property()</code> function that the <code>char*</code> is <code>NULL</code> after the call to <code>get_property(c, Hostname, &amp;get_hostname_into_here);</code></strong></p> <pre><code>char *get_hostname_into_here; get_property(c, Hostname, &amp;get_hostname_into_here); printf("genericly retrieved hostname is %s (%p)\n", get_hostname_into_here, &amp;get_hostname_into_here); // Expect get_hostname_into_here not to be NULL, but it is. </code></pre> <p><a href="https://gist.github.com/dee4a9a75a30882ac6e2" rel="nofollow">full source code for example (with output)</a>.</p>
    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.
 

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