我对指针非常困惑。如果我们创建一个类型为' char'的指针变量,那就像char *ch;
那样,并为其分配一个字符数组。然后我们可以通过增加指针(++ ch)来访问字符串中的每个字母。
char *ch;
char a[5]="hello";
*ch=a;
while(*ch) {
printf("%c",*ch);
++ch;
}
这完全没问题。但我看到很多例子,
struct example {
char *ch;
};
int main() {
struct example ex={"hello"};
printf("%s",ex.ch);
}
我对这个例子非常困惑,比如如何直接将字符串分配给字符指针(而不是将字符串赋值给变量,然后将其分配给字符指针)可以使其可访问。在前一种情况下,* ch指向数组的起始内存" a"。但在第二种情况下,指针ch指向哪个内存?谁能给我一个明确的解释呢?
答案 0 :(得分:2)
进行此作业时
ch=a;
您正在将指针ch
设置为字符数组a[]
的开头(注意:数组保持空终止的事实纯属巧合 - 您的代码具有未定义的行为,因为'\0'
末尾的第六个字符"hello"
不会复制到五个字符的数组中。赋值ch
成为存储在数组a[]
中的C字符串的“别名”,这意味着您可以将它与字符串操作和格式化例程一起使用。
你的第二个例子不是作业,而是初始化:
struct example ex={"hello"};
用花括号括起来是一个初始化器。 C编译器将采用每个元素(您只有一个,但可能有很多)并将其分配给struct
的相应字段。在这种情况下,字符串文字"hello"
被分配给ch
成员。
初始值设定项的规则是按声明顺序分配花括号中的值。如果您希望使用C99的指定初始化程序功能,您有机会覆盖它:
struct example ex={ .ch = "hello"};
答案 1 :(得分:1)
此代码段
char *ch;
char a[5]="hello";
*ch=a;
while(*ch)
{
printf("%c",*ch);
++ch;
}
有未定义的行为。它可以正常工作你必须将字符数组声明为
char a[6]="hello";
或 char a [] ="你好&#34 ;;
在这种情况下,数组确实会有终止零。
至于此代码段
struct example
{
char *ch;
};
int main()
{
struct example ex={"hello"};
printf("%s",ex.ch);
}
然后在本声明中
struct example ex={"hello"};
编译器首先放置字符串文字" hello"在内存中作为具有类型char[6]
的字符数组,然后将指向数组的第一个元素的指针分配给结构的数据成员ch。
这两个声明之间的区别
char ch[] = "hello";
和
char *ch = "hello";
是在第一种情况下创建一个字符数组,其每个元素由字符串文字的相应字符初始化,该字符串文字本身不会存储在内存中。 在第二种情况下,字符串文字将存储在内存中,而指针ch将包含其第一个字符的地址。
答案 2 :(得分:0)
char a[] = "hi";
char *ch = "hello";
此处a
是一个大小为3字节的char数组,用于存储,' h
',' i
'和' \0
'。这个内存的3个字节在堆栈中分配以保留字符串。
这里ch
是一个指针变量,它存储一个char的地址,ch
的大小是4个字节来存储地址(指针的大小是编译器特定的)。然后" hello
"是一个常量字符串文字,它将作为只读数据存在于进程内存的文本段中。并且第一个字节的地址被分配给ch
变量。为ch
变量分配了4个字节的内存来存储堆栈中的地址,文本段中需要5个字节的内存来保持字符串文字" hello
"。
有关其他观点的解释,请阅读here。