Asool
Asool

Reputation: 14199

Char pointer puzzle

I'm new to c and attempting socket programming. I have a question about pointers.

Say I have a setup like this:

int main() {
    ... // some code
    int numbytes = receive(i); 
}

int receive(int num) {
    ... // some code
    msgLength = ... // some code
    char msgWithLength[4 + msgLength]; 
    int n = getMsg(clientSocket, msgWithLength, 4 + msgLength);
    char * msg = unpack(msgWithLength, 4);
    return n; 
}

char * unpack(char *msgWithHeader, int headerSize) {
    char *msg = ... // some code to remove header from msgWithHeader
    return msg;
}

What I want is to access msg in in main. I don't want recieve to return msg though, I want it to return an int. Also, in main, I don't know the size of msg.

Ideally I'd have something like

int main() {
    char * msg;
    int numbytes = receive(i, msg); 
    // And be able to access msg here
}

But this doesn't work. I guess my question is related to pointers and passing by reference. Any ideas on how to get this to work?

Upvotes: 0

Views: 102

Answers (2)

Scooter
Scooter

Reputation: 7061

You have to pass a pointer to your variable in C in order to "pass by reference". To get data into a char * variable from a function that you call, the function has to take the address of your char *. The syntax for the address of a character pointer looks like: char** (one asterisk to represent a pointer, and the other asterisk to show that the pointer is pointing to a "char *", a character pointer variable). The value given to the "char * *" parameter is the address of your char * variable : &msg. Then inside the function you dereference the char ** variable - *address_of_msg - to assign to the msg variable that is external to the function.

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int receive(int a, char **address_of_msg)
{
  *address_of_msg = malloc(200);
  strcpy(*msg,"modified in subroutine");
  return 10;
}

int main(void)
{
  char *msg;
  int return_value;
  return_value = receive(20,&msg);
  printf("return value: %d msg: %s\n",return_value,msg);
}

Upvotes: 1

Cheatah
Cheatah

Reputation: 1835

It's perfectly normal to do something like that with pointers. But it can be a bit tricky. If the function does the memory allocation, you will have to pass a pointer to a pointer as an argument, which is possible, but not very common. The Apache Portable Runtime library makes use of this technique.

It is more common to pass a pointer to a buffer and the size of the buffer as arguments, like so:

int your_read(int fd, char *buf, size_t len) {
    return read(fd, but, len);
}
// called using e.g.:
char the_buffer[1024];
your_read(0, the_buffer, sizeof(the_buffer))

If you do want to do something similar to what I described first, it would be:

int create_object(struct example **e) {
    *e = malloc(sizeof(**e));
    if (*e == NULL)
        return -1;
    (*e)->name = "example";
    return 0;
}
// called using:
struct example *the_example;
create_object(&example);

Upvotes: 1

Related Questions