0

我正在通过了解一点 Python 来进行自学“Learn C the hard way”。我已经阅读了几个教程,但我无法理解指针和赋值是如何工作的。我知道如果您取消引用指针,您可以直接给它一个值,如下所示:

int *anint = 42;

但是具体引用一个已经创建的变量的内存位置呢?具体来说,我试过:

char *pointer_to_strlit;
char *strlit = "some stuff";
pointer_to_strlit = &strlit;

为什么在我这样做之后会导致段错误:

printf("I print strlit: %s\nI print it again by pointing to it: %s\nI print where the pointer is pointing: %p\n", strlit, *pointer_to_strlit, pointer_to_strlit);

C 中的类型似乎很难说明它们的行为方式以及如何使用指针来引用特定类型。是否有明确的指南专门概述了指向每种不同数据类型(char*char*char[]intstructvoidnull、 函数等)的语法?甚至可以帮助我理解规则集的步骤列表也会很有用。

4

3 回答 3

2

挂在那里!经过更多的练习,指针会变得有意义。但是如果有疑问,请尝试推理每个值的含义。使用笔和纸尝试绘制内存中的每个字节确实很有帮助。

char *pointer_to_strlit;- 在这里你声明一个指向一个字符的指针。您可能已经知道,C 中的字符串由指向该字符串第一个字符的指针表示。该字符串应以空值结尾。这意味着最终应该有一个 ASCII0字符表示字符串已经结束。

char *strlit = "some stuff";- 您的程序内存将包含此字符串的字符(准确地说是 11 个字符——您看到的文本有 10 个字符,空终止符有 1 个)。在这里,您声明了另一个指针,这次指向该字符串中的第一个字符“s”。

pointer_to_strlit = &strlit;- 这将值设置为指针pointer_to_strlit地址strlit。这可能不是您想要的。

如果事情变得混乱,试着把每个指针想象成一个普通的旧数字——本质上就是指针,一个代表内存地址的巨大数字。让我们再看一遍上面的内容:

char *pointer_to_strlit;- 这里的值pointer_to_strlit是未定义的,因为你还没有设置它。

char *strlit = "some stuff";- 假设第一个“s”的地址是1234500。的值strlit将是那个数字,1234500

pointer_to_strlit = &strlit;- 但是它自己的地址是strlit什么?假设是其他值1234600。的值pointer_to_strlit现在将是1234600

尝试pointer_to_strlit%s现在打印,您的程序将崩溃——地址1234600不是字符串的第一个字符,而是另一个数字——巨大数字的字节之一,即指针。代码将尝试遍历它认为是字符串以查找空终止符,最终在到达无法访问的内存时崩溃。

于 2012-07-09T02:21:22.300 回答
1
int *anint = 42;

42 是一个整数文字,anint应该保存指向整数的地址,而不是整数本身。

char *pointer_to_strlit;
char *strlit = "some stuff";    // Should be const char *strlit = "some stuff";
pointer_to_strlit = &strlit;    // Wrong

&strlit给出指针的地址(即 char **),而pointer_to_strlit它的类型为 char*。所以,应该是

pointer_to_strlit = strlit;

字符串文字位于只读位置。打开警告,编译器应该会给你一些不错的消息。

于 2012-07-09T02:21:59.827 回答
1
int *anint = 42;

这个声明是不正确的。 anint是指向 int 的指针,但您已将其初始化为 int。

char *pointer_to_strlit;
char *strlit = "some stuff";

这些声明很好。 "some stuff"是一个字符串文字,在 C 中是 a char *,所以可以用它来初始化strlit

pointer_to_strlit = &strlit;

这是不正确的。 &strlit是 a char**,因为它是 a 的地址char*

printf(
    "I print strlit: %s\n"
    "I print it again by pointing to it: %s\n"
    "I print where the pointer is pointing: %p\n", 
    strlit, *pointer_to_strlit, pointer_to_strlit
);

在这里你使用strlitas %s,这很好。然后你使用*pointer_to_strlitas %s,这很糟糕:%s需要一个指向以空字符结尾的字符串的指针,你给了它一个char,所以它出现了段错误。

于 2012-07-09T02:28:27.400 回答