【问题标题】:purpose of using pointers in C [closed]在 C 中使用指针的目的 [关闭]
【发布时间】:2021-03-13 11:13:22
【问题描述】:

我无法理解使用指针的目的。下面的代码是使用指针打印给定字符串的所有排列。

#include<stdio.h>
#include<stdlib.h>
#include <string.h>

void swap(char *p1, char *p2) {
char pmt;
pmt = *p1;
*p1 = *p2;
*p2 = pmt;
}
void permutation(char *str, int index,int n ) {
int i; 
if (index == n) {
printf("%s ", str);
}
else {
for (i = index; i<=n; i++) {
swap((str+index), (str+i));
permutation(str, index+1, n);
swap((str+index), (str+i));
    }
  }
}

int main() {
char s[] = "ABCD";
int n = strlen(s);
permutation(s, 0, n-1);
printf("\n\n");
return 0;
}

如果我要删除指针,我的交换函数现在将变为

void swap(char p1, char p2) {
char pmt;
pmt = p1;
p1 = p2;
p2 = pmt;
}

我仍然会得到与带有指针的输出相同的输出。但是,需要注意的是我的输出会产生一些警告

grok1.c:23:6: warning: incompatible pointer to integer conversion passing 'char *' to parameter of type 'char'; dereference with * [-Wint-conversion]
swap((str+index), (str+i));
     ^~~~~~~~~~~
     *
grok1.c:10:16: note: passing argument to parameter 'p1' here
void swap(char p1, char p2) {
               ^
grok1.c:23:19: warning: incompatible pointer to integer conversion passing 'char *' to parameter of type 'char'; dereference with * [-Wint-conversion]
swap((str+index), (str+i));
                  ^~~~~~~
                  *
grok1.c:10:25: note: passing argument to parameter 'p2' here
void swap(char p1, char p2) {
                        ^
grok1.c:25:6: warning: incompatible pointer to integer conversion passing 'char *' to parameter of type 'char'; dereference with * [-Wint-conversion]
swap((str+index), (str+i));
     ^~~~~~~~~~~
     *
grok1.c:10:16: note: passing argument to parameter 'p1' here
void swap(char p1, char p2) {
               ^
grok1.c:25:19: warning: incompatible pointer to integer conversion passing 'char *' to parameter of type 'char'; dereference with * [-Wint-conversion]
swap((str+index), (str+i));
                  ^~~~~~~
                  *
grok1.c:10:25: note: passing argument to parameter 'p2' here
void swap(char p1, char p2) {

4 warnings generated.
ABCD ABCD ABCD ABCD ABCD ABCD ABCD ABCD ABCD ABCD ABCD ABCD ABCD ABCD ABCD ABCD ABCD ABCD ABCD ABCD ABCD ABCD ABCD ABCD 

如果有人可以帮助解释这些警告,我将不胜感激,因为我在这里有点挣扎。谢谢!

【问题讨论】:

  • 您的交换版本将无效。您实际上可以对其进行测试以反驳您的假设。
  • 如果您更改函数的签名(参数的数量和类型以及返回类型),您还必须更改调用方式:swap(str[i], str[j])。但如前所述,该函数交换两个局部变量,不会对您的排序产生任何影响。
  • 不管你怎么说,你的输出和非指针代码不一样。它是 ABCD 重复 24 次,而之前都是排列。

标签: c pointers permutation


【解决方案1】:

在回答这个问题之前,你需要先了解两件事: 首先,当您将字符串传递给函数时,实际上是将数组中第一个元素的地址传递给它。 其次,有两种方法可以将地址传递给函数;通过价值或参考! 现在您的置换函数接受一个地址作为第一个参数,即您的字符串“ABCD”;现在的问题是,当您将字符串传递给交换函数时,您没有给它两个要交换的字符串的地址,因此交换函数将创建字符串的两个副本并在内部交换它们,然后在函数终止时删除副本. 你需要做的是通过引用传递str来改变原来的值

【讨论】:

    【解决方案2】:

    指针是 C 编程的一个基本方面。我们必须在两种情况下使用指针:

    • 当我们希望函数修改参数时;
    • 当我们想要跟踪动态分配的内存时;

    指针在构建动态数据结构(如列表、树、队列等)时也很有用。我们可以使用指针来迭代数组或其他序列。我们可以使用指针来隐藏或隔离实现细节(FILE 类型就是一个很好的例子)。我们也可以使用指向函数的指针来实现回调或多态,但我将在这个答案中坚持使用对象指针。

    对象指针值通过以下三种方式之一获得:

    • 在变量上使用一元 &amp; 运算符1;
    • 调用返回指针值的库函数,例如malloccallocrealloc用于分配动态内存,还可以调用fopenstrchrstrtok等。 ;
    • 使用数组表达式;

    一个对象指针值是有效,如果它在对象的生命周期内指向一个对象。尝试通过无效指针读取或写入会导致未定义的行为。

    当您将数组表达式s 传递给排列时,您实际上传递的是数组第一个元素的地址。除非它是 sizeof 或一元 &amp; 的操作数,或者是用于在声明中初始化字符数组的字符串文字,否则将转换类型为“T 的 N 元素数组”的表达式,或“decay”,指向“pointer to T”类型的表达式,表达式的值将是数组中第一个元素的地址。因此,为什么您的 permutations 函数具有签名

    void permutations( char *str, int index, int n )
    

    由于str 具有char * 类型,表达式 str + indexstr + i 具有char * 类型。这就是为什么当您将 swap 更改为使用 char 而不是 char * 参数时收到所有警告的原因。 str + index 等价于表达式&amp;str[index]str + i 等价于&amp;str[i]

    请记住,C 通过值传递所有函数参数 - 函数定义中的形式参数是内存中与函数调用中的实际参数不同的对象,因此对形式参数的任何更改都不会反映在实际参数中。

    如果您将swap 定义为

    void swap(char p1, char p2) {
      char pmt;
      pmt = p1;
      p1 = p2;
      p2 = pmt;
    }
    

    并将其称为

    char a = 'a';
    char b = 'b';
    
    printf( "a = %c, b = %c\n", a, b );
    swap( a, b );
    printf( "a = %c, b = %c\n", a, b );
    

    那么你的输出将是

    a = a, b = b
    a = a, b = b
    

    要交换ab 的内容,必须使用指针:

    void swap(char *p1, char *p2) {
      char pmt;
      pmt = *p1;
      *p1 = *p2;
      *p2 = pmt;
    }
    ...
    printf( "a = %c, b = %c\n", a, b );
    swap( &a, &b );
    printf( "a = %c, b = %c\n", a, b );
    

    现在你的输出将是

    a = a, b = b
    a = b, b = a
    

    1. 从技术上讲,我们在 lvalue 上使用它,这是一个指定对象的表达式,以便可以读取或修改该对象。

    【讨论】:

      猜你喜欢
      • 2015-12-06
      • 2018-05-27
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-02-08
      • 1970-01-01
      • 2012-07-21
      • 2019-02-13
      相关资源
      最近更新 更多