我正在通过了解一点Python来“自学”“学习C”。我已经阅读了几个教程,但我无法理解指针和赋值的工作原理。我知道如果你取消引用指针,你可以直接给它一个值,如:
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[]
,int
,struct
,{{1 },void
,函数等)?即使是一个有助于我理解规则集的步骤列表也很有用。
答案 0 :(得分:2)
挂在那里!经过多次练习后,指针才有意义。但如有疑问,请尝试推断每个价值的含义。使用笔和纸来尝试绘制内存中的每个字节真的有帮助。
char *pointer_to_strlit;
- 在这里你声明一个指向一个角色的指针。您可能已经知道,C中的字符串由指向该字符串的第一个字符的指针表示。该字符串应该以null结尾。这意味着最终应该有一个ASCII 0
字符,表示字符串已经结束。
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
不是字符串的第一个字符,而是另一个数字 - 一个大数字的字节,指针。代码将尝试遍历它认为是字符串以查找空终止符,最终在到达不可访问的内存时崩溃。
答案 1 :(得分: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;
字符串文字位于只读位置。打开警告,编译器应该给你一些体面的消息。
答案 2 :(得分:1)
int *anint = 42;
此声明不正确。 anint
是指向int的指针,但您已将其初始化为int。
char *pointer_to_strlit;
char *strlit = "some stuff";
这些声明没问题。 "some stuff"
是一个字符串文字,在C中是char *
,因此可以用它初始化strlit
。
pointer_to_strlit = &strlit;
这是不正确的。 &strlit
是char**
,因为它是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
);
在这里,您使用strlit
作为%s
,这很好。然后你使用*pointer_to_strlit
作为%s
,这是错误的:%s
期望指向以空字符结尾的字符串,你给它一个char
,所以它是段错误的。