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

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

我是 C 的初学者,我想在我的函数中使用指针。

我试图通过使用作为函数参数传递的指针来填充 int 的数组,但我不知道如何正确地完成它。

如何正确执行此操作?

函数

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

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

主要

int main() {

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

    //rest of my programm
} 

您可以将 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 字符数组中的八位字节是否正确,但我相信您已经做到了。

关于我的示例代码的最后一点说明,strtok 将在 ip char 数组中进行更改,如果您想防止这种情况发生,请复制它并将其传递给函数原来的ip。

在 C 中,如果你声明一个数组(ipv4[4]),它有存储他的元素,它的指针是它的名字(ipv4),它的元素是 ipv4[0],ipv4[1],ipv4[2 ]、ipv4[3]。因此,如果您想将数组传递给修改数组的函数(void function(int * array)),您应该只使用指针 function(ipv4);

但是在这种情况下,您没有将数组声明为数组,而是声明了一个指针,那么您就没有这些指针指向的内存。 有很多方法可以为这些指针获取内存,例如函数 malloc 或 calloc。在这里你试图将一个 char* 分配给一个 int* 这不是最好的主意,因为当你做 ipv4[2] 相当于 (ipv4+2) 时,因为 ipv4 是一个 char 当你执行 ipv4+2 时,ipv4 增长 2*sizeof(char)。所以现在如果你做 *(ptid+2) ptid 递增 2*sizeof(int) 这可以或不可以与 chars 相同。

希望对您有所帮助。

如果您尝试直接均衡指向数组的指针,可能会出现警告和问题。所以我解决这个问题的方法是创建一个函数:

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

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

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 例程都是以点分符号字符串作为参数的函数之一,则它会期望一个以空字符结尾的字符串。

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

这些功能之一可能也有您想要在 "validate" 例程中执行的操作。

另一方面,如果您的问题只是如何将通用的点分符号字符串转换为 int 或 byte 值序列,那将采用不同的方法。如果您不知道有多少个值由点分隔,您可能需要考虑使用 '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 == '[=14=]') {
            *resumePtr = NULL;
            return (token);
        }
    } else {
        token = str;

        if (*token == '[=14=]') {
            *resumePtr = NULL;
            return (NULL);
        }
    } 

    p = token;
    while (*p != '[=14=]') {
        if (*p == delimiter) {
            break;
        }
        p++;
    }

    /* At this point, p either points to a delimiter or a null character */
    if (*p != '[=14=]') {
        *p = '[=14=]';
        *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'