简体   繁体   English

void 指向字符串指针的指针

[英]void pointer to string pointer

The compareStrings is going to compare two strings. compareStrings将比较两个字符串。 The code below works fine when the void pointer is cast to char pointer.当 void 指针被转换为 char 指针时,下面的代码工作正常。

int compareStrings(void *value1, void *value2) {
    const char *str1, *str2;

    str1 =  (char *)value1;
    str2 =  (char *)value2;

    return strcmp(str1, str2);
}

However, when I cast the type to pointer to pointer to a char, the code dumps segmentation fault error which I think, reasonably, it should not.但是,当我将类型转换为指向指向 char 的指针的指针时,代码会转储分段错误错误,我认为这是合理的,它不应该。

int compareStrings(void *value1, void *value2) {
    const char **str1, **str2;

    str1 =  (char **)value1;
    str2 =  (char **)value2;

    return strcmp(*str1, *str2);
}

Can anyone explain the problem with the second function?谁能解释第二个函数的问题?

UPDATE :更新

The complete code is:完整的代码是:

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


int compare(void *value1, void *value2);
int binarySearch(void **array, int size, void *value,
             int(*compareFunc)(void *, void *)); 
int compareStrings(void *value1, void *value2);

int binarySearch(void **array, int size, void *value,
             int(*compareFunc)(void *, void *)) {
    int low, mid, high, compareResult;

    low = 0;
    high = size;
    while (low < high) {
        mid = low + ((high - low) / 2);
        compareResult = (*compareFunc)(array[mid], value);
        if (compareResult < 0) {
            low = mid + 1;
        } else {
            high = mid;
        }
    }

    return low;
}

int compareStrings(void *value1, void *value2) {
    const char *str1, *str2;

    str1 =  (char *)value1;
    str2 =  (char *)value2;     

    return strcmp(str1, str2);
}


int main() {
    int nElements, maxStringLen, index;
    char **stringArray;
    char *sToFind;

    nElements = 10;
    maxStringLen = 100;   
    sToFind = NULL;
    stringArray = malloc(sizeof(char *) * nElements);

    for (int i = 0; i < nElements; i++) {
        stringArray[i] = malloc(sizeof(char) * maxStringLen);
        sprintf(stringArray[i], "sample%d", i+1);
    }

    sToFind = "sample3";
    index = binarySearch((void **)stringArray, nElements, sToFind,         compareStrings);
    if (index >= nElements) {
        printf ("ERROR: value %s not found at index %d\n", sToFind, index);
    }else{
        printf("item found at index %d!\n", index);     
    }

    for(int i = 0; i < nElements; i++) {
        free(stringArray[i]);
    }
    free(stringArray);

    return 0;   
} 

The problem is that your are casting a pointer and not transforming it into a pointer to a pointer.问题是您正在转换指针而不是将其转换为指向指针的指针。

The cast (char **) just change the type of the following expression, it do not transform it. cast (char **)只是改变以下表达式的类型,它不会转换它。 So the original and the resulting pointer are still the same pointer (they point the same place in memory), just the type is different.所以原始指针和结果指针仍然是同一个指针(它们指向内存中的同一个地方),只是类型不同。 So both points to a string.所以两者都指向一个字符串。 But with your cast you lie to the compiler: you are telling him that you know what you are doing, and that the pointer point to a pointer to a string.但是通过你的演员表,你对编译器撒了谎:你告诉他你知道你在做什么,并且指针指向一个指向字符串的指针。

So you get a segmentation fault: the pointer point to a text and not to a pointer to a text: you are deferencing a string and oops.因此,您会遇到分段错误:指针指向文本而不是指向文本的指针:您正在延迟字符串和哎呀。

You should have written:你应该写:

str1 =  (char **)&value1;

Note: your const char * is probably wrong.注意:您的const char *可能是错误的。 You are saying that the string is constant (and only the first one), not that the variable is constant (which should be written char * const ).你是说字符串是常量(并且只有第一个),而不是变量是常量(应该写成char * const )。

when I cast the type to pointer to pointer to a char, the code dumps segmentation fault error which I think, reasonably, it should not.当我将类型转换为指向指向 char 的指针的指针时,代码会转储分段错误错误,我认为这是合理的,它不应该。

