简体   繁体   English

char和int的指针

[英]pointer of char and int

Hi I have a simple question 嗨,我有一个简单的问题

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

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

Why the first one works but the second one doesnot work? 为什么第一个有效但第二个有效? I think the first one should be 我认为第一个应该是

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

I think a stores the address of "abc". 我认为存储“abc”的地址。 So why it shows abc when i print a? 那么为什么我在打印时会显示abc? I think I should print *a to get the value of it. 我想我应该打印* a来获得它的价值。

Thanks 谢谢

Ying

Why the first one works but the second one doesnot work? 为什么第一个有效但第二个有效?

Because in the first, you're not asking it to print a character, you're asking it to print a null-terminated array of characters as a string. 因为在第一个,你不是要求它打印一个字符,你要求它打印一个以空字符结尾的字符数组作为字符串。

The confusion here is that you're thinking of strings as a "native type" in the same way as integers and characters. 这里的混乱是你将字符串视为“本机类型”,与整数和字符的方式相同。 C doesn't work that way; C不起作用; a string is just a pointer to a bunch of characters ending with a null byte. 字符串只是指向以空字节结尾的一堆字符的指针。

If you really want to think of strings as a native type (keeping in mind that they really aren't), think of it this way: the type of a string is char * , not char . 如果你真的想把字符串想象成一个本机类型(记住它们确实不是),那就这样想吧:字符串的类型是char * ,而不是char So, printf("%s\\n", a); 所以, printf("%s\\n", a); works because you're passing a char * to match with a format specifier indicating char * . 因为您传递char *以匹配指示char *的格式说明符,所以可以正常工作。 To get the equivalent problems as with the second example, you'd need to pass a pointer to a string—that is, a char ** . 要获得与第二个示例相同的问题,您需要将指针传递给字符串 - 即char **

Alternatively, the equivalent of %d is not %s , but %c , which prints a single character. 或者, %d的等价物不是%s ,而是%c ,它打印单个字符。 To use it, you do have to pass it a character. 要使用它, 必须通过它的字符。 printf("%c\\n", a) will have the same problem as printf("%d\\n", b) . printf("%c\\n", a)printf("%d\\n", b)具有相同的问题。


From your comment: 来自你的评论:

I think a stores the address of "abc". 我认为存储“abc”的地址。 So why it shows abc when i print a? 那么为什么我在打印时会显示abc? I think I should print *a to get the value of it. 我想我应该打印* a来获得它的价值。

This is where the loose thinking of strings as native objects falls down. 这是字符串作为本机对象的松散思维落空的地方。

When you write this: 当你写这个:

char *a = "abc";

What happens is that the compiler stores a array of four characters— 'a' , 'b' , 'c' , and '\\0' —somewhere, and a points at the first one, the a . 所发生的是,编译器存储阵列四个characters- 'a''b''c' ,和'\\0' -somewhere,和a在第一个点时, a As long as you remember that "abc" is really an array of four separate characters, it makes sense to think of a as a pointer to that thing (at least if you understand how arrays and pointer arithmetic work in C). 只要你记得"abc"实际上是一个包含四个独立字符的数组,那么将a视为指向该事物的指针是有意义的(至少如果你理解数组和指针算术在C中是如何工作的)。 But if you forget that, if you think a is pointing at a single address that holds a single object "abc" , it will confuse you. 但是如果你忘了这一点,如果你认为a指的是一个包含单个对象"abc" ,那么它会让你感到困惑。


Quoting from the GNU printf man page (because the C standard isn't linkable): GNU printf手册页引用(因为C标准不可链接):

d, i 我,我

The int argument is converted to signed decimal notation … int参数转换为带符号的十进制表示法...

c C

… the int argument is converted to an unsigned char, and the resulting character is written… ...将int参数转换为unsigned char,并将结果字符写入...

s 小号

… The const char * argument is expected to be a pointer to an array of character type (pointer to a string). ... const char *参数应该是指向字符类型数组(指向字符串的指针)的指针。 Characters from the array are written up to (but not including) a terminating null byte ('\\0') … 数组中的字符被写入(但不包括)终止空字节('\\ 0')...


One last thing: 最后一件事:

You may be wondering how printf("%s", a) or strchr(a, 'b') or any other function can print or search the string when there is no such value as "the string". 您可能想知道当没有“字符串”这样的值时, printf("%s", a)strchr(a, 'b')或任何其他函数如何打印或搜索字符串。

They're using a convention: they take a pointer to a character, and print or search every character from there up to the first null. 他们正在使用一种约定:它们使用指向一个字符的指针,并从那里打印或搜索每个字符直到第一个空值。 For example, you could write a print_string function like this: 例如,您可以像这样编写print_string函数:

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

Or: 要么:

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

Either way, you're assuming the char * is a pointer to the start of an array of characters, instead of just to a single character, and printing each character in the array until you hit a null character. 无论哪种方式,您都假设char *是一个指向字符数组开头的指针,而不是仅指向一个字符,并打印数组中的每个字符,直到您点击一个空字符。 That's the "null-terminated string" convention that's baked into functions like printf , strstr , etc. throughout the standard library. 这是“空终止字符串”约定,它被整合到标准库中的printfstrstr等函数中。

Strings aren't really "first-class citizens" in C. In reality, they're just implemented as null-terminated arrays of characters, with some syntactic sugar thrown in to make programmers' lives easier. 字符串在C语言中并不是真正的“一等公民”。实际上,它们只是作为空终止的字符数组实现,并带有一些语法糖,使程序员的生活更轻松。 That means when passing strings around, you'll mostly be doing it via char * variables - that is, pointers to null-terminated arrays of char . 这意味着当传递字符串时,你将主要通过char *变量来做 - 也就是指向以null结尾的char数组。

This practice holds for calling printf , too. 这种做法也适用于调用printf The %s format is matched with a char * parameter to print the string - just as you've seen. %s格式与char *参数匹配以打印字符串 - 正如您所见。 You could use *a , but you'd want to match that with a %c or an integer format to print just the single character pointed to. 您可以使用*a ,但是您希望将其与%c或整数格式匹配以仅打印指向的单个字符。

Your second example is wrong for a couple of reasons. 你的第二个例子是错误的,原因有两个。 First, it's not legal to make the assignment b = 1 without an explicit cast in C - you'd need b = (int *)1 . 首先,如果没有在C中显式转换,则赋值b = 1是不合法的 - 你需要b = (int *)1 Second, you're trying to print out a pointer, but you're using %d as a format string. 其次,您正在尝试打印指针,但您使用%d作为格式字符串。 That's wrong too - you should use %p like this: printf("%p\\n", (void *)b); 这也是错的 - 你应该像这样使用%pprintf("%p\\n", (void *)b); .

What it really looks like you're trying to do in the second example is: 你在第二个例子中尝试做的事实是:

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

That is, make a pointer to an integer, then dereference it and print it out. 也就是说,创建一个指向整数的指针,然后取消引用它并将其打印出来。

Editorial note: You should get a good beginner C book (search around here and I'm sure you'll find suggestions) and work through it. 编辑说明:你应该得到一本好的初学C书(在这里搜索,我相信你会找到建议)并通过它来完成。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM