1

嗨,我有一个简单的问题

char *a="abc";
printf("%s\n",a);

int *b;
b=1;
printf("%d\n",b);

为什么第一个有效,第二个无效?我觉得第一个应该是

char *a="abc";
printf("%s\n",*a);

我认为 a 存储“abc”的地址。那么为什么当我打印 a 时它显示 abc 呢?我想我应该打印 *a 来获得它的价值。

谢谢

4

2 回答 2

3

为什么第一个有效,第二个无效?

因为首先,您不是要求它打印一个字符,而是要求它打印一个以空字符结尾的字符数组作为字符串。

这里的困惑是您将字符串视为“本机类型”,其方式与整数和字符相同。C 不能那样工作;字符串只是指向以空字节结尾的一堆字符的指针。

如果您真的想将字符串视为本机类型(请记住它们实际上不是),请这样想:字符串的类型是char *,而不是char。因此,printf("%s\n", a);之所以有效,是因为您要传递 achar *以匹配格式说明符,指示char *. 要获得与第二个示例相同的问题,您需要传递一个指向字符串的指针,即 a char **.

或者,等效于%dis not %s, but %c,它打印单个字符。要使用它,您必须向它传递一个字符。printf("%c\n", a)将遇到与 相同的问题printf("%d\n", b)


从您的评论中:

我认为 a 存储“abc”的地址。那么为什么当我打印 a 时它显示 abc 呢?我想我应该打印 *a 来获得它的价值。

这就是将字符串视为原生对象的松散想法失败的地方。

当你写这个:

char *a = "abc";

发生的情况是,编译器存储了一个由四个字符组成的数组——<code>'a'、'b''c''\0'——某处,并a指向第一个字符,即a. 只要您记得它"abc"实际上是一个由四个单独字符组成的数组,就可以将其a视为指向该事物的指针(至少如果您了解数组和指针算术在 C 中的工作原理)。但是如果你忘记了这一点,如果你认为a它指向一个包含单个对象的单个地址"abc",那会让你感到困惑。


引用GNUprintf手册页(因为 C 标准不可链接):

d, 我

int 参数被转换为有符号十进制表示法……</p>

C

... int 参数被转换为无符号字符,并写入生成的字符...</p>

s

… const char * 参数应该是指向字符类型数组的指针(指向字符串的指针)。数组中的字符最多写入(但不包括)一个终止空字节('\0')……</p>


最后一件事:

您可能想知道当没有“字符串”这样的值时,如何printf("%s", a)或任何其他函数可以打印或搜索字符串。strchr(a, 'b')

他们使用约定:他们获取一个字符的指针,然后打印或搜索从那里到第一个 null 的每个字符。例如,您可以编写print_string如下函数:

void print_string(char *string) {
    while (*string) {
        printf("%c", *string);
        ++string;
    }
}

或者:

void print_string(char *string) {
    for (int i=0; string[i]; ++i) {
        printf("%c", string[i]);
    }
}

无论哪种方式,您都假设char *是指向字符数组开头的指针,而不仅仅是单个字符,并打印数组中的每个字符,直到您遇到空字符。这是“以空字符结尾的字符串”约定,在整个标准库中都融入了printf、等函数。strstr

于 2013-06-06T18:46:30.510 回答
1

字符串在 C 中并不是真正的“一等公民”。实际上,它们只是实现为以空字符结尾的字符数组,并添加了一些语法糖以使程序员的生活更轻松。这意味着在传递字符串时,您主要是通过char *变量来执行此操作 - 即指向以空字符结尾的char.

这种做法也适用于 call printf%s格式与打印字符串的参数相匹配——char *正如您所见。你可以使用*a,但您希望将其与 a%c或整数格式匹配以仅打印指向的单个字符。

由于几个原因,您的第二个示例是错误的。首先,在 C 中没有显式强制转换的情况下进行赋值是不合法的b = 1——你需要b = (int *)1. 其次,您试图打印出一个指针,但您将%d其用作格式字符串。这也是错误的 - 你应该使用%p这样使用: printf("%p\n", (void *)b);.

在第二个示例中,您真正想要做的是:

int b = 1;
int *p = &b;
printf("%d\n", *p);

也就是说,创建一个指向整数的指针,然后取消引用它并打印出来。

编者注:你应该得到一本很好的初学者 C 书(在这里搜索,我相信你会找到建议)并完成它。

于 2013-06-06T18:39:09.540 回答