[英]Output behaviour of relational operators when used in printf - C Language
[英]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.