为什么我不需要在打印之前取消引用C中的字符指针?

为什么这段代码有效? 我希望我需要取消引用ptrprintf("%s\n", *ptr); 在我打印之前,如果我尝试这样做,我会得到一个Segmentation Fault

 #include  int main(int argc, char *argv[]) { char name[] = "Jordan"; char *ptr = name; printf("%s\n", ptr); } 

希望你们能给我一些见解。

打印字符串时我们需要字符串的起始地址。

 printf("%s\n", ptr); ^ address with %s 

它打印字符直到\0 nul遭遇。

而打印聊天 int ..我们需要值变量

 printf("%c\n", *ptr); ^ * with %c print first char 

scanf()你总是需要给出一个字符串

 scanf("%s", ptr); ^ string address 

对于int scanf()一个char

 scanf("%c", ptr); ^ read at first location char address 

注意: Scanf()需要使用%c地址将扫描值存储在内存中。

小心你的ptr 指向一个常量字符串,所以你不能在scanf中使用

为什么Segmentation会出现以下代码?

  printf("%s\n", *ptr); 

当你这样做时,因为%s printf将*ptr解释为一个地址,但它实际上不是一个地址,如果你将它视为地址,它指向一个为你的程序读取保护的位置(进程)所以它会导致分段故障。

您的ptr通过name指向内存中的一些常量字符串(“Jordan”),如下图所示:

 name 2002 ┌─────┬─────┬─────┬─────┬─────┬─────┬─────┬─────┬─────┬─────┐ │ 'J' │ 'o' │ 'r' │ 'd' │ 'a' │ 'n' │'\0' │ ........ └─────┴─────┴─────┴─────┴─────┴─────┴─────┴─────┴─────┴─────┘ ^ | ptr = name ==> ptr = 2002 *ptr = 'J' 

printf("%s\n", *ptr); *ptr = 'J'*ptr = 'J' ASCII值是7474地址不在您的过程控制之下,并且您正在尝试从该内存位置读取并且发生内存冲突和分段错误。

如果编译包含printf("%s\n", *ptr);代码printf("%s\n", *ptr); 然后用适当的选项说-WallGCC你会收到如下警告:

warning: format '%s' expects argument of type 'char *', but argument 2 has type 'int'

%s需要(期望)一个char*类型的地址,但你正在投入价值

注意:

 printf("%s\n", *ptr); ^ ^ argument-2 argument-1 

这是因为传递给printf的格式字符串中的%s格式说明符意味着相应的参数应该是字符串,而不是单个字符。 在C中,字符串是指向一个字符块开头的指针,该字符块在结尾处具有空字符(值为0的字节)。

基本上,这是有效的,因为你正在做你应该打印的字符串。

格式说明符%s告诉printf期望指向以null结尾的char数组的指针。 这是什么nameptr

*name*ptr不是。 如果你取消引用它们,你将得到一个char ,它基本上是对printf – 导致未定义的行为。

printf的%s格式化程序需要一个“字符串”,它实际上是一个指向以null结尾的字符数组的指针。

也就是说,printf 希望你将指针传递给它。 取消引用指针时,它取字母J,其值在ascii中为74(十进制),并尝试将其视为指向数组的指针。 这是一个无法访问的内存区域,因此您会遇到分段违规。

*ptr本质上是对单个char的引用,而不是对char的字符串的引用。 由于这个char *char[]基本上是一回事

当您声明char prt = name时,您将解除引用它。 ”这里不是变量的一部分,只是表明你想要变量所指向的方式。 如果你要将* prt再次放入printf中,那么你要做两次。 name是一个字符数组,* ptr是一个指向这些字符的解引用指针。

希望解释有帮助:-)