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

时间:2013-04-05 19:11:56

标签: c

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

#include <stdio.h>

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

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

6 个答案:

答案 0 :(得分:21)

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

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()字符

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

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

小心您的ptr 指向一个常量字符串,因此您无法在scanf中使用

  

为什么细分错误以下代码?

    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'和char'J'的ASCII值为74,但74地址不在您的过程控制之下,而您正试图从中读取内存位置及其发生内存冲突和分段错误。

如果您为包含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 

答案 1 :(得分:5)

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

基本上,这是有效的,因为你正在按照你想要的那样打印字符串。

答案 2 :(得分:1)

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

*name*ptr不是。如果您取消引用它们,则会返回一个char,它基本上位于printf - 导致未定义的行为。

答案 3 :(得分:1)

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

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

答案 4 :(得分:0)

*ptr基本上是对单个char的引用,而不是char的字符串。由于此char *char[]基本相同

答案 5 :(得分:0)

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

希望解释有助于: - )