【问题标题】:Determine Palindrome - How does operator * work?确定回文 - 运算符 * 如何工作?
【发布时间】:2011-10-21 23:27:58
【问题描述】:

这个程序应该接受一个三位数并将其更改为回文。 123 将变为 321

逻辑正确,程序编译正确。 :) 然而,这些的逻辑来之不易。

我的教授用“堆栈图”解释了一些事情,我发现它们很有帮助。我基于另一个程序创建了这个程序,因为我注意到它和different program I made 之间的相似之处,但是指向是如何工作的呢?

#include <stdio.h>

void reverse_number(int in_val, int *out_val) {
    int ones, tens, hundreds;

    ones = in_val % 10;
    tens = (in_val % 100 - ones) / 10;
    hundreds = (in_val - (ones + tens)) / 100;

    *out_val = (ones * 100) + (tens * 10) + hundreds;
}

int main() {
    int in_val;
    int out_val;

    printf("Give a three digit num to reverse: \n");
    scanf("%d", &in_val);

    reverse_number(in_val, &out_val);
    printf("New number is: %d \n", out_val);

    return 0;
}

此外,我现在开始了解如何使用这些指针基于一种模板编写程序,并且我非常基本地了解参数中的星号的含义(声明为指针变量)。

例如,我知道m = &amp;q; 为变量m 提供另一个变量q 的地址,我知道m = *g; 意味着地址g 的值将进入m,但是我真的不熟悉这些在函数和主文件的上下文中是如何工作的。

如果有人能够阐述它(在这个程序中)如何工作的基本逻辑,那就太棒了。作为一名数学专业的学生,​​我可以理解数学和东西的操作,但指针并没有让我感到困惑,但在我看来,有一些方法可以做到这一点,而无需处理变量的地址等。

【问题讨论】:

  • 哦,天哪,在编辑这个问题和在程序编译的编译器中编辑程序之间。我的错。我应该删除问题吗?
  • 许多数据结构,如链表和树,如果不使用指针就无法创建。指针令人困惑——但它们并非无用。
  • 编辑您的问题以询问其工作原理:)
  • @Arthur Well 堆栈溢出背后的想法是提供集体知识。我会把它留在这里,因为下线的人可能会在搜索中找到它,并且证明对他们有用。另一种选择是看看你是否能找到它没有编译的原因,并将你的解决方案作为答案发布。
  • 您使用什么系统/编译器?使用 Linux/gcc 它可以编译并运行正常。

标签: c pointers palindrome


【解决方案1】:

当我运行它时,它会编译,甚至可以工作。见:http://ideone.com/RHWwI

所以它一定是你编译它的方式。你的编译器错误是什么?

【讨论】:

  • 是的,它非常好,但是对于在具有高级限制的终端上编译良好的东西,我遇到了很多运行时错误。有什么想法吗?
【解决方案2】:

好了,既然你对&amp;* 操作符已经完全理解了,那么剩下的就非常非常简单了。

假设你有:

int q;
int *m;
m = &q;

如果你说:

int *m2;
m2 = m;

m2 将包含与m 相同的值,即它的地址为q。因此,*m*m2 将给您相同的值(即q 的值)(您确实明白*&amp; 的逆运算符吧?所以*(&amp;q) = q&amp;(*m) = m(在后一种情况下,m需要是*的指针才能适用。))

那么,这如何与函数一起使用?简单的!当您将参数传递给函数时,您按值传递它们。当你通过指针传递时,你实际上是在传递值,即变量的指针。

让我们详细检查一下你的函数调用:

reverse_number(in_orig, &out_orig);

我将您的 in_valout_val 重命名为 in_origout_orig,这样它就不会与 reverse_number 的混淆。

现在,&amp;out_origout_orig 的地址。当作为参数传递时,它被复制到reverse_numberout_val 参数中。这和写作一模一样:

int *out_val = &out_orig;

现在,如果您的main 中有上述行,您可以只写*out_val = something;,它会更改out_orig,对吗?好吧,既然你在out_val 中有out_orig 的地址,那么谁在乎*out_val 是设置在main 还是reverse_number 中?

所以你看到了吗?当你有一个指针时,你可以复制它,无论是将它复制到另一个变量还是将它作为函数的参数传递(这基本上是同一件事),你仍然可以访问它指向的同一个变量。毕竟,所有副本都具有相同的值:out_orig 的地址。现在,如果您想在函数或main 中访问它,这并不重要。

编辑:指针定义中的*

* 也可以用来定义一个指针,这与之前使用* 作为获取地址值的运算符无关。

这只是定义,所以你必须学习它:

如果您有一个type 类型的值(例如int),那么该变量的地址(使用operator &amp;)的类型为type *(在本例中为int *)。由于指针采用该地址,因此指针的类型为type *

相反,如果指针的类型为type *(例如int *),则获取指针指向的值(使用operator *)的类型为type(在本例中为int )。

总而言之,你可以这样说:

operator &, adds one * to the type of the variable
operator *, removes one * from the type of the expression

让我们看一些例子:

int x;
x has type int
&x has type int *

float *y;
y has type float *
&y has type float **
*y has type float

struct Data ***d;
d has type struct Data ***
&d has type struct Data ****
*d has type struct Data **
*(*d) has type struct Data *
*(*(*d)) has type struct Data

如果你注意到了,我说过&amp;* 添加到变量 的类型,但*表达式 的类型中删除了一个*时间>。这是为什么?因为&amp; 给出了一个变量的地址。当然,因为没有其他东西有地址。例如a+b(可能)在内存中没有任何地址,如果有,它只是暂时的且无用的。

operator * 但是,适用于地址。无论您如何计算地址,operator * 都会对其进行处理。例子:

*(0x12345678) -> Note that even if the compiler let's you do this,
                 your program will most likely crash

*d -> like we saw before

*(d+4) -> This is the same as writing d[4]
          And now you know why arrays and pointers are treated as one

如果是动态二维数组:

*(*(d+4)+6) -> This is the same as writing d[4][6]

【讨论】:

  • 当你写“int *m;”时在前几行中,这意味着 m 被声明为指针,这意味着它是一个地址?编辑:这有点令人困惑。星号表示在一个地址处给出一个值,和号表示给出一个值的地址,但是当你想将一个变量声明为指针(地址)时,你可以写“int *p”或“float *k”。同样,当您在函数中编写整数参数时,您可以编写 void something(int *u, int *y) 并且这些参数是地址而不是地址的值。看起来星星意味着两个略有不同的东西
  • * 有两种含义。一,就像你说的“地址的值”(旁注:&amp; 不是值的地址,而是变量的地址)。与计算地址处的值 完全无关,* 用于定义指针。让我编辑我的答案,然后你阅读它。
  • 谢谢你 Shahbaz 我从来没有正确地表达我对你帮助我理解这些基础知识的感激之情。
猜你喜欢
  • 2020-01-29
  • 2011-02-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-10-25
  • 2017-11-30
相关资源
最近更新 更多