C语言中的字符指针 #包括 内部主(空){ char*p=“你好”; p=“Bye”//为什么这是有效的C代码?为什么没有解封操作符? int*z; int x; *z=x z*=2//s z=2//不起作用,为什么它对字符起作用? char*str[2]={“你好”,“再见”}; print(“%s”,str[1]);//打印再见。为什么没有解扩操作符? //为什么这是有效的C代码?如果我创建了一个带指针的数组 //元素不应该打印内存地址而不是字符串吗? 返回0; }

C语言中的字符指针 #包括 内部主(空){ char*p=“你好”; p=“Bye”//为什么这是有效的C代码?为什么没有解封操作符? int*z; int x; *z=x z*=2//s z=2//不起作用,为什么它对字符起作用? char*str[2]={“你好”,“再见”}; print(“%s”,str[1]);//打印再见。为什么没有解扩操作符? //为什么这是有效的C代码?如果我创建了一个带指针的数组 //元素不应该打印内存地址而不是字符串吗? 返回0; },c,arrays,pointers,character,C,Arrays,Pointers,Character,我的问题与评论一起概述。在gerneal中,我很难理解字符数组和指针。具体地说,为什么我可以访问它们而不需要去法语操作符。当您键入“Bye”时,您实际上是在创建一个称为。这是一个特例,但本质上,当你这样做的时候 #include <stdio.h> int main(void){ char *p = "Hello"; p = "Bye"; //Why is this valid C code? Why no derefencing op

我的问题与评论一起概述。在gerneal中,我很难理解字符数组和指针。具体地说,为什么我可以访问它们而不需要去法语操作符。

当您键入“Bye”时,您实际上是在创建一个称为。这是一个特例,但本质上,当你这样做的时候

 #include <stdio.h>

  int main(void){

  char *p = "Hello";  
  p = "Bye";              //Why is this valid C code? Why no derefencing operator?

  int *z;
  int x;
  *z = x
  z* = 2                 //Works
  z  = 2                 //Doesn't Work, Why does it work with characters?

 char *str[2] = {"Hello","Good Bye"};

 print("%s", str[1]);      //Prints Good-Bye.     WHY no derefrencing operator?
                          // Why is this valid C code? If I created an array with pointers
                         // shouldn't the element print the memory address and not the string?
  return 0;

  }
您要做的是将这个字符串文本的地址分配给
p
(我认为编译器以依赖于实现的方式存储字符串本身)。正如Richard J.Ross III所解释的,从技术上讲,地址是字符数组的第一个元素

由于它是一种特殊情况,因此不适用于其他类型

顺便说一下,对于
char*p=“Hello”这样的行,您可能会收到编译器警告。您需要将它们定义为
const char*p=“Hello”因为修改它们是未定义的,如链接所述


至于打印代码

p = "Bye";
不需要解引用操作,因为内部
%s
需要传递指针(特别是
char*
),因此解引用由
printf
完成。当printf需要指针时,可以通过传递一个值来测试这一点。当它试图取消引用时,应该会出现运行时崩溃

print("%s", str[1]); 
是将文本的地址赋值给指针


运算符的工作方式与指针“数组”的引用增加n类似。这是不一样的,但它是这样工作的。

你混淆了一些东西:它对字符的作用就像它对整数的作用一样


它不能处理字符串,因为它们是字符数组,数组只能使用第一个元素的地址存储在变量中

稍后,您将创建一个字符指针数组或字符串数组。这意味着数组的第一个元素是字符串,第二个元素也是字符串。在打印部分,您使用的是数组的第二个元素。因此,毫不奇怪,第二个字符串被打印出来了

如果你这样看,你会发现语法是一致的。

记住
“Hello”
“Bye”
都是
char*
而不是
char

所以这一行,
p=“再见”
表示指针p指向一个
常量字符*
即“Bye”
但在下一种情况下,使用
int*

*z=2
表示

`由'z'指向的int'被赋值为2 虽然,
z=2
表示指针
z
指向相同的
int
,由
2
指向。但是,
2
不是指向其他
int
s的
int指针

在gerneal中,我很难理解字符数组和指针

这对于初学C语言的程序员来说是很常见的。我在1985年也有同样的困惑

array[n]
由于p被声明为char*,因此p只是一个包含char的内存地址的变量。上面的赋值将p的值设置为常量字符串“Bye”的第一个字符的地址,即字母“B”的地址

z被声明为char*,因此您唯一可以分配给它的是char的内存地址。不能将2赋给z,因为2不是字符的地址,而是一个常量整数值

z  = 2

在本例中,str被定义为两个char*变量的数组。在print语句中,您正在打印其中的第二个,即字符串“再见”中第一个字符的地址。

对于str[1],会发生解引用。在内部,它会像*(str+1)到p=“Bye”一样工作,实际上p是指向常量的指针,所以如果您喜欢*p='a';它在编译时不允许您使用,但由于您使用了p=“Bye”,它将为p提供一个新地址,因此它将work@user93353. 我确实买了一本书。这个密码来自一本书。谢谢你富有洞察力的评论。这本书没有解释发生了什么?你需要买一本更好的书——也许是克尼汉和里奇?可能是其中之一—您没有存储文本本身的地址—您(在几乎所有最近的编译器中)在静态分配的以null结尾的字符数组中存储第一个元素的地址。编译器本身之外没有字符串文字。因此,如果我分配字符串文字的地址,为什么在打印该地址的内容时仍然不需要*呢?@RichardJ.RossIII非常正确,但差异足够小,我觉得我的版本对新手来说可能更容易理解。@Vlad:您不需要*因为printf%s说明符知道它应该得到一个指向字符的指针。我知道它是以null结尾的字符数组的第一个元素,老实说,语法让我很困惑。所以,如果我打印字符串“再见”中第一个字符的地址,为什么要打印“再见”?这正是让我困惑的地方。@Vlad:%s说明符不只是看第一个字符('G')。之后,它会继续在内存地址中打印字符('o',然后是'o',等等)。当它看到一个内存地址的内容
p = "Bye";
z  = 2
print("%s", str[1]);