繁体   English   中英

在C语言中传递结构变量时的printf行为

[英]printf behaviour on passing a structure variable in C language

我正在尝试一个程序来理解结构变量的行为,

示例代码:

struct temp
{
   int a;
   int b;
}obj;

int main()
{
   obj.a = 10;
   obj.b = 7;
   /* to see whether obj and &obj both are same 
    * I was verifying whether structure variables behave as arrays
    */
   printf("%d -- %p",obj,&obj); 
   return 0;
}

我期待输出为10和obj的地址但令我惊讶的是,实际输出为10和00000007

这对我来说很烦人!!!

谁能帮助我理解为什么printf正在接受第二个成员并打印其价值。

发生这种情况是因为第一个参数预计有4个字节(一个int),但它有8个字节(struct obj)。

当你将obj传递给printf函数时,它会将整个obj结构(包括b成员)放在堆栈上。 因此,当打印时,第一个参数(obj.a)的堆栈中的前4个字节和第二个参数的堆栈中的下一个4个字节(obj.b)。

看一下这个:

printf("%d %p %p\n", obj, &obj, &obj);

因为你正在把obj推到堆栈上。 换句话说,你将10和7整数推到那里,其中一个用于%d ,另一个用于%p 根本没有使用实际指针。

将行更改为:

printf("%d %d -- %p\n",obj,&obj);

你会得到类似的东西:

10 7 -- 0x804a01c

具有正确的地址:

这是帮助的图片:

What you push                 What printf uses
               +------------+
     /         |         10 |      %d
obj <          +------------+
     \         |          7 |      %p
               +------------+
&obj           | 0x80001234 |      not-used
               +------------+

当人们使用%d整数格式说明符将long传递给printf时,我遇到过类似的问题。 %d仅使用long的第一部分,第二部分使用所有其他参数。 详情请见此处

这就是为什么当你在printf系列函数中使用说明符不匹配时,gcc会弹出那些漂亮的小温暖消息:

qq.c: In function ‘main’:
qq.c:14: warning: incompatible implicit declaration of built-in function ‘printf’
qq.c:14: warning: format ‘%d’ expects type ‘int’, but argument 2
                  has type ‘struct temp’

您可能会花费大量时间来弄清楚为什么printf打印出打印的内容,甚至可以理解所有内容,只是为了稍后发现,在您的下一个实验中,您完全清楚的解释不再适用,您必须开始一切从头开始。

在这种情况下,真实且普遍适用的解释是您的代码产生未定义的行为 您为printf函数指定了%d格式说明符。 这意味着相应的参数必须具有int类型,只有int而不是int 您提供的是struct temp类型的对象,而不是int struct temp不是int 一旦你这样做,代码的行为是不确定的。 无论出于何种意义,它都可以打印绝对任何东西。 它什么都不打印。 它会崩溃。 形式上,它甚至可以格式化您的硬盘。 行为未定义。 这意味着,即使您设法“理解”当前程序的行为,它也可能会因为天气变化,日历上的日期发生变化或编译器版本发生变化而明天随机更改。

简而言之,您的代码没有任何意义(特别是因为格式说明符的问题)。 试图挑选无意义代码的行为是浪费时间。

printf函数采用可变数量的参数。 这意味着它不知道您在编译时传递给它的参数。 相反,它试图通过分析您传递的格式字符串在运行时实现这一点。

printf("%d -- %p",obj,&obj);

上面的代码按值推送obj结构,其大小为两个整数。 加上它的地址,它消耗一个整数的大小(假设32位架构)。

另一方面,根据格式字符串,您必须传递一个整数和一个地址。

你只是把它搞糊涂了。 它认为第二个结构成员b是传递的第二个参数,并将其作为指针打印出来。 这解释了00000007。

这是你必须做的:

printf("%d -- %p",obj.a,&obj);

暂无
暂无

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

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