[英]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.