只想知道这段用 C 编写的代码是如何工作的
Just want to know how this code written in C works
#include <stdio.h>
int main(){
char *name;
printf("Enter a name: ");
scanf("%[^\n]s", &name);
printf("%s", &name);
return 0;
}
在这里,我创建了一个悬挂指针,即不指向任何地址,我尝试将一个字符串存储到其中,我发现在指针之前使用一个符号对 I-O 有效,但我只是不知道为什么。我刚刚开始使用 C.
输出结果如下
Enter a name: Joseph Tribbiani
Joseph Tribbiani
&name
表示“使用指针变量'name'的地址”作为scanf的目标。
scanf
正在使用指针变量地址(分配 4 或 8 个字节,具体取决于体系结构)并破坏堆栈(假设输入的字符超过 3 或 7 个)- 这对一个简单的主程序。 (为什么多于 3 或 7?因为 scanf
添加了一个空终止符。)
编译器警告可能显示为:
main.c:20:14: warning: format ‘%s’ expects argument of type ‘char *’, but argument 2 has type ‘char **’ [-Wformat=]
此程序显示损坏:
int main()
{
char s[20] = "Hello World\n"; // the storage for 's' is corrupted by the scanf
char *name;
printf("%s",s);
printf("Enter a name: ");
scanf("%[^\n]s", &name);
printf("%s\n", &name);
printf("%s",s);
}
产生:
Hello World
Enter a name: its a small world
its a small world
all world
通过使用符号 &name
,您实际上是在获取变量 name
的地址,它是一个指向 char 的指针。是的,name
没有指向任何地址,但它仍然是一个变量,它占用 space 来存储它的值,就像 int
变量一样。根据您的体系结构,name
占用 4 或 8 个字节。这意味着您可以将字节存储到这个 name
变量中,就像您存储任何其他变量一样。
您的代码有效,因为您使用变量 name
作为字符数组来存储您的输入。您 scanf
字符串并将其存储到 name
然后 printf
出来。在用完 name
的大小之前,您可以输入 4 个或 8 个单字节字符。 (UPD:感谢 Andy 的评论,因为 scanf
添加了一个空终止字节,它实际上是 3 或 7 个字符。我完全忘记了:p)
在我的 64 位 Ubuntu 20.10 和 gcc 10.3.0 上,我得到 stack smashing error if I input more than 8 chars. However, if I input abcdefgh
and print out the value of name
(not &name
) using printf("%p", name)
, I will get 0x6867666564636261
. Recall that the ASCII code for the character a
is 97, aka 0x61. And since my pc uses Little Endian Byte Order,0x6867666564636261
的最低有效字节只是 0x61
。这意味着 'a'
存储在 name
的第一个字节,然后是 'b'
、'c'
...,就像 char 数组一样。
#include <stdio.h>
int main(){
char *name;
printf("Enter a name: ");
scanf("%[^\n]s", &name);
printf("%s", &name);
return 0;
}
在这里,我创建了一个悬挂指针,即不指向任何地址,我尝试将一个字符串存储到其中,我发现在指针之前使用一个符号对 I-O 有效,但我只是不知道为什么。我刚刚开始使用 C.
输出结果如下
Enter a name: Joseph Tribbiani
Joseph Tribbiani
&name
表示“使用指针变量'name'的地址”作为scanf的目标。
scanf
正在使用指针变量地址(分配 4 或 8 个字节,具体取决于体系结构)并破坏堆栈(假设输入的字符超过 3 或 7 个)- 这对一个简单的主程序。 (为什么多于 3 或 7?因为 scanf
添加了一个空终止符。)
编译器警告可能显示为:
main.c:20:14: warning: format ‘%s’ expects argument of type ‘char *’, but argument 2 has type ‘char **’ [-Wformat=]
此程序显示损坏:
int main()
{
char s[20] = "Hello World\n"; // the storage for 's' is corrupted by the scanf
char *name;
printf("%s",s);
printf("Enter a name: ");
scanf("%[^\n]s", &name);
printf("%s\n", &name);
printf("%s",s);
}
产生:
Hello World
Enter a name: its a small world
its a small world
all world
通过使用符号 &name
,您实际上是在获取变量 name
的地址,它是一个指向 char 的指针。是的,name
没有指向任何地址,但它仍然是一个变量,它占用 space 来存储它的值,就像 int
变量一样。根据您的体系结构,name
占用 4 或 8 个字节。这意味着您可以将字节存储到这个 name
变量中,就像您存储任何其他变量一样。
您的代码有效,因为您使用变量 name
作为字符数组来存储您的输入。您 scanf
字符串并将其存储到 name
然后 printf
出来。在用完 name
的大小之前,您可以输入 4 个或 8 个单字节字符。 (UPD:感谢 Andy 的评论,因为 scanf
添加了一个空终止字节,它实际上是 3 或 7 个字符。我完全忘记了:p)
在我的 64 位 Ubuntu 20.10 和 gcc 10.3.0 上,我得到 stack smashing error if I input more than 8 chars. However, if I input abcdefgh
and print out the value of name
(not &name
) using printf("%p", name)
, I will get 0x6867666564636261
. Recall that the ASCII code for the character a
is 97, aka 0x61. And since my pc uses Little Endian Byte Order,0x6867666564636261
的最低有效字节只是 0x61
。这意味着 'a'
存储在 name
的第一个字节,然后是 'b'
、'c'
...,就像 char 数组一样。