简体   繁体   English

使用指向作为 function 参数传递的数组的指针

[英]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.我是 C 的初学者,我正在尝试在我的 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.我正在尝试使用作为 function 的参数传递的指针来填充int数组,但我不知道如何正确执行。

How can I do this correctly?我怎样才能正确地做到这一点?

Function 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. ip是一个包含 ipv4 地址的 char 数组。

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.您可以将 ipv4 int数组传递给指向int参数的指针,将会发生的情况是它将衰减为指向其第一个元素的指针,以便与 function 内的数组正常工作,您还应该传递数组的大小。

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.这将需要验证以检查 ip 字符数组中的八位字节是否正确,但我相信您已经这样做了。

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.关于我的示例代码的最后一个注意事项, strtok将在 ip char数组中进行更改,如果您想防止这种情况发生,请将其复制并传递给 function 而不是原始 Z957B527BCFCAD2E80F58D2063。

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].在 C 中,如果你声明一个数组(ipv4[4]),它的元素有 memory,它的指针是它的名称(ipv4),它的元素是 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);因此,如果您想将数组传递给修改数组的 function(void 函数(int* 数组)),您应该只使用指针函数(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.但是在这种情况下,您不是将数组声明为数组,而是在声明一个指针,那么这些指向指针的指针就没有 memory。 There are a lot of ways to get memory for these pointer, for example the function malloc or calloc.有很多方法可以为这些指针获取 memory,例如 function malloc 或 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).在这里,您尝试将 char* 分配给 int*,这不是最好的主意,因为当您执行 ipv4[2] 时,它等同于(ipv4+2),因为当您执行 ipv4+2 时,ipv4 是一个字符ipv4 增长 2 *大小(字符)。 So now if you do *(ptid+2) ptid increments by 2*sizeof(int) which can or can not be the same as chars.所以现在如果你做 *(ptid+2) ptid 增加 2*sizeof(int) 可以或不能与字符相同。

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:所以我对这个问题的解决方案是制作一个 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.在将 IP 地址的点分符号的 ASCII 字符串转换为“int”时,您必须记住的一件事是,对于各种套接字例程,它需要采用网络字节顺序(相对于主机字节顺序)。

https://www.ibm.com/support/knowledgecenter/en/SSB27U_6.4.0/com.ibm.zvm.v640.kiml0/asonetw.htm 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).有多种函数可用于进行这种转换(并返回 ASCII)。 Look at the man pages for "inet_addr()", "inet_aton()", and the associated functions for a more detailed description.查看“inet_addr()”、“inet_aton()”和相关函数的手册页以获得更详细的描述。

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.现在,您在评论中说 ipv4 应该是 16 的数组,但您在代码中将其声明为 4 的数组。 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.如果每个 inet 例程是具有点分符号字符串作为参数的函数之一,则每个 inet 例程都将期望 null 终止字符串。

https://linux.die.net/man/3/inet_aton 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.另一方面,如果您的问题只是如何从通用的点表示法字符串转换为 int 或 byte 值的序列,那将采用不同的方法。 If you do not know how many values are separated by the dots, you might want to consider using 'strtok' to parse the string.如果您不知道有多少个值被点分隔,您可能需要考虑使用 'strtok' 来解析字符串。 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. 'strtok' function 在很多情况下都非常有用,但如果某些字段为空,则它不适用于解析具有逗号或制表符分隔字段的文件中的行。 For example, say you were parsing a comma delimited file that contained the following:例如,假设您正在解析包含以下内容的逗号分隔文件:

one,two,,four,,six

With strtok, you would get使用 strtok,你会得到

'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'

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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