tags:

views:

122

answers:

8

I'm working with this structure in C:

/** This structure describes an Internet host address. */
typedef struct pj_hostent
{
    char    *h_name;        /**< The official name of the host. */
    char   **h_aliases;     /**< Aliases list. */
    int      h_addrtype;    /**< Host address type. */
    int      h_length;      /**< Length of address. */
    char   **h_addr_list;   /**< List of addresses. */
} pj_hostent;

I can access the h_name part of the structure fine like this:

strcpy(test1, he->h_name); // copy part of struct into char[] array

and it contains a meaningful "sip2" value. However, when I try to access the elements of h_addr_list like this:

strcpy(test1, he->h_addr_list[0]);

I get meaningless jibberish.

What's the correct way in C to access values like this?

A: 

struct elements are accessed with the dot operator

strcpy(test1, he.h_addr_list[0]);

elements of structs that are "pointed" to are accessed with the -> operator

strcpy(test1, he->h_addr_list->[0]);

If you're getting gibberish, then either test1 isn't big enough, h_addr_list isn't pointing to an array of char*, or the first element of the array is actually gibberish.

mepcotterell
It wouldn't compile if he was doing this wrongly. His example uses an arrow for the field that does work.
Martin Broadhurst
I'm doing this in XCode, and using the dot operator generates an error "Request for member 'h_addr_list' in something not a structure or union"
MusiGenesis
A: 

You are accessing it correctly. That field really does contain gibberish.

Martin Broadhurst
A: 

strcpy assumes that you have already allocated memory to the character pointer. So, probably, the pointer is still having a NULL value.

Alan Haggai Alavi
+4  A: 

h_addr_list[0] is not a string, it is a pj_in_addr, which is a 32-bit integer which is not null terminated.

printf() it with %d or %x, not %s.

See PJLIB Reference: Network Address Resolution for an example of use.

mouviciel
This is a useful answer. The asker is having a problem with APIs, not with C; perhaps the question should be edited to reflect this. To add to this answer: you could also use the inet_ntoa or inet_ntop functions to convert an in_addr to a string.
tcovo
@tcovo: I am having problems with APIs *and* with C (not to mention problems using a Mac for the first time in 20 years). I'm about to ask another question about taking an IP address given to me as an `unsigned int` and converting it to an `NSString` like "192.10.56.102", which I'm guessing the two functions you mentioned are good for.
MusiGenesis
A: 

The struct only contains a pointer. You need to allocate some storage for that pointer to point at before you can use it. As it is, the pointer almost certainly just contains a (more or less) random value. When you use that as a target in your call to strcpy, you're overwriting that random memory location -- which can and will lead to major problems elsewhere.

h_addr_list is pretty much the same way -- it's just a pointer to a pointer. That'll (normally) be used to refer to an array of strings, but something has to allocate that array of strings before it can be put to any meaningful use. Given the similarity to a hostent structure, along with this structure there's presumably some analog to (or wrapper around) gethostbyname and/or gethostbyaddress that initializes this. In the case of the wrapper (which I'd judge the more likely of the two), it probably gets the correct data in a hostent, and then copies data from the hostent to this structure.

Jerry Coffin
A: 

A short Example that does work. Remember that allocating for the struct does not allocate for the pointer.

typedef struct pj_hostent
{
    char    *h_name;        /**< The official name of the host. */
    char   **h_aliases;     /**< Aliases list. */
    int      h_addrtype;    /**< Host address type. */
    int      h_length;      /**< Length of address. */
    char   **h_addr_list;   /**< List of addresses. */
} pj_hostent;

int _tmain(int argc, _TCHAR* argv[])
{
    char* s[]= {"this","is","couple of words"};
    pj_hostent hst = {"high",s,3,4,s };
    char  buff[255] = {};
    //Access as a local initialized struct
    strcpy(buff,hst.h_addr_list[0]);
    printf("%s\n",buff);
    pj_hostent * he = & hst; 
    //Access as a pointer 
    strcpy(buff,he->h_addr_list[0]);
    printf("%s\n",buff);
    gets(buff);
}
rerun
Don't use `gets`. **NEVER!**
pmg
For some example code that is going nowhere.
rerun
A: 

If you never initialized/allocated memory for those pointers, you would get jibberish and/or segmentation faults because they are pointing to random points in memory.

JRam930
+1  A: 

Just because it is declared as a char** does NOT mean that it is an array of strings.

It may be a pointer to a byte-buffer of unknown format. (ie. jibberish)

You should check any available documentation or other source code for details of exactly what h_addr_list is, and how it should be interpreted.

abelenky
+1. Read documentation instead of assuming/guessing what an API gives you - if documentation is non existing, you'll have to resort to source code/examples.
nos