printf(“c”和*(*(ptr+;i)和printf(“s”和*(*(ptr+;i)和#x2B;x))之间的差异

printf(“c”和*(*(ptr+;i)和printf(“s”和*(*(ptr+;i)和#x2B;x))之间的差异,c,pointers,printf,undefined-behavior,c-strings,C,Pointers,Printf,Undefined Behavior,C Strings,我有一个指针数组,当我尝试这个C代码时,得到了一个分段错误。我做错了什么 char *ptr[] = {"exam","example","testexample"}; printf("%c\n",*(*(ptr+2)+7)); printf("%s\n",*(*(ptr+2)+7)); 在给出预期结果的第一条打印语句的输出中 printf("%c\n",*(*(ptr+2)+7)); 但是第二个不是给出 mple 正在给予 printf("%s\n"

我有一个指针数组,当我尝试这个C代码时,得到了一个分段错误。我做错了什么

  char *ptr[] = {"exam","example","testexample"};
    printf("%c\n",*(*(ptr+2)+7));
    printf("%s\n",*(*(ptr+2)+7));
在给出预期结果的第一条打印语句的输出中

   printf("%c\n",*(*(ptr+2)+7)); 
但是第二个不是给出

  mple
正在给予

   printf("%s\n",*(*(ptr+2)+7));    Segmentation fault (core dumped)

我做错了什么?

表达式的类型

  char *ptr[] = {"exam","example","testexample"};
    printf("%c\n",*(*(ptr+2)+7));
    printf("%s\n",*(*(ptr+2)+7));
*(*(ptr+2)+7)
char
。因此,
printf
的第一个调用是正确的

但是第二个调用不正确,因为格式说明符
%s
需要类型为
char*
的参数。因此,通过表达式
*(*(ptr+2)+7)
获得的字符值,即字符
'm'
(例如,在ASCII中具有值
100
)被解释为地址

在第二次通话中,只需使用

*(ptr+2)+7
这是一个演示程序

#include <stdio.h>

int main(void) 
{
    char *ptr[] = { "exam", "example", "testexample" };

    printf( "%c\n", *( *( ptr + 2 ) + 7 ) );

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

    return 0;
}

表达式的类型

*(*(ptr+2)+7)
char
。因此,
printf
的第一个调用是正确的

但是第二个调用不正确,因为格式说明符
%s
需要类型为
char*
的参数。因此,通过表达式
*(*(ptr+2)+7)
获得的字符值,即字符
'm'
(例如,在ASCII中具有值
100
)被解释为地址

在第二次通话中,只需使用

*(ptr+2)+7
这是一个演示程序

#include <stdio.h>

int main(void) 
{
    char *ptr[] = { "exam", "example", "testexample" };

    printf( "%c\n", *( *( ptr + 2 ) + 7 ) );

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

    return 0;
}
您的参数
*(*(ptr+2)+7)
计算结果为一个字符,其值
'm'
,该值(在基于ASCII的平台上)与数字109相同

当你这样做的时候

printf("%s\n",*(*(ptr+2)+7));
这与

它被编译成机器代码,将数字109
加载到寄存器中,并将该寄存器推送到堆栈上。它没有告诉printf它在哪里找到的任何东西--
'm`--只有一个原始ASCII值被传递给函数

printf
然后尝试将109解释为指向某些字符的指针,而不是字符本身,因为这是您通过编写
%s
要求它执行的操作。不出所料,这会出现可怕的错误,因为109不是程序可以访问的任何内容的地址

如果要打印字符串的结尾,可以改为编写

printf("%s\n", *(ptr+2)+7 );
不将
*
运算符应用于要传递的指针。

您的参数
*(*(ptr+2)+7)
计算为一个值为
'm'
的字符,该值(在基于ASCII的平台上)与数字109相同

当你这样做的时候

printf("%s\n",*(*(ptr+2)+7));
这与

它被编译成机器代码,将数字109
加载到寄存器中,并将该寄存器推送到堆栈上。它没有告诉printf它在哪里找到的任何东西--
'm`--只有一个原始ASCII值被传递给函数

printf
然后尝试将109解释为指向某些字符的指针,而不是字符本身,因为这是您通过编写
%s
要求它执行的操作。不出所料,这会出现可怕的错误,因为109不是程序可以访问的任何内容的地址

如果要打印字符串的结尾,可以改为编写

printf("%s\n", *(ptr+2)+7 );
不将
*
运算符应用于要传递的指针。

((ptr+2)+7)是字符值

因此,第一条语句是正确的,因为“%c”告诉printf第一个参数是char:

printf("%c\n",*(*(ptr+2)+7));
但在第二条语句中,“%s”告诉printf第一个参数是(char*),即指向char的指针。 这样,当程序执行时

printf("%s\n",*(*(ptr+2)+7));
查看((ptr+2)+7)的值(一个char值,在本例中为'm'),就好像它是一个char指针。 这就是分割错误的原因

因此,更正后的secon声明将是

printf("%s\n",*(ptr+2)+7);
希望这有帮助。

((ptr+2)+7)是一个字符值

因此,第一条语句是正确的,因为“%c”告诉printf第一个参数是char:

printf("%c\n",*(*(ptr+2)+7));
但在第二条语句中,“%s”告诉printf第一个参数是(char*),即指向char的指针。 这样,当程序执行时

printf("%s\n",*(*(ptr+2)+7));
查看((ptr+2)+7)的值(一个char值,在本例中为'm'),就好像它是一个char指针。 这就是分割错误的原因

因此,更正后的secon声明将是

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

希望这能有所帮助。

问题在于表达式
*(*(ptr+2)+7)的使用。
很难看出它的作用。这种结构主要用于还不熟悉C语言的初学者。这就是为什么C有一个语法糖:
*(*(ptr+2)+7)
完全等同于
ptr[2][7]
,这是您应该使用的形式

现在,
ptr[2][7]
显然是一个
char
,但是
%s
需要一个指向
char
的指针,它是以null结尾的字符串中的第一个字符,所以让我们传入一个指向该字符的指针:


问题在于表达式
*(*(ptr+2)+7)
的使用-很难看出它的作用。这种结构主要用于还不熟悉C语言的初学者。这就是为什么C有一个语法糖:
*(*(ptr+2)+7)
完全等同于
ptr[2][7]
,这是您应该使用的形式

现在,
ptr[2][7]
显然是一个
char
,但是
%s
需要一个指向
char
的指针,它是以null结尾的字符串中的第一个字符,所以让我们传入一个指向该字符的指针:


在第二个示例中,您将字符值
'm'
用作无效指针值的指针。删除一个
*
作为
printf(“%s\n”,*(ptr+2)+7)一件更容易理解的事情是记住,对于任何指针
ptr
和索引
i
,表达式
*(ptr+i)
完全等于