Thread: Help with pointers please.

  1. #1
    Registered User
    Join Date
    Mar 2014
    Location
    Corning, New York, USA
    Posts
    96

    Help with pointers please.

    I have struggled for a very long time with pointers in C. I've never had a good concept and whenever I've written a program, I hate to say it, but I've pretty much just tried a bunch of trial and error type things until it worked. As you can imagine, this causes big problems when you don't have a fundamental understanding of how the code works.

    With that being said, I was hoping someone could recommend a good free source on pointers in C. Even though I understand a little bit about them, I'd like a source that assumes I have no idea what a pointer is and fully explains everything.

    I know this is going to sound sad, but I'm writing a program and I need to check the return value of a function. The function returns NULL if no COM ports are found on the system. I seem to not be able to understand why this doesn't work:
    Code:
        if(sp_list_ports(&ports)==NULL) {
            printf("We've found no com ports.\n");
        } else {
            for(i = 0; ports[i]; i++) {
                printf("Found port: '%s'.\n", sp_get_port_name(ports[i]));
            }
        }
    The problem is in the if statement. When I try to compile, I get a warning saying: warning: comparison between pointer and integer
    I believe on this system, NULL is a macro defined as 0. If I type something like:
    Code:
        if(!sp_list_ports(&ports)) {...
    There's no error. Now, if NULL is really set as 0, how come when I use:
    Code:
        if(sp_list_ports(&ports)==0) {...
    We get no warning? I can compare NULL to 0 and get no error. This leads me to believe there's a problem with comparing it to the pointer.

    Could someone help me please? Thank you.

  2. #2
    Registered User
    Join Date
    Mar 2014
    Location
    Corning, New York, USA
    Posts
    96
    I think I made an error in my previous post. I think NULL on this MinGW compiler is defined as ((void *)0).

  3. #3
    Registered User migf1's Avatar
    Join Date
    May 2013
    Location
    Athens, Greece
    Posts
    385
    If that's the sp_list_ports() you are using, then it does not return a pointer. It returns an enum value (defined here: libserialport: libserialport.h Source File).
    "Talk is cheap, show me the code" - Linus Torvalds

  4. #4
    Registered User
    Join Date
    May 2003
    Posts
    1,619
    A quick run-down on what a pointer is:

    A pointer is just a special type of numeric variable, designed to store a memory address. So you can manipulate the pointer itself (the memory address stored), and you can also manipulate the contents of that memory address, be "dereferencing" the pointer.

    Take a look at this thread for some ideas on what a pointer is and how it works:
    changing variables with pointers
    You ever try a pink golf ball, Wally? Why, the wind shear on a pink ball alone can take the head clean off a 90 pound midget at 300 yards.

  5. #5
    Registered User
    Join Date
    Mar 2014
    Location
    Corning, New York, USA
    Posts
    96
    Quote Originally Posted by migf1 View Post
    If that's the sp_list_ports() you are using, then it does not return a pointer. It returns an enum value (defined here: libserialport: libserialport.h Source File).
    Okay, so my mistake was thinking NULL was set to 0. I knew sp_list_ports returned SP_OK on success, which was defined as 0 (I looked at the source as well). I thought NULL was defined with 0. Thank you for your help. Here's the new code. This seems to work.
    Code:
        /* Get a list of serial ports on the system, if any, and store them in pointer ports */
        sp_list_ports(&ports);
        if(*ports==NULL) {
    	printf("0 COM ports found.\n");
        } else {
            /* We found some COM ports, lets print them. */
            for(i = 0; ports[i]; i++) {
                printf("Found port: '%s'.\n", sp_get_port_name(ports[i]));
            }
        }

  6. #6
    Registered User
    Join Date
    Mar 2014
    Location
    Corning, New York, USA
    Posts
    96
    Quote Originally Posted by Cat View Post
    A quick run-down on what a pointer is:

    A pointer is just a special type of numeric variable, designed to store a memory address. So you can manipulate the pointer itself (the memory address stored), and you can also manipulate the contents of that memory address, be "dereferencing" the pointer.

    Take a look at this thread for some ideas on what a pointer is and how it works:
    changing variables with pointers
    Thank you! When I wake up a little more, I'll read the whole thing. I majored in Computer Science but I went into the Marine Corps and had some damage to the head while I was in there. My memory gets a little messed up sometimes. It seems to take extra time to memorize new stuff and the old stuff seems a little blurry. If I can get a good fundamental understanding of all these pointers, I think I'll be good.

    I have trouble with this whole dereferencing thing. Like when do you dereference a pointer? When don't you? If you notice, in my code, with the if statement, I have to a * in front of ports. My understanding (from what I remember from college), this means compare what's stored at wherever port points to to NULL and if they're equal, print 0 com ports found. If I didn't have the * in front of it, I'd just be comparing NULL to a memory address or something.

    I'm sure the link you sent will correct all my misinformation and reinforce all the information I once learned. Thanks!

  7. #7
    Registered User migf1's Avatar
    Join Date
    May 2013
    Location
    Athens, Greece
    Posts
    385
    Quote Originally Posted by Spork Schivago View Post
    ...

    I have trouble with this whole dereferencing thing. Like when do you dereference a pointer? When don't you? If you notice, in my code, with the if statement, I have to a * in front of ports. My understanding (from what I remember from college), this means compare what's stored at wherever port points to to NULL and if they're equal, print 0 com ports found. If I didn't have the * in front of it, I'd just be comparing NULL to a memory address or something.
    ...
    Actually, according to the documentation of the function sp_list_ports(), the ports variable should be defined of type: struct sp_port **

    It's my understanding that the function dynamically creates and fills in ports, as a NULL terminated array of pointers to sp_port structures, hence the need to pass the address of ports to the function (that is, a triple pointer). If something goes wrong, the function sets ports to NULL instead.

    So, after calling sp_list_ports( &ports ) you should check ports (the name of the dynamically created array) against NULL.

    *ports is the 1st element of the dynamically created array. That element is a pointer to a sp_port structure, which may be NULL I guess if no ports were found, but most probably it won't even exist/been allocated if no ports were found... it depends on how sp_list_ports() works internally.

    PS. Here's a fairly decent free resource on pointers. Regarding NULL, you may also want to take a look at this thread.
    "Talk is cheap, show me the code" - Linus Torvalds

  8. #8
    Registered User
    Join Date
    Mar 2014
    Location
    Corning, New York, USA
    Posts
    96
    Thanks Migf1. I'll be sure to check it out. The code seems to work. If I have no COM ports, it prints 0 COM ports found, if it finds them, it lists them. I looked at the source code, serialport.c, and saw what happened if something went wrong. I could be wrong though. If I didn't have the * in front of ports (to check the first element), when there where 0 COM ports found, the code didn't work. It think there was a COM port. I'm lucky in the sense that I have a USB to serial adapter on this PC, so I can easily add / remove the serial port for testing purposes.

    I tried creating separate functions for the port stuff, like enum_ports, print_ports, free_ports. The compiler didn't like my code at all.

    I first tried this:
    Code:
    int enum_ports(struct sp_port **ports);    /* Function to enumerate COM ports on the system */
    int print_ports(struct sp_ports **ports);  /* Function to print the enumerated ports found on the system */
    int free_ports(struct sp_ports **ports);   /* Function to free up memory from the libserialport malloc calls */
    That didn't work. The compiler complained a lot, with messages like:
    Code:
    In file included from src/main.c:12:0: src/prototype.h:7:23: warning: 'struct sp_port' declared inside 
    parameter list int enum_ports(struct sp_port **);  /* Function to enumerate COM ports on the system */
    Then I tried this:
    Code:
    int enum_ports(struct sp_port **ports);    /* Function to enumerate COM ports on the system */
    int print_ports(struct sp_ports **ports);  /* Function to print the enumerated ports found on the system */
    int free_ports(struct sp_ports **ports);   /* Function to free up memory from the libserialport malloc calls */
    From what I was reading, this could be caused by the fact that I have the struct defined in main, like this:
    Code:
    struct sp_port **ports;	        /* structure to hold COM ports for libserialport library */
    Perhaps I need to declare it globally in my main.c file? Before main()... Also, because I'm planning on passing a pointer of type structure ports to the functions, maybe I need an extra asterisk? I guess this is just more proof I still need more reading.

    The original forum was nice but a bit confusing at parts because there where questions being asked and it would through me off a bit. Like I was following what was being said, then someone would ask a question with incorrect info, like hey, can I do this? and I'd start confusing what they where trying to do with the correct way. I'm sure this is just a problem that I have. Other people can probably read it just fine. I found some book I started reading, C Programming, A Modern Approach - 2nd Edition, by K.N. King. I've just started from the beginning. Figured I'd fill in the some of the missing caps.

  9. #9
    Registered User
    Join Date
    Mar 2014
    Location
    Corning, New York, USA
    Posts
    96
    Okay, just a little clarification, after looking at my code above, I noticed an extra s on sp_port. This caused some compiler errors. I created a new project, just a main function and my functions that call the libserialports library functions. It compiles, finds a port, than crashes. So...I've taken a break from that project and started reading up on the pointers...

    I have a question. With the link you've given me, it takes about int being the size of 4 bytes on modern systems. I'm assuming the whole article assumes the size of int to be 4-bytes. I want to get into PCB development using PICs or AVRs in the future. int might not always be 4-bytes but I think with the article, the size of the data types might not matter so much.

    I've seen stuff before like:
    Code:
    int *ptr_a;
    int* ptr_b;
    Are they the same? one has the * with int, one has the star with the variable's name.

    Also, if I had something like,
    Code:
    int** ptr_a, ptr_b;
    ;
    ptr_a becomes **ptr_a and ptr_b because just ptr_b, right? Not *ptr_b with one asterisk?

    Thanks.

  10. #10
    Registered User migf1's Avatar
    Join Date
    May 2013
    Location
    Athens, Greece
    Posts
    385
    Quote Originally Posted by Spork Schivago View Post
    Thanks Migf1. I'll be sure to check it out. The code seems to work. If I have no COM ports, it prints 0 COM ports found, if it finds them, it lists them. I looked at the source code, serialport.c, and saw what happened if something went wrong. I could be wrong though. If I didn't have the * in front of ports (to check the first element), when there where 0 COM ports found, the code didn't work. It think there was a COM port.
    This makes sense only if sp_list_ports() does NOT consider as error the case where no ports are found. Which in turn means that even when no ports are found, the functions allocates the ports array anyway with just a single element, and sets it to NULL. I guess this is an effort to be consistent with the concept of ports being a NULL terminated array of pointers to sp_port structures. No ports found, so the array contains just a NULL as its only element. *ports is the same as ports[0] in our case. Btw, make sure you call sp_free_port_list( ports ) when you are done, otherwise you'll leak memory.

    I'm lucky in the sense that I have a USB to serial adapter on this PC, so I can easily add / remove the serial port for testing purposes.

    I tried creating separate functions for the port stuff, like enum_ports, print_ports, free_ports. The compiler didn't like my code at all.

    I first tried this:
    Code:
    int enum_ports(struct sp_port **ports);    /* Function to enumerate COM ports on the system */
    int print_ports(struct sp_ports **ports);  /* Function to print the enumerated ports found on the system */
    int free_ports(struct sp_ports **ports);   /* Function to free up memory from the libserialport malloc calls */
    That didn't work. The compiler complained a lot, with messages like:
    Code:
    In file included from src/main.c:12:0: src/prototype.h:7:23: warning: 'struct sp_port' declared inside 
    parameter list int enum_ports(struct sp_port **);  /* Function to enumerate COM ports on the system */
    Then I tried this:
    Code:
    int enum_ports(struct sp_port **ports);    /* Function to enumerate COM ports on the system */
    int print_ports(struct sp_ports **ports);  /* Function to print the enumerated ports found on the system */
    int free_ports(struct sp_ports **ports);   /* Function to free up memory from the libserialport malloc calls */
    What's the difference between those 2 code snippets? They look exactly the same to me (however, I'm quite tired right now).

    From what I was reading, this could be caused by the fact that I have the struct defined in main, like this:
    Code:
    struct sp_port **ports;            /* structure to hold COM ports for libserialport library */
    Perhaps I need to declare it globally in my main.c file? Before main()...
    This doesn't make much sense, unless you provide more detailed code. The warning you get from the compiler, most likely means that you are using struct sp_ports inside the parameter lists without having previously declared or defined it in that file.

    Also, because I'm planning on passing a pointer of type structure ports to the functions, maybe I need an extra asterisk? I guess this is just more proof I still need more reading.
    It depends on what you are trying to do. An extra asterisk would be needed if your functions will change the address of the ports array, perhaps by malloc'ing, or reallocing the array. However, judging from the names of those functions, that's not the case, so you most probably don't need an extra asterisk. That's all guesswork for me though, because (despite their descriptive names) I don't know what you are actually doing inside those functions. You need to provide more detailed code.

    ...
    I found some book I started reading, C Programming, A Modern Approach - 2nd Edition, by K.N. King. I've just started from the beginning. Figured I'd fill in the some of the missing caps.
    That's an excellent introductory book to C programming. However, what you are dealing with here (with the libserialport and GTK+) require you to have a pretty good grasp of some advanced use of pointers and data structures. I'm not saying that the book will not help you, but afterward you should probably read about (or even better practice) techniques that may be more advanced that the ones presented by the book. David Hanson's C Interfaces and Implementations is a great complement to King's book.
    "Talk is cheap, show me the code" - Linus Torvalds

  11. #11
    Registered User migf1's Avatar
    Join Date
    May 2013
    Location
    Athens, Greece
    Posts
    385
    We were cross-posting.

    Quote Originally Posted by Spork Schivago View Post
    ...
    I have a question. With the link you've given me, it takes about int being the size of 4 bytes on modern systems. I'm assuming the whole article assumes the size of int to be 4-bytes. I want to get into PCB development using PICs or AVRs in the future. int might not always be 4-bytes but I think with the article, the size of the data types might not matter so much.
    The article says that when it was written, on x86 machines the sizeof an int was 4 bytes. It doesn't imply that this is always true.

    I've seen stuff before like:
    Code:
    int *ptr_a;
    int* ptr_b;
    Are they the same? one has the * with int, one has the star with the variable's name.
    Yeap, they are exactly the same. In C, the 1st example is more idiomatic (the 2nd example is more common in C++).

    Also, if I had something like,
    Code:
    int** ptr_a, ptr_b;
    ;
    ptr_a becomes **ptr_a and ptr_b because just ptr_b, right? Not *ptr_b with one asterisk?

    Thanks.
    The above code defines ptr_a as a double pointer to int, and ptr_b is defined a simple int. Try to avoid code like that. It becomes more clear if you use separate lines:

    Code:
    int **ptr_a;
    int ptr_b;
    "Talk is cheap, show me the code" - Linus Torvalds

  12. #12
    Registered User
    Join Date
    May 2012
    Location
    Arizona, USA
    Posts
    948
    Quote Originally Posted by Spork Schivago View Post
    I have a question. With the link you've given me, it takes about int being the size of 4 bytes on modern systems. I'm assuming the whole article assumes the size of int to be 4-bytes. I want to get into PCB development using PICs or AVRs in the future. int might not always be 4-bytes but I think with the article, the size of the data types might not matter so much.
    C only guarantees that 'int' is large enough to hold a value between -32767 and +32767, which means it's at least 16 bits wide. Most 32-bit/64-bit systems have 32-bit 'int'. This just goes beyond the minimum size guaranteed by C.

    Quote Originally Posted by Spork Schivago View Post
    I've seen stuff before like:
    Code:
    int *ptr_a;
    int* ptr_b;
    Are they the same? one has the * with int, one has the star with the variable's name.
    They are the same. The spaces are ignored.

    Quote Originally Posted by Spork Schivago View Post
    Also, if I had something like,
    Code:
    int** ptr_a, ptr_b;
    ;
    ptr_a becomes **ptr_a and ptr_b because just ptr_b, right? Not *ptr_b with one asterisk?

    Thanks.
    ptr_a is a pointer to pointer to int, and ptr_b is an int. The asterisks bind to the variable name rather than to the type. That's the main reason I and many others prefer to write such as declaration like this:
    Code:
    int **ptr_a, ptr_b;
    or, better, like this:
    Code:
    int **ptr_a;
    int ptr_b;
    to make it clear that the asterisks apply to ptr_a but not to ptr_b.

  13. #13
    Registered User
    Join Date
    Mar 2014
    Location
    Corning, New York, USA
    Posts
    96
    Quote Originally Posted by migf1 View Post
    This makes sense only if sp_list_ports() does NOT consider as error the case where no ports are found. Which in turn means that even when no ports are found, the functions allocates the ports array anyway with just a single element, and sets it to NULL. I guess this is an effort to be consistent with the concept of ports being a NULL terminated array of pointers to sp_port structures. No ports found, so the array contains just a NULL as its only element. *ports is the same as ports[0] in our case. Btw, make sure you call sp_free_port_list( ports ) when you are done, otherwise you'll leak memory.
    Yes, if I understand the code correctly, if no COM ports are found, it's not treated as an error. This is what makes up the sp_list_ports(...) function.
    Code:
    SP_API enum sp_return sp_list_ports(struct sp_port ***list_ptr)
    {
    #ifndef NO_ENUMERATION
        struct sp_port **list;
        int ret;
    #endif
    
    
        TRACE("%p", list_ptr);
    
    
        if (!list_ptr)
            RETURN_ERROR(SP_ERR_ARG, "Null result pointer");
    
    
        *list_ptr = NULL;
    
    
    #ifdef NO_ENUMERATION
        RETURN_ERROR(SP_ERR_SUPP, "Enumeration not supported on this platform");
    #else
        DEBUG("Enumerating ports");
    
    
        if (!(list = malloc(sizeof(struct sp_port *))))
            RETURN_ERROR(SP_ERR_MEM, "Port list malloc failed");
    
    
        list[0] = NULL;
    
    
        ret = list_ports(&list);
    
    
        if (ret == SP_OK) {
            *list_ptr = list;
        } else {
            sp_free_port_list(list);
            *list_ptr = NULL;
        }
    
    
        RETURN_CODEVAL(ret);
    #endif
    }
    NO_ENUMERATION gets set if the developers don't know how to enumerate the COM ports on a system yet, for example, on the Android smartphones. The part that says,
    Code:
    *list_ptr = NULL;
    I took that as we set the first element in the structure to NULL. Then, afterwards, if we find more, we add them to the list. This means that if no COM ports are found, I should be checking *ports to see if it's set to NULL, right?

    Quote Originally Posted by migf1 View Post
    What's the difference between those 2 code snippets? They look exactly the same to me (however, I'm quite tired right now).
    You're correct. I copied and pasted but forgot to change the first code. With the function prototypes in the first code snippets I posted, it wasn't supposed to have **ports. I had first tried:
    Code:
    int enum_ports(struct sp_port **);    /* Function to enumerate COM ports on the system */
    int print_ports(struct sp_ports **);  /* Function to print the enumerated ports found on the system */
    int free_ports(struct sp_ports **);   /* Function to free up memory from the libserialport malloc calls */
    I was almost certain I could do this with function prototypes and was almost certain the second example wouldn't make a difference, you know, replacing ** with **ports. I was correct.

    Quote Originally Posted by migf1 View Post
    This doesn't make much sense, unless you provide more detailed code. The warning you get from the compiler, most likely means that you are using struct sp_ports inside the parameter lists without having previously declared or defined it in that file.
    I believe the problem with the code, why the error didn't make much sense, was because there was no , it was struct sp_port **ports;. Two of those function declarations I created use struct sp_ports, instead of struct sp_port.

    Quote Originally Posted by migf1 View Post
    It depends on what you are trying to do. An extra asterisk would be needed if your functions will change the address of the ports array, perhaps by malloc'ing, or reallocing the array. However, judging from the names of those functions, that's not the case, so you most probably don't need an extra asterisk. That's all guesswork for me though, because (despite their descriptive names) I don't know what you are actually doing inside those functions. You need to provide more detailed code.
    What I wanted to do was call some custom made functions from main, passing them the struct sp_port **ports; structure, and have those functions do various things, instead of having all the code in main. I actually have a main.c file and then a ports.c file. I wanted, in main, to call my functions in the ports.c file, enum_ports, print_ports, and free_ports, passing a pointer to struct sp_port **ports; to each function. And then have those functions do various things (error checking on the library call that I made, etc).

    Quote Originally Posted by migf1 View Post
    That's an excellent introductory book to C programming. However, what you are dealing with here (with the libserialport and GTK+) require you to have a pretty good grasp of some advanced use of pointers and data structures. I'm not saying that the book will not help you, but afterward you should probably read about (or even better practice) techniques that may be more advanced that the ones presented by the book. David Hanson's C Interfaces and Implementations is a great complement to King's book.
    Okay, thank you. It's obvious to me now I need to just spend the time and purchase some books and read up on the subject again. There's just been too much time I think that's passed since I last programmed. I remember taking a C programming class in college, advanced data structures, and there was another class. I don't remember if it was the advanced data structures class that dealt with stuff like linked lists and binary trees or if it was the third class. There was also an intro into C++ class I took but remember nothing from. Last time I had a job as a system programmer was back in 2005. That was over 10 years ago now and I guess I just need to relearn stuff. I've played with some small code since then, but nothing too complicated. I thought it'd all come back to me, like riding a bike, but unfortunately, the pointer stuff has been confusing me.

    Thank you though for taking the time to help me. I appreciate it.

  14. #14
    Registered User
    Join Date
    Mar 2014
    Location
    Corning, New York, USA
    Posts
    96
    Quote Originally Posted by migf1 View Post
    ...
    The article says that when it was written, on x86 machines the sizeof an int was 4 bytes. It doesn't imply that this is always true.
    Yeah, I didn't mean to imply that the article was implying that an int is always 4-bytes. I believe in the article, it actually tells you it might not be always 4-bytes. I remember when int on Windows was 2 bytes but in Linux, it was 4 bytes (or at least that's how I remember it). Let me try to rephrase my question.

    If the size of a data type, like int, was 4-bytes on one system but 2-bytes on another, would that affect my code drastically? Would I have to do anything different when dealing with pointers? I try to use uint#_t, like uint8_t, when I need something that stores at least #-bits and when the size of the data type might matter. I don't know if this is a good practice or not though. I can't see where it could hurt anything, only help. But I've been out of the loop for some time now. I know it makes using printf and functions like printf a pain. I have to do stuff like,
    Code:
        uint8_t my_age = 33;
    
        printf("Age: %" PRIu8 ".\n", my_age);
    Perhaps there's a better way to do this and I just don't know the proper flag character?
    Quote Originally Posted by migf1 View Post
    ...
    Yeap, they are exactly the same. In C, the 1st example is more idiomatic (the 2nd example is more common in C++).



    The above code defines ptr_a as a double pointer to int, and ptr_b is defined a simple int. Try to avoid code like that. It becomes more clear if you use separate lines:

    Code:
    int **ptr_a;
    int ptr_b;
    Okay, I understand, and yeah, it is a lot clearer when you use separate lines. I just needed to make sure I understood. Thank you.

  15. #15
    Registered User migf1's Avatar
    Join Date
    May 2013
    Location
    Athens, Greece
    Posts
    385
    Quote Originally Posted by Spork Schivago View Post
    Yes, if I understand the code correctly, if no COM ports are found, it's not treated as an error. This is what makes up the sp_list_ports(...) function.
    Code:
    ...
    NO_ENUMERATION gets set if the developers don't know how to enumerate the COM ports on a system yet, for example, on the Android smartphones. The part that says,
    Code:
    *list_ptr = NULL;
    I took that as we set the first element in the structure to NULL. Then, afterwards, if we find more, we add them to the list. This means that if no COM ports are found, I should be checking *ports to see if it's set to NULL, right?
    Almost right

    In the scope of the function, *list_ptr is the array itself. The line *list_ptr = NULL; initializes to nowhere the not yet allocated array. There are no array elements at that point. Once the array gets allocated, then its first element can be accessed via *(*list_ptr)or (*list_ptr)[0]. The address of all the above are the same, but the type of the latter 2 is not the same with the type of the former (in general, any array element is a different object than the array itself).

    However, the presented function does not allocate directly the *list_ptr array. Instead, it uses a locally defined dynamic array called sp_port **list as an intermediate step for the allocation. If allocation succeeds, it sets the 1st element equal to NULL (via the line: list[0] = NULL;) and then it assigns list to *list_ptr. Put otherwise, the actual line that sets the 1st element of the dynamic array equal to NULL, is line #29 in the code you posted.

    You're correct. I copied and pasted but forgot to change the first code. With the function prototypes in the first code snippets I posted, it wasn't supposed to have **ports. I had first tried:
    Code:
    int enum_ports(struct sp_port **);    /* Function to enumerate COM ports on the system */
    int print_ports(struct sp_ports **);  /* Function to print the enumerated ports found on the system */
    int free_ports(struct sp_ports **);   /* Function to free up memory from the libserialport malloc calls */
    I was almost certain I could do this with function prototypes and was almost certain the second example wouldn't make a difference, you know, replacing ** with **ports. I was correct.

    I believe the problem with the code, why the error didn't make much sense, was because there was no , it was struct sp_port **ports;. Two of those function declarations I created use struct sp_ports, instead of struct sp_port.
    That certainly explains the compiler warning

    Also, you are right in that there is no need to specify argument names when declaring functions (prototypes). The problem was that due to that extra 's', you were using a non-existed/defined/declared type.

    What I wanted to do was call some custom made functions from main, passing them the struct sp_port **ports; structure, and have those functions do various things, instead of having all the code in main. I actually have a main.c file and then a ports.c file. I wanted, in main, to call my functions in the ports.c file, enum_ports, print_ports, and free_ports, passing a pointer to struct sp_port **ports; to each function. And then have those functions do various things (error checking on the library call that I made, etc).
    As I explained in my previous post, if the address of the ports array is NOT changed inside the functions, then you do NOT need an extra asterisk (and consequently you don't need to pass ports with the address-of operator in front of it when calling the functions). The function sp_list_ports() needs the extra asterisk because the address of ports is changed inside the function, since ports is assigned the address returned by malloc() inside the function. This new address must be passed back to the caller of the function.

    You may want to refresh the stuff about C's "call by value" concept, along with how we achieve a "call by reference" instead, by using pointers.

    Regarding splitting your source into multiple files, King's book does a pretty good job in explaining it, but Hanson makes it the reference point of his whole book.

    I'd suggest to first read the relative chapter in King's book, and then before (or instead of) going to Hanson's book, first have a look at this article.

    ...
    Thank you though for taking the time to help me. I appreciate it.
    No problem. I'm sure you'll do the same when I'll need help in a topic you have more experience than me.
    "Talk is cheap, show me the code" - Linus Torvalds

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Replies: 4
    Last Post: 08-29-2015, 01:15 PM
  2. Replies: 43
    Last Post: 05-23-2013, 03:01 PM
  3. size of struct with pointers and function pointers
    By sdsjohnny in forum C Programming
    Replies: 3
    Last Post: 07-02-2010, 05:19 AM
  4. Storing function pointers in generic pointers
    By Boxknife in forum C Programming
    Replies: 6
    Last Post: 08-01-2009, 01:33 PM
  5. weak pointers and use_count smart pointers
    By Mario F. in forum C++ Programming
    Replies: 2
    Last Post: 07-29-2006, 07:54 AM