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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/26525394/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-02 11:29:58  来源:igfitidea点击:

use printf("%s",..) to print a struct, the struct's first variable type is 'char *', why can get a right string stored in 'char *'?

cstruct

提问by tardis

In C language,define a struct like this:     

在 C 语言中,定义一个结构体如下:     

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


int main()
{
    str a;
    a.s = "abc"
    printf("%s", a);
    return 0;
}

the output is: "abc", I want to konw why can get this?
I guess the complier think printf("%s", a)as printf("%s", *&a)because &a is equal to &a.s, so *&a is equal to *&a.s, right?

输出是:“abc”,我想知道为什么能得到这个?
我猜编译器认为printf("%s", a)printf("%s", *&a)因为 &a 等于 &a.s,所以 *&a 等于 *&a.s,对吗?

but if so, if I put the int lenat the first in the struct body like this:

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

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

this time the output is: 10, why?
Maybe compiler read %d so it knows that should print a integer value, only print 4 bytes? I want to get some explain about it.

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

采纳答案by Sean

What you're doing is undefined behaviour...

你在做什么是未定义的行为......

As for why it works, it's down to the nature of now variable length arguments work in C. Functions like printfrely on the format string to tell them what type of argument has been passed. In your first example you've indicated that you're passing a string (%s) but you've actually passed a struct. The printffunction will look for a char*pointer on the stack, and because your struct starts with a string it will find one! If you swap the order of sand lenaround and then call printfwith a %syou'll either get garbage output or an access violation.

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

The same rule applies to your second example where you have swapped the order but this time you're trying to output an integer. You've passed the entire structure to the printfcall which then looks for a inton the stack. Because the struct starts with an intyou got lucky! If you'd not swapped the field order around you'd have seen a number other than 10.

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

回答by Nicolas Charvoz

You must specify which value you want to print, printf and C in general cannot guess :)

您必须指定要打印的值,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);
}

Otherwise it's undefined behaviour and Segfault is coming !

否则它是未定义的行为,Segfault 来了!

回答by John Zwinck

You're invoking undefined behavior. Enable warnings and errors in your compiler (e.g. gcc -Wall -Wextra -Werror) and your ability to do these shenanigans will disappear.

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

If you really want to know, it's probably because when you pass aby value to printf(), its first member is the char*and that's what printf() sees when it looks for the string to print. In other words, you got lucky.

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