【问题标题】:Just want to know how this code written in C works [duplicate]只想知道用 C 编写的这段代码是如何工作的[重复]
【发布时间】:2021-10-11 18:39:49
【问题描述】:
#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

【问题讨论】:

  • 注意 - 虽然数据类型不同,但根本问题与重复(写入分配内存的边界之外)相同
  • 如果你写的是scanf("%[^\n]s", name);,那么崩溃的可能性会更大。
  • 另见this answer
  • [ 说明符之后的所有这些幻象 s 是怎么回事? (在问答和cmets中)
  • 由于scanfprintf 的参数类型不正确,还有未定义的行为

标签: c pointers input output ampersand


【解决方案1】:

通过使用与符号&amp;name,您实际上获取了变量name 的地址,它是一个指向char 的指针。是的,name 不指向任何地址,但它仍然是一个变量,并且它占用空间来存储其值,就像 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 上,如果我输入超过 8 个字符,我会得到 stack smashing error。但是,如果我输入abcdefgh 并使用printf("%p", name) 打印出name(不是&amp;name)的值,我将得到0x6867666564636261。回想一下,字符 a 的 ASCII 码是 97,也就是 0x61。由于我的电脑使用Little Endian Byte Order0x6867666564636261 的最低有效字节就是0x61。这意味着'a' 存储在name 的第一个字节,然后是'b''c' ...,就像一个字符数组一样。

【讨论】:

  • 别忘了 scanf 添加了一个空终止字节 - 所以实际上它是 3 或 7 个单字节字符。很好的解释。
【解决方案2】:

&amp;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

【讨论】:

    猜你喜欢
    • 2015-11-27
    • 2017-08-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-01-16
    • 2017-04-09
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多