首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >指针和指针指向指针的麻烦

指针和指针指向指针的麻烦
EN

Stack Overflow用户
提问于 2016-05-30 20:57:46
回答 1查看 91关注 0票数 8

我很难理解为什么一段代码能工作。以下是stdlib实现qsort的比较函数:

代码语言:javascript
复制
int scmp(const void *p1, const void * p2)
{
  char *v1, *v2;

  v1 = (char *) p1;
  v2 = (char *) p2;
  return strcmp(v1,v2);
}

当然,这只适用于字符串。我的问题是:为什么下面的代码起作用?

代码语言:javascript
复制
int scmp(const void *p1, const void * p2)
{
  char *v1, *v2;

  v1 = *(char **) p1;
  v2 = *(char **) p2;
  return strcmp(v1,v2);
}

在我看来,在第二个版本中,我正在有力地将一个char*转换为char**。问题是该变量仍将包含char变量的地址。当我应用*时,我的理解是C将通过获取p1的内容来处理这个命令,然后按照存储在其中的地址读取8个字节(在我的arch上),这样它最终将得到一个char*类型的值。在我看来,这将导致将8个字符合并到无效的内存地址中。

尽管如此,这两种功能仍然工作得很好。我哪里出问题了?

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2016-05-30 21:30:54

假设您希望使用int对数组进行排序。

代码语言:javascript
复制
int numbers[] = {10, 50, 35, 62, 22};

首先,创建一个可以比较两个int的函数。

代码语言:javascript
复制
int intCompare(void* p1, void* p2)
{
   int n1 = *(int*)p1;
   int n2 = *(int*)p2;
   return (n1 < n2);
}

然后,您可以使用:

代码语言:javascript
复制
qsort(numbers, 5, sizeof(int), intCompare);

numbers被传递给qsort时,它被腐化为int*,并被传递为void*。当我们需要从void*中的intCompare中提取数字时,我们需要在取消引用指针和比较值之前将其转换为int*

将类推到字符串,假设您想要排序:

代码语言:javascript
复制
char* strings[] = { "abc", "xyz", "def" };

qsort的调用将是:

代码语言:javascript
复制
qsort(strings, 3, sizeof(char*), scmp);

strings被传递给qsort时,它被腐化为char**,并被传递为void*。被qsort传递给qsort的指针的底层类型将是char**类型,而不是char*类型。因此,正确的做法是:

代码语言:javascript
复制
int scmp(const void *p1, const void * p2)
{
  char *v1, *v2;

  v1 = *(char **) p1;
  v2 = *(char **) p2;
  return strcmp(v1,v2);
}

第一个版本的工作是由于幸运巧合在某些情况下。这里有一个示例程序,它显示了几种情况,其中它不工作,而第二个版本应该总是工作。

代码语言:javascript
复制
#include <stdio.h>
#include <string.h>
#include <stdlib.h>

// First version of scmp
int scmp1(const void *p1, const void * p2)
{
  char *v1, *v2;

  v1 = (char *) p1;
  v2 = (char *) p2;
  return strcmp(v1,v2);
}

// Second version of scmp
int scmp2(const void *p1, const void * p2)
{
  char *v1, *v2;

  v1 = *(char **) p1;
  v2 = *(char **) p2;
  return strcmp(v1,v2);
}

void test1()
{
   char* strings[] = { "abc", "xyz", "def" };
   qsort(strings,  3, sizeof(char*), scmp1);
   for( int i = 0; i < 3; ++i )
   {
      printf("%s\n", strings[i]);
   }
   printf("\n");
}

void test2()
{
   char* strings[] = { "abc", "xyz", "def" };
   qsort(strings,  3, sizeof(char*), scmp2);
   for( int i = 0; i < 3; ++i )
   {
      printf("%s\n", strings[i]);
   }
   printf("\n");
}

void test3()
{
   char** strings = malloc(3*sizeof(char*));
   strings[0] = "abc";
   strings[1] = "xyz";
   strings[2] = "def";

   qsort(strings,  3, sizeof(char*), scmp1);
   for( int i = 0; i < 3; ++i )
   {
      printf("%s\n", strings[i]);
   }

   free(strings);
   printf("\n");
}

void test4()
{
   char** strings = malloc(3*sizeof(char*));
   strings[0] = "abc";
   strings[1] = "xyz";
   strings[2] = "def";

   qsort(strings,  3, sizeof(char*), scmp2);

   for( int i = 0; i < 3; ++i )
   {
      printf("%s\n", strings[i]);
   }

   free(strings);
   printf("\n");
}

int main()
{
   // Does not work.
   test1();

   // Should work always.
   test2();

   // Does not work.
   test3();

   // Should work always.
   test4();
}

产出(使用gcc 4.8.4):

代码语言:javascript
复制
abc
xyz
def

abc
def
xyz

abc
xyz
def

abc
def
xyz
票数 6
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/37533596

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档