C-串指针指针



compareStrings将要比较两个字符串。当void指针被施加到炭指针时,下面的代码正常工作。

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 %dn", 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;   
} 

当我将类型施放到指针指向char指针时,代码转储 分段故障错误,我认为这不应该。

当您将指针指向指针时,该操作不会影响铸造的指针。它仍然指向相同的内存。这是由打印量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= %pnAddress of %s= %pnn",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)= %cn", *str1);       //'*' this dereferences the address to the value of the first character
    printf("(*str2)= %cnn", *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

我希望它有帮助。

问题是您正在铸造指针,而不是将其转换为指针变成指针。

铸件(char **)只是更改以下表达式的类型,它不会改变它。因此,原始指针和结果指针仍然是相同的指针(它们指向内存中的同一位置(,只有类型是不同的。因此,这两个指向字符串。但是,有了您的演员,您对编译器撒谎:您告诉他您知道自己在做什么,而指针指向弦指针。

因此,您会得到一个分段错误:指针指向文本,而不是指向文本指针:您是在递延字符串和糟糕。

您应该写信:

str1 =  (char **)&value1;

注意:您的const char *可能是错误的。您是说字符串是恒定的(并且只有第一个(,而不是变量是常数(应编写char * const(。

相关内容

  • 没有找到相关文章

最新更新