我是编程新手,有些部分让我在学习指针时感到困惑。
代码1:
int main()
{
char string[]="hello";
char *my_pointer=string;
printf("first character is %c", *my_pointer);
return 0;
}
输出:第一个字符是h
代码2:
int main()
{
char array_of_words[]="one\0two\0three";
char *my_pointer=array_of_words;
printf("%s \n",my_pointer);
return 0;
}
输出:一个
的问题:
我在这里混淆,第一个代码中的printf函数部分使用星号符号表示指向内部指针(my_pointer),这是变量字符串的地址,引用指向内存的数组的指针字符串数组“hello”中第一个单词的地址。我的理解是真的吗?
当我在printf中更改%c时(“第一个字符是%c”,* my_pointer); 到%s,程序崩溃了。我想知道为什么我不能使用%s 如果我不在printf中的my_pointer中使用星号(“第一个字符是%c”,my_pointer),那会有什么不同;
在第二个代码中,my_pointer变量在{printf(“%s \ n”,my_pointer);}中没有使用星号(*)。在这段代码中my_pointer是指array_of_words变量的地址还是my_pointer里面的内容?以及为什么输出是'一'而不是'o'?
答案 0 :(得分:5)
C字符串,数组和指针可能非常混乱。让我们来看看每个人是什么。
指针指的是内存中的地址。你似乎对它们有些熟悉。可以把它想象成一个储物柜钥匙 - 它告诉你在内存中你可以存储数据的地方。
当您声明一个数组时,编译器会设置一个内存区域来存储它。您调用该数组的变量可以被视为指向该数据开头的指针。例如,* string是字符串的第一个元素。
现在让我们将其应用到你的程序中。
两个程序都创建一个字符串并将my_pointer
设置为字符串开头的内存地址。 my_pointer=string
表示"将变量string
的内容(将其衰减到字符串开头的地址)复制到my_pointer
。"
在程序1中,将*my_pointer
读作" my_pointer
指向的内存地址的内容。"由于my_pointer
指向字符串的第一个元素,即字符h
。
为什么在替换%s
时它会崩溃?因为printf
需要一个指向字符串的指针,所以它可以遍历整个数组。由于C是按值复制的,因此给它第一个元素的值是没有意义的,因为它无法获得任何其他元素。结果,printf
尝试将字符作为内存地址读取,该地址失败。一个好的编译器可能会看到并给你一个警告。
现在程序2. my_pointer
引用内存中字符串的地址,而不是变量array_of_words
的地址。输出为one
因为printf
打印所有内容直到第一个空字符(\0
)。由于第一个空值就在one
之后,它会打印one
,然后点击空值并停止。
答案 1 :(得分:2)
当您声明char string[]="Hello"
时,您声明了一个字符数组。
string
指向数组的第一个元素。 *
被称为解除引用运算符。
假设ptr
是一个整数指针。 *ptr
将为您提供指针ptr
指向的内存位置的内容。在声明时,您必须将其声明为int *ptr
,以便编译器知道ptr是指针变量(因此在那里是星号)。
执行printf("first character is %c", *my_pointer);
时,函数需要一个与%c
对应的字符。声明char *string
和char string[]
大致(非完全)等效。 my_pointer
是一个字符类型指针。 *my_pointer
解除引用my_pointer
。换句话说,*my_pointer
为您提供my_pointer
的内容,即字符串中的第一个字符。
但是%s
期望一个字符串(一个字符数组,基本上是一个char指针)作为printf
中的对应参数。 *my_pointer
是一个角色。 my_pointer
可以视为字符串。此外,print
会将参数视为字符串并打印who; e,直到\0
。
my_pointer=array_of_words
将array_of_words
的值“分配”给my_pointer
。
array_of_words[]
是一个数组,因此array_of_words
的值基本上是数组第一个元素的内存地址(注意缺少[])。实际上my_pointer
现在指向数组的第一个元素。
希望这能解释它。
答案 2 :(得分:2)
第一个代码中的printf函数部分使用星号符号表示 指向内部指针(my_pointer)的内容是什么 变量字符串,用于引用数组的指针字符串 指向数组“hello”中第一个字的内存地址。是我的 理解是真的吗?
Ans :*my_pointer
中的printf
表示当前指针my_pointer
指向的内存地址所代表的值。即'h'
。指针不知道array
;它只知道一个内存地址。
你知道,声明和定义期间的*
意味着两件不同的事情。前者表示变量类型是指向char
类型值的指针,后者表示ValueOf operator(*)
当我在printf中更改%c时(“第一个字符是%c”,* my_pointer);至 %s,程序崩溃。我想知道为什么我不能使用%s
Ans :这是因为当printf
看到%s
占位符时,它希望提供的对象是一个指针,以便它可以从第一个char迭代到空值(\0
)。但在你的情况下,它发现char
也被认为是8位整数,因此渲染器开始从内存地址104
开始加载字符,直到找到\0
。因此,当分配内存不足时,它会崩溃。
如果我在printf中的my_pointer中没有使用星号(“第一个字符是%c”,my_pointer),那会有什么不同;
Ans :正如我已经说过的那样; char也是一个8位无符号整数,因此编译器认为你提供了一个char(因为my_pointer
返回内存地址,如果你还记得是整数)并尝试渲染它;但不幸的是,没有这样的可打印的字符,所以你看到一个空白。
在第二个代码中,my_pointer变量在{printf(“%s \ n”,my_pointer);}中没有使用星号(*)。在这段代码中my_pointer是指array_of_words变量的地址还是my_pointer里面的内容?
答案:我之前的话应该回答这个问题
为什么输出是'一'而不是'o'?
答案:您在字符串中有\0
个,printf
搜索\0
以了解该字符串已结束。所以第一次找到空值;它终止渲染。
答案 3 :(得分:1)
假设string
变量位于内存地址100。
在C中,自动附加NUL字符(\ 0)。
string
|-------|
|hello\0|
|-------|
100
char *my_pointer = string;
可分为2个陈述:
char *my_pointer;
my_pointer = string;
由于my_pointer是指向char的指针,因此my_pointer
的值是一个地址
它指向char。
my_pointer
|------|
|100 |
|------|
*my_pointer
是一种类似加法或减法的操作。
它意味着转到该内存地址并获取值。这有一个奇特的名字:DEREFERENCING。
*my_pointer
检索内存地址为100的第一个字符h
。现在为什么只是h
?不是其余的?这是因为printf()要求使用%c格式说明符的字符。如果你想要整个字符串,可以用
printf("%s\n", my_pointer );
请注意,没有解除引用字符。在这种情况下,my_pointer
成为100的内存地址。由于有%s格式说明符,它将从内存地址100读取,直到NUL字节字符为' \ 0'。这标志着字符串的结束。
转到第二个示例,array_of_words
有3个字符串。字符串的定义是当字符以\0
(NUL字符)结束时。
让我们说array_of_words
存储在200的内存地址中。
array_of_words
|-----------------|
|one\0two\0three\0|
|-----------------|
200
char *my_pointer=array_of_words;
my_pointer
|------|
|200 |
|------|
printf("%s \n",my_pointer);
returns characters starting from memory address of 200 till '\0' character.
这就是one
仅出现的原因。
希望我能正确解释并希望它能帮助你更好地理解。
指针是一个非常具有挑战性的主题。有关于这个主题的书籍。