When you cast the pointer to pointer that operation does not affect the casted pointer.当您将指针转换为指针时,该操作不会影响转换的指针。 It still points to same memory.它仍然指向相同的内存。 This is demonstrated by printout 3.打印输出3.证明了这一点3.

1. Original string addresses:
Address of str1= 0x55bc799fea65
Address of str2= 0x55bc799fea6a

3. The addresses after casting `(char **)` do not change:
Address of  (char **)value1= 0x55bc799fea65
Address of  (char **)value2= 0x55bc799fea6a

Casting is not & or * operation!强制转换不是&*操作!

When you do dereferencing by * that operation dereferences the value of the original pointer.当您通过*取消引用时,该操作会取消引用原始指针的值。

The result is not what you want:结果不是你想要的:

4.
Address of *(char **)value1= 0x343332 00 34 33 32 31
Address of *(char **)value2= 0x31     00 35 34 33 32    

These are not the addresses as you expected but the values of the strings.这些不是您预期的地址,而是字符串的值。

Those values are not the valid addresses!这些值不是有效地址! When you try to use them as the string addresses you will get segmentation fault in the strcmp function.当您尝试将它们用作字符串地址时,您将在strcmp函数中遇到分段错误。

Take a look at the demo program:看一下演示程序:

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

void print_addresses(char *nr, char *d1, void *a1, char *d2, void *a2)
{
    printf("%s.\nAddress of %s= %p\nAddress of %s= %p\n\n",nr, d1, a1, d2, a2);
}

int compareStrings1 (void *value1, void *value2)
{
    char *str1, *str2;

    str1 = (char *) value1;  
    str2 = (char *) value2;

    //2.
    print_addresses("2", "str1", str1, "str2", str2);

    return strcmp(str1, str2);
}

int compareStrings2(void *value1, void *value2) {
    char **str1, **str2;
    char **s1, **s2;    

    str1 =  (char **)value1;  //  warning: assignment from incompatible pointer type 
    str2 =  (char **)value2;  //  warning: assignment from incompatible pointer type 

   //3. Addresses after casting `(char **)` do not change:
    print_addresses( "3",  " (char **)value1", str1, " (char **)value2", str2);  // str1,str2 are still pointing to the original strings!
    //---------------------------------------------------------------------------------------------

    print_addresses( "4", "*(char **)value1", *str1, "*(char **)value2", *str2);  // '*' this dereferences the address to the value of the first character

    printf("(*str1)= %c\n", *str1);       //'*' this dereferences the address to the value of the first character
    printf("(*str2)= %c\n\n", *str2);       //'*' this dereferences the address to the value of the first character 

    // Now:

    s1 =  (char **) &value1;             // '&'' gives us pointer to pointer
    s2 =  (char **) &value2;             // '&'' gives us pointer to pointer

    //5.
    print_addresses( "5", " (char **) & value1" ,   s1, " (char **) & value2",   s2);    // pointer to pointer address 

    //6.
    print_addresses( "6", "*(char **) & value1",   *s1, "*(char **) & value2",  *s2);    // dereferencing pointer to pointer

    return strcmp(*s1, *s2);             // OK!
}

int main()
{
    char *str1 = "1234";
    char *str2 = "2345";  // 5 bytes

    //1.  Original string addresses:
    print_addresses("1", "str1", str1, "str2", str2);

    int res1 = compareStrings1(str1, str2);
    int res2 = compareStrings2(str1, str2);

   return 0; 
}

Output:输出:

1.
Address of str1= 0x55bc799fea65
Address of str2= 0x55bc799fea6a

2.
Address of str1= 0x55bc799fea65
Address of str2= 0x55bc799fea6a

3.
Address of  (char **)value1= 0x55bc799fea65
Address of  (char **)value2= 0x55bc799fea6a

4.
Address of *(char **)value1= 0x3433320034333231
Address of *(char **)value2= 0x310035343332

(*str1)= 1
(*str2)= 2

5.
Address of  (char **) & value1= 0x7ffd061f56b8
Address of  (char **) & value2= 0x7ffd061f56b0

6.
Address of *(char **) & value1= 0x55bc799fea65
Address of *(char **) & value2= 0x55bc799fea6a

I hope it helps.我希望它有帮助。

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

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