【问题标题】:Why don't I need to dereference a character pointer in C before printing it?为什么我不需要在打印之前取消引用 C 中的字符指针?
【发布时间】:2013-03-28 07:50:57
【问题描述】:

为什么这段代码有效?我希望我需要取消引用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);
}

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

【问题讨论】:

    标签: c


    【解决方案1】:

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

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

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

    而要打印 chat 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 值是 7474 地址不在您的进程控制之下,您正试图从该内存位置读取,并且它存在内存冲突和发生分段错误。

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

    【讨论】:

      【解决方案2】:

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

      基本上,这是可行的,因为您正在按照您应该做的事情来打印字符串。

      【讨论】:

        【解决方案3】:

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

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

        【讨论】:

          【解决方案4】:

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

          *name*ptr 不是。如果你取消引用它们,你会得到一个char,这基本上是在欺骗printf - 导致未定义的行为。

          【讨论】:

            【解决方案5】:

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

            【讨论】:

              【解决方案6】:

              当你声明 char prt = name 那就是你取消引用它的地方。这里的“”不是变量的一部分,只是一种显示你想要那个变量指向什么的方式。如果您要将 *prt 再次放入您的 printf 中,您将执行两次。 name 是一个字符数组, *ptr 是指向这些字符的解引用指针。

              希望解释有所帮助:-)

              【讨论】:

                猜你喜欢
                • 2013-04-01
                • 1970-01-01
                • 1970-01-01
                • 2015-03-07
                • 2015-10-15
                • 1970-01-01
                • 2022-01-02
                • 1970-01-01
                相关资源
                最近更新 更多