简体   繁体   中英

Using a pointer to an array passed as a parameter of a function

I'm a beginner in C and I'm trying to use a pointer in my function.

I'm trying to fill an array of int by using a pointer passed as an argument of the function, but I don't know how to do it properly.

How can I do this correctly?

Function

int validate_ip(char *ip, int *ptid) { /*function where I want to use it*/ }

ip is a char array that contains an ipv4 address.

Main

int main() {

    int ipv4[4];
    int *ptid = ipv4;

    //rest of my programm
} 

You can pass the ipv4 int array to a pointer to int argument, what will happen is that it will decay to a pointer to its first element, to work properly with the array inside the function you should also pass the size of the array.

For example:

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

int validate_ip(char *ip, int *ptid, size_t size) {

    const char delim[] = ".";
    char *token;
    size_t i = 0;

    //tokenize the ip and convert it to int
    //this is for sample purposes, octet validation should be performed
    token = strtok(ip, delim);
    while (token != NULL && i < size) {
        ptid[i++] = atoi(token);
        token = strtok(NULL, delim);
    }
    return 1;
}

int main()
{
    char ip[] = {"192.168.0.3"}; //sample ip
    int ipv4[4];

    if(validate_ip(ip, ipv4, 4)){
        for (int i = 0; i < 4; i++)
        { 
            printf("%d ", ipv4[i]);
        }
    }
}

This will need the validations to check if the octets in the ip char array are correct, but I believe you already done that.

One last note regarding my sample code, strtok will make changes in the ip char array, if you want to prevent this, make a copy of it and pass it to the function instead of the original ip.

in C if you declare an array(ipv4[4]) it has memory for his elements and its pointer is its name(ipv4), its elements are ipv4[0],ipv4[1],ipv4[2],ipv4[3]. So if you want to pass an array to a function which modify the array(void function(int* array)) you should just use the pointer it would be function(ipv4);

But in this case you are not declaring your array as an array, you are declaring a pointer, then you dont have memory for these pointer to poin. There are a lot of ways to get memory for these pointer, for example the function malloc or calloc. Here you are trying to assign a char* to a int* which is not the best idea because when you do ipv4[2] is equivalent to (ipv4+2), cause ipv4 is a char when you do ipv4+2 ipv4 grows 2*sizeof(char). So now if you do *(ptid+2) ptid increments by 2*sizeof(int) which can or can not be the same as chars.

I hope that was helpfull.

There can be warnings and problems if you try to directly equalize a pointer to an array. So my solution to this problem is making a function:

void equalize(int * pointer, int[] array , int size){
    int i;
    for(i=0;i<size;i++){
        pointer[i]=array[i];}
    }
}

One thing you have to remember on converting an ASCII string of the dotted notation of an IP address to a "int" is that it needs to be in network byte order (vs host byte order) for the various socket routines.

https://www.ibm.com/support/knowledgecenter/en/SSB27U_6.4.0/com.ibm.zvm.v640.kiml0/asonetw.htm

There are various functions available for doing this conversion (and back to ASCII). Look at the man pages for "inet_addr()", "inet_aton()", and the associated functions for a more detailed description.

Now, you say in your comment that ipv4 should be an array of 16, but you have it declared as an array of 4 in your code. You need to change that. Each of the inet routines is going to expect a null terminated string if it is one of the functions that has a dotted notation string as a parameter.

https://linux.die.net/man/3/inet_aton

It's possible that one of these functions might have what you are wanting to do in your "validate" routine also.

On the other hand, if your question is just how to convert from a generic dotted notation string to a sequence of int or byte values, that would be approached different. If you do not know how many values are separated by the dots, you might want to consider using 'strtok' to parse the string. For example:

void main (int argc, char *arg )
{
    int   i;
    char  buffer[128];
    char  *token;

    for (i = 1; i < argv[i]; i++) {
        strcpy(buffer, argv[i]);
        printf("Converting '%s'... Bytes =", argv[i]);
        for (token = strtok(buffer, "."); token != NULL; token = strtok(NULL, ".")) {
            printf(" %d", atoi(token));
        }
        printf("\n");
    }
}

The 'strtok' function is very useful in a lot of situation, but it would not work for parsing lines from a file where you have comma or tab delimited fields if some of the fields were empty. For example, say you were parsing a comma delimited file that contained the following:

one,two,,four,,six

With strtok, you would get

'one'
'two'
'four'
'six'

whereas you probably wanted to get

'one'
'two'
''
'four'
''
'six'

To get that, you would need to write your own routine, something like this:

char  *ParseDelimited( char *str, char delimiter, char **resumePtr )
{
    char  *token;
    char  *p;

    if (str == NULL) {
        if (*resumePtr == NULL)
            return (NULL);

        token = *resumePtr;
        if (*token == '\0') {
            *resumePtr = NULL;
            return (token);
        }
    } else {
        token = str;

        if (*token == '\0') {
            *resumePtr = NULL;
            return (NULL);
        }
    } 

    p = token;
    while (*p != '\0') {
        if (*p == delimiter) {
            break;
        }
        p++;
    }

    /* At this point, p either points to a delimiter or a null character */
    if (*p != '\0') {
        *p = '\0';
        *resumePtr = p + 1;
    } else {
        *resumePtr = NULL;
    }
    return (token);
}

You would then use this routine like this:

char  buffer[1024];
char  *token;
char  resume;

strcpy(buffer, "one,two,,four,,six");
for (token = ParseDelimited(buffer, ',', &resume); token != NULL; token = ParseDelimited(NULL, ',', &resume)) {
    printf("'%s'\n", token);
}

Which would give you:

'one'
'two'
''
'four'
''
'six'

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM