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

时间:2020-05-20 13:19:12

标签: c arrays function pointers int

我是C语言的初学者,我正在尝试在函数中使用指针。

我正在尝试使用作为函数参数传递的指针来填充int的数组,但是我不知道如何正确地做到这一点。

如何正确执行此操作?

功能

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

ip是一个包含ipv4地址的char数组。

主要

int main() {

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

    //rest of my programm
} 

4 个答案:

答案 0 :(得分:0)

您可以将ipv4 int数组传递到指向int参数的指针,这将发生是它将衰减到指向其第一个元素的指针,以便与函数内部的数组一起正常工作您还应该传递数组的大小。

例如:

#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]);
        }
    }
}

这将需要进行验证,以检查ip char数组中的八位字节是否正确,但是我相信您已经做到了。

关于示例代码的最后一个注意事项,strtok将在ip char数组中进行更改,如果要防止这种情况,请对其进行复制并将其传递给函数,而不是传递给函数。原始IP。

答案 1 :(得分:0)

在C中,如果您声明一个数组(ipv4 [4]),则该数组具有用于其元素的内存,并且其指针是其名称(ipv4),其元素是ipv4 [0],ipv4 [1],ipv4 [2], ipv4 [3]。因此,如果要将数组传递给修改数组的函数(无效函数(int *数组)),则应仅使用指针,该指针应为function(ipv4);

但是在这种情况下,您没有将数组声明为数组,而是声明了一个指针,那么您没有足够的内存来存储这些指向poin的指针。 有很多方法可以获取这些指针的内存,例如,函数malloc或calloc。在这里,您尝试将char *分配给int *并不是一个好主意,因为当您执行ipv4 [2]等效于(ipv4 + 2)时,由于当您使用ipv4是char ipv4 + 2 ipv4增长2 * sizeof(char)。因此,现在,如果您将*(ptid + 2)ptid递增2 * sizeof(int),则该字符可以与chars相同或不相同。

我希望这会有所帮助。

答案 2 :(得分:0)

如果尝试直接使指向数组的指针相等,可能会出现警告和问题。因此,我对这个问题的解决方案是创建一个函数:

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

答案 3 :(得分:0)

将IP地址的点分符号的ASCII字符串转换为“ int”时,必须记住的一件事是,对于各种套接字例程,它必须采用网络字节顺序(相对于主机字节顺序)。 / p>

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

有多种功能可用于执行此转换(并转换回ASCII)。请查看手册页“ inet_addr()”,“ inet_aton()”以及相关的函数,以获取更详细的描述。

现在,您在注释中说ipv4应该是16的数组,但是在代码中已将其声明为4的数组。您需要更改它。如果每个inet例程都是以点号表示的字符串作为参数的函数之一,则它们将期望以null结尾的字符串。

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

这些功能之一可能也具有您想要在“验证”例程中进行的操作。

另一方面,如果您的问题是如何从通用的点分符号字符串转换为int或字节值序列,则将采用不同的方法。如果您不知道点之间有多少个值,可以考虑使用“ strtok”来解析字符串。例如:

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");
    }
}

在许多情况下,“ strtok”功能非常有用,但如果某些字段为空,则无法从具有逗号或制表符分隔字段的文件中解析行。例如,假设您正在解析一个包含以下内容的逗号分隔文件:

one,two,,four,,six

使用strtok,您将得到

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

您可能想获得的

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

要实现这一点,您需要编写自己的例程,如下所示:

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);
}

然后您将使用以下例程:

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);
}

哪个会给你:

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