C 指针到指针分段错误
我创建了一个插入排序方法,它接受数组、数组大小和比较器。比较器的功能如下:C 指针到指针分段错误,c,pointers,segmentation-fault,comparator,C,Pointers,Segmentation Fault,Comparator,我创建了一个插入排序方法,它接受数组、数组大小和比较器。比较器的功能如下: int compare_int_ptr(void* ptr1, void* ptr2) { double i1 = *(double*)ptr1; double i2 = *(double*)ptr2; if(i1<i2) { return -1; } if(i1 == i2) { return 0; } return 1; } void insertion_sort(
int compare_int_ptr(void* ptr1, void* ptr2) {
double i1 = *(double*)ptr1;
double i2 = *(double*)ptr2;
if(i1<i2) {
return -1;
}
if(i1 == i2) {
return 0;
}
return 1;
}
void insertion_sort(void** array, int size, CompFunction compare){
int i,j;
void* key;
for(i = 1; i<size;i++){
key = array[i];
for(j = i-1; j>=0 && compare(array[j],key)>=0;j--){
swap(&array[j+1],&array[j]);
}
array[j+1] = key;
}
}
int比较_int_ptr(void*ptr1,void*ptr2){
双i1=*(双*)ptr1;
双i2=*(双*)ptr2;
如果(i1=0;j--){
交换(&数组[j+1],&数组[j]);
}
数组[j+1]=键;
}
}
如果我尝试执行它,就会出现分段错误,因此我认为我没有正确使用指针。当我进行交换时,我将它与&一起传递,这是正确的吗
编辑:这是我调用方法的地方:
int main(int argc, char const *argv[]) {
if(argc < 2) {
printf("Usage: sortingfirstusage <file_name>\n");
exit(EXIT_FAILURE);
}
double* array = load_array(argv[1]);
insertion_sort((void**)array, 3, compare_int_ptr);
free(array);
return 0;
int main(int argc,char const*argv[]){
如果(argc<2){
printf(“用法:sortingfirstusage\n”);
退出(退出失败);
}
double*array=load_数组(argv[1]);
插入排序((void**)数组,3,比较整数ptr);
自由(数组);
返回0;
数组已正确加载,因为我在调用插入排序之前打印了所有元素,并且它们都已加载
void qsort( void *ptr, size_t count, size_t size,
int (*comp)(const void *, const void *) );
与qsort一样,排序函数应该将
void*
作为第一个参数,而不是void**
。调用insertion\u sort
时,应该注意到双间接寻址是一个错误。转换double[]
array tovoid**
需要强制转换,而它可以自动转换为void*
而不需要强制转换。如果不知道加载数组(argv[1]);的作用,答案是无法预测的,正如Peter在评论中所建议的那样
假设此函数调用正在执行合法的操作,并使用可以正确取消引用的指针加载数组,则问题在于强制转换。无法将指针转换为指向指针的指针。必须传递指针的地址才能完成所需的操作
insertion_sort(&array, 3, compare_int_ptr);
您正在尝试对一个双精度数组进行排序。
double*array
指向n
元素中的第一个元素:
array ==> [ double ] \
[ double ] |
. > n elements
. |
[ double ] /
您正在将array
强制转换为void**
:
(void **)array ==> [ void * ] \
[ void * ] |
. > n elements
. |
[ void * ] /
要确定前方是否有麻烦并不难。void*
不是double
。它可能与double
的大小相同,也可能不同。它几乎肯定不会指向有效的内存位置,因此,如果您取消引用它,您将调用未定义的行为,几乎肯定会导致您的程序失败g被信号杀死。不幸的是,insertion\u sort
函数在调用比较函数时会取消对它的引用:
key = array[i];
for(j = i-1; j>=0 && compare(array[j],key)>=0;j--){
array[i]
和array[j]
都是无效的void*
值(因为基础内存包含double
s,而不是void*
s)。您的比较函数在此处取消引用它们:
double i1 = *(double*)ptr1;
double i2 = *(double*)ptr2;
ptr1
和ptr2
包含无意义的指针值。它们不指向double
s。取消引用它们会调用未定义的行为
这是一个工作版本的
insertion\u sort
,使用了与C标准库中的qsort
函数相同的函数类型和等效功能(尽管该函数的效率远远低于qsort
):
插入\u排序.h:
#ifndef INSERTION_SORT_H_INCLUDED__
#define INSERTION_SORT_H_INCLUDED__
#include <stddef.h>
void insertion_sort(void *base, size_t nmemb, size_t size,
int (*compar)(const void *, const void *));
#endif
#include <string.h>
#include "insertion_sort.h"
void insertion_sort(void *base, size_t nmemb, size_t size,
int (*compar)(const void *, const void *))
{
char (*b)[size] = base;
size_t i;
size_t j;
int cmp;
for (i = 1; i < nmemb; i++) {
j = i - 1;
/* search backwards for insertion point */
while ((cmp = compar(b + j, b + i)) > 0 && j > 0)
j--;
if (cmp <= 0)
j++; /* went back one too far */
if (j < i) {
/* rotate element i to position j, j to j+1, ..., i-1 to i */
char tmp[size];
memcpy(&tmp[0], &b[i][0], size);
memmove(&b[j + 1][0], &b[j][0], size * (i - j));
memcpy(&b[j][0], &tmp[0], size);
}
}
}
#include <stdio.h>
#include "insertion_sort.h"
int compar_double(const void *a, const void *b)
{
double d1 = *(const double *)a;
double d2 = *(const double *)b;
if (d1 < d2)
return -1;
if (d1 > d2)
return 1;
return 0;
}
void print_doubles(const double *d, size_t n)
{
size_t i;
for (i = 0; i < n; i++)
printf("%g\n", d[i]);
}
int main(void)
{
double numberlist[] = { 3.0, 1.0, 5.0, -4.0, 2.0 };
size_t len = sizeof numberlist / sizeof numberlist[0];
printf("Unsorted:\n");
print_doubles(numberlist, len);
printf("\n");
insertion_sort(numberlist, len, sizeof numberlist[0], compar_double);
printf("Sorted:\n");
print_doubles(numberlist, len);
return 0;
}
请。更具体地说,请学习如何使用调试器在崩溃发生时捕获崩溃,以及如何在代码中定位崩溃发生的时间和地点。您还需要提供有关如何调用函数的信息。如果调用方传递的指针与函数预期/假设的指针不同,则I’我会解释你的问题。但是,如果没有这些信息,没有人能帮你诊断。更一般地说,当你问问题时,最好提供一个(按照链接了解更多信息)。错误在哪里?您没有显示数组是如何生成的。如果这是错误的,则会出现错误。您没有显示交换正在执行的操作。它似乎包含指针,但没有大小。它是函数还是宏?问题编辑请验证a我在调用中进行了转换:插入排序((void**)数组,3,比较int\ptr);我的问题(我猜)是使用指针。我需要将数组用作void**。
void**
是不正确的。请尊重编译器在没有强制转换时打印的错误。使用void**
完全是错误的。为什么这个答案被否决了?它指出了代码的一个完全合法的问题,不是吗?
Unsorted:
3
1
5
-4
2
Sorted:
-4
1
2
3
5