使用printf("%s",..)打印一个struct,struct的第一个变量类型是'char*',为什么可以得到一个存储在'char*'中的正确字符串?

tar*_*dis 4 c struct

在C语言中,定义一个这样的结构:

typedef struct str
{
    char *s;
    int len;
}str;


int main()
{
    str a;
    a.s = "abc"
    printf("%s", a);
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

输出是:"abc",我想知道为什么可以得到这个?
我猜编者认为printf("%s", a)printf("%s", *&a) 因为与一个等于&A.S,因此*a等于*A.S,对不对?

但如果是这样,如果我把int len结构体中的第一个放在这样:

typedef struct str
{
    int len;
    char *s;
}str;
int main()
{
    str a;
    a.len = 10;
    printf("%d", a);
}
Run Code Online (Sandbox Code Playgroud)

这次输出是:10,为什么?
也许编译器读取%d所以它知道应该打印一个整数值,只打印4个字节?我想得到一些解释.

Joh*_*nck 6

您正在调用未定义的行为.在编译器中启用警告和错误(例如gcc -Wall -Wextra -Werror),您执行这些恶作剧的能力将消失.

如果你真的想知道,那可能是因为当你将a值传递给printf()时,它的第一个成员就是char*printf()在查找要打印的字符串时所看到的内容.换句话说,你很幸运.


Nic*_*voz 5

您必须指定要打印的值,printf和C通常无法猜测:)

typedef struct str
{
    int len;
    char *s;
}str;
int main()
{
    str a;
    a.len = 10; // As you did there, you specify which value from your struct !
    printf("%d", a.len);
}
Run Code Online (Sandbox Code Playgroud)

否则,这是不确定的行为,Segfault就要来了!


Sea*_*ean 1

你正在做的是未定义的行为......

至于它为什么起作用,这取决于现在可变长度参数在 C 中工作的本质。像这样的函数printf依赖于格式字符串来告诉它们传递了什么类型的参数。在第一个示例中,您已经表明您正在传递一个字符串 ( %s),但实际上您传递了一个结构。该函数将在堆栈上printf查找指针,并且因为您的结构以字符串开头,所以它会找到一个!如果你交换和 的char*顺序,然后用 a调用,你将得到垃圾输出或访问冲突。slenprintf%s

同样的规则适用于您交换了顺序的第二个示例,但这次您尝试输出一个整数。您已将整个结构传递给调用,然后调用在堆栈上printf查找 a 。int因为该结构以 an 开头,int你很幸运!如果您没有交换场序,您会看到 10 以外的数字。