簡體   English   中英

void 指向字符串指針的指針

[英]void pointer to string pointer

compareStrings將比較兩個字符串。 當 void 指針被轉換為 char 指針時,下面的代碼工作正常。

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

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

    return strcmp(str1, str2);
}

但是,當我將類型轉換為指向指向 char 的指針的指針時,代碼會轉儲分段錯誤錯誤,我認為這是合理的,它不應該。

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

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

    return strcmp(*str1, *str2);
}

誰能解釋第二個函數的問題?

更新

完整的代碼是:

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

問題是您正在轉換指針而不是將其轉換為指向指針的指針。

cast (char **)只是改變以下表達式的類型,它不會轉換它。 所以原始指針和結果指針仍然是同一個指針(它們指向內存中的同一個地方),只是類型不同。 所以兩者都指向一個字符串。 但是通過你的演員表,你對編譯器撒了謊:你告訴他你知道你在做什么,並且指針指向一個指向字符串的指針。

因此,您會遇到分段錯誤:指針指向文本而不是指向文本的指針:您正在延遲字符串和哎呀。

你應該寫:

str1 =  (char **)&value1;

注意:您的const char *可能是錯誤的。 你是說字符串是常量(並且只有第一個),而不是變量是常量(應該寫成char * const )。

當我將類型轉換為指向指向 char 的指針的指針時,代碼會轉儲分段錯誤錯誤,我認為這是合理的,它不應該。

當您將指針轉換為指針時,該操作不會影響轉換的指針。 它仍然指向相同的內存。 打印輸出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

強制轉換不是&*操作!

當您通過*取消引用時,該操作會取消引用原始指針的值。

結果不是你想要的:

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

這些不是您預期的地址,而是字符串的值。

這些值不是有效地址! 當您嘗試將它們用作字符串地址時,您將在strcmp函數中遇到分段錯誤。

看一下演示程序:

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

輸出:

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

我希望它有幫助。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM