C语言中字符指针的澄清

C语言中字符指针的澄清,c,pointers,character-arrays,C,Pointers,Character Arrays,我正在阅读《K&R》第二版第5章 在第87页,指向字符数组的指针介绍如下: char *pmessage; pmessage = "Now is the time"; 如何知道pmessage是指向字符数组的指针,而不是指向单个字符的指针 为了扩展,在第94页,定义了以下功能: /* month_name: return the name of the n-th month */ char *month_name(int n) { static char *name[] = {

我正在阅读《K&R》第二版第5章

在第87页,指向字符数组的指针介绍如下:

char *pmessage;
pmessage = "Now is the time";
如何知道
pmessage
是指向字符数组的指针,而不是指向单个字符的指针

为了扩展,在第94页,定义了以下功能:

/* month_name: return the name of the n-th month */
char *month_name(int n)
{
    static char *name[] = {
        "Illegal month",
        "January", "February", "March",
        ...
    };

    return (n < 1 || n > 12) ? name[0] : name[n];
}
/*month\u name:返回第n个月的名称*/
字符*月份名称(整数n)
{
静态字符*名称[]={
“非法月份”,
“一月”、“二月”、“三月”,
...
};
返回(n<1 | n>12)?名称[0]:名称[n];
}
如果只提供了上述函数声明,如何知道返回的是单个字符还是字符数组

如果假定从
month\u name()
返回的是一个字符数组,并对其进行迭代,直到遇到
NULL
,但返回的实际上是一个字符,那么是否存在分段错误的可能性

有人能演示一下单字符指针和字符数组指针的声明和赋值,它们与函数的用法以及返回的函数的标识吗?

怎么办

char *pmessage;
pmessage = "Now is the time";  
是什么意思?
char*pmessage
表示您将
pmessage
声明为指向
char

pmessage=“现在是时候了”
表示
pmessage
现在指向字符串文本的第一个字符
现在是时间

当您从函数返回
pmessage
时,将返回指向字符串文本的指针。
如果使用
%c
说明符打印
pmessage
,则它将打印
N
,如果使用
%s
打印,则它将打印整个字符串文字

printf("%c\n", *N);     // 'N' will be printed
printf("%s\n", N);      //  "Now is the time" will be printed 

因此,您有一个字符串文本,它是一个具有静态存储持续时间的字符数组:

"Now is the time"
在大多数情况下,数组将衰减为指向第一个元素的指针,这就是此处发生的情况:

pmessage = "Now is the time";
您需要以这样一种方式来设计和记录您的接口,即您知道输入和输出的预期结果。没有运行时信息来说明所指向内容的性质

例如,如果我们看一下数据,它告诉我们:

对strtok()的每次调用都返回一个指针,指向包含下一个令牌的以null结尾的字符串

因此,程序员确切地知道应该期望什么,并相应地处理结果


如果您有一个指向单个字符的指针,而它像一个C样式的字符串,那么您将有一个指针,因为您将访问超出范围的内存。分段错误是一种可能性,但未定义只是意味着结果不可预测。

奇怪的是,C信任程序员的智能。如果我看到一个函数,如:

/* month_name: return the name of the n-th month */
char *month_name(int n)
{
    static char *name[] = {
        "Illegal month",
        "January", "February", "March",
        ...
    };

    return (n < 1 || n > 12) ? name[0] : name[n];
}
/*month\u name:返回第n个月的名称*/
字符*月份名称(整数n)
{
静态字符*名称[]={
“非法月份”,
“一月”、“二月”、“三月”,
...
};
返回(n<1 | n>12)?名称[0]:名称[n];
}
我查看了文档,读到它返回一个以NUL结尾的字符串,该字符串是指向静态分配内存的指针。这对我来说已经足够了,可以像我应该做的那样对待返回值

如果函数的创建者在将来的版本中将返回值更改为不同类型的字符串,他们最好大声喊出来,更改函数名,或者说得非常清楚,否则从他们的角度来看,这是非常糟糕的行为

另一方面,如果我不能正确地处理返回值,即使它被正确地记录了,那么我就不会那么聪明,可能会成为一名Java开发人员

最后,如果功能没有记录,找到它的所有者并烧毁他的房子。1

1如果它在库中,则此版本已发布!不要在人们开始编写图书馆代码时就烧毁他们的房子^_^

如何知道pmessage是指向字符数组的指针,而不是指向单个字符的指针

你没有。至少,无法从指针值本身判断它是否指向单个
char
char
数组的第一个元素。这两种方法都可以使用

您必须依赖上下文或明确指定如何使用指针。例如,
scanf
使用不同的转换说明符来确定指针是否指向单个
char

char single_char;
scanf( " %c", &single_char );
char array_of_char[N];
scanf( "%s", &array_of_char[0] );
字符的数组

char single_char;
scanf( " %c", &single_char );
char array_of_char[N];
scanf( "%s", &array_of_char[0] );
请记住,当它不是
sizeof
或一元
&
运算符的操作数或用于初始化声明中另一个数组的字符串文字时,“t
的N元素数组”类型的表达式将被转换(“衰减”)为“指向
t
的指针”表达式,表达式的值将是数组第一个元素的地址,因此最后一行也可以被写入

scanf( "%s", array_of_char );
由于该转换规则,每当您将数组表达式传递给函数时,函数实际接收的是指针值。实际上,函数声明

void foo( char str[N] );

相当于

void foo( char *str );

这三种方法都将
str
视为指向
char
的指针

如何知道
pmessage
是指向字符数组的指针,而不是指向单个字符的指针?一个没有。但我们知道自己所使用的功能。如果一个人不知道他使用的函数返回什么,他怎么能期望创建一个能工作的程序呢?你不知道。更重要的是,你不知道它是否以null结尾。这有时会引起一些问题@ShafikYaghmour,可能由Java开发人员编写;)Shafik的回答从某人编写函数和使用他人函数的角度详细回答了提出的问题,而您的回答同样令人担忧