C s1与&;s1及;s1.a(结构)
当不与C s1与&;s1及;s1.a(结构),c,structure,C,Structure,当不与运算符一起使用时,结构变量包含什么 康涅斯特程序 #include<stdio.h> typedef struct{ char a; int b; } scratch; int main(){ scratch s1 = {2,4}; printf("%p",s1); o/p 000566000 printf(" %p",&s1); o/p 00000420 printf(" %p",&s1
运算符一起使用时,结构变量包含什么
康涅斯特程序
#include<stdio.h>
typedef struct{
char a;
int b;
} scratch;
int main(){
scratch s1 = {2,4};
printf("%p",s1); o/p 000566000
printf(" %p",&s1); o/p 00000420
printf(" %p",&s1.a); o/p 00000420
return 0;
}
#包括
类型定义结构{
字符a;
int b;
}刮擦;
int main(){
划痕s1={2,4};
打印件(“%p”,s1);o/p 000566000
printf(“%p”和&s1);o/p 00000420
printf(“%p”,&s1.a);o/p 00000420
返回0;
}
sturct变量s1
及其第一个成员s1.a
在与和一起使用时都返回相同的地址,但s1
返回一些其他值。这是垃圾还是什么
结构s1包含什么?(当我使用oops语言执行此操作时,对象变量打印一些与java相关的地址,java中没有地址运算符)
有人能告诉我s1在这里干什么吗?或者仅仅是编译器问题?这:
printf("%p",s1);
是无效的,可能是未定义的行为。格式说明符%p与结构不兼容。如果启用警告,GCC会告诉您:
format ‘%p’ expects argument of type ‘void *’, but argument 2 has type ‘scratch’ [-Wformat]
您所有的printf
语句都是非法的
在printf中(“%p”,s1)当预期为void*
时,传递code>typescratch
。这会导致未定义的行为
在printf中(“%p”和&s1)当需要void*
时,将传递code>typescratch*
。这会导致未定义的行为。使用printf(“%p”,(void*)&s1)代码>取而代之
在printf中(“%p”、&s1.a)当需要void*
时,传递code>typechar*
。这会导致未定义的行为。使用printf(“%p”,(void*)和s1.a)改为code>。关于printf(“%p”,s1)代码>-它是一个垃圾值,因为它(结构)与格式说明符%p
不兼容,因为它不是指针-它与编译器无关-它与函数printf()
和varargs的行为有关-请注意,当您只键入printf(“%d”)时
它将打印一个值,一个当时在堆栈内存中找到的随机值-printf()
认为您传输了两个参数,一个格式字符串和一个与格式说明符匹配的值,所以他使用varargs来提取变量(这显然不存在,因为我们没有传输它)它提取了一个随机的垃圾值。关于s1
和s1.a
具有相同的地址-这是因为整数a
是结构scratch
中的第一个变量,因此当您请求a
的地址时,您请求它开始的第一个字节(尽管这里是char
,所以它只是一个字节),结构本身(作为结构)不会消耗一些额外的内存,因此s1
和s1.a
具有相同的地址,因为s1.a
实际上是结构的第一个字节。&s1是s1的地址。
&s1.a是s1.a的地址,与s1的地址相同,因为“a”是结构的第一个元素
现在,“%p”用于打印指针地址。s1是结构实例,不是地址,因此不应使用“%p”打印。是否确定此处的输出正确
printf("%p",s1)
将取s1的值(即它表示的字节,具体取决于编译它的方式和目标机器体系结构),并将其视为指针。它在任何情况下都会生成编译器警告-
test.c:10:15: warning: format specifies type 'void *' but the argument has type 'scratch' [-Wformat]
对于未打包的结构,一个字符将占用4个字节(在大多数系统上,由实现定义)。结构布置如下所示
因此,s1内存中的布局是(在小端系统上)
0x02(字符)0x000000(3字节填充)0x04000000(整数)
如果您在64位little endian系统(64位指针)上打印出来,它将需要8个字节的指针地址,最小的字优先
因此,它将打印出来
0x400000002-在大多数现代系统上,如果填充字节初始化为零,或者堆栈恰好包含零。如果堆栈不包含零,则4到2之间的字节可能包含任何内容
当您打印出s1(&s1)或s1.a(&s1.a)的地址时,您打印出的是它们存储的实际内存地址,在这两种情况下都是相同的。这是正确的做法。你的第一段主要是错的,这将使你很难回答这个问题。C没有“类”,一般来说,一个对象是在“堆栈”上分配还是在“堆”上分配取决于它的类型是如何定义的。不,类成员不是在“堆”上分配的。我说的是“对象是在“堆栈”上分配还是在“堆”上分配取决于它的类型是如何定义的”。你知道你把你的问题标记为C而不是Java吗?@user3205479你的代码是C。你标记了你的问题C。你在询问操作符的地址。然后你突然开始谈论java?有意思。你真的毫无意义。我在这里完成了。问题仍然是,当您将s1
放在堆栈上调用printf()
时,C编译器会做什么。它会复制结构吗?是的,它会复制结构。printf将不正确地使用它,调用未定义的行为。它不一定是copy。有些编译器在堆栈上进行复制,并在后台传递该副本的地址。它是合法的,只要它表面上看起来像是传递价值。请记住,C标准甚至不需要堆栈,所以幕后发生的是实现定义的,这是未定义的行为。任何事情都有可能发生。在我的系统中,我确实看到“指针”的低位字节是2,正如您所期望的那样。但也许你的系统给了你一个不同的未定义的行为。这是允许的。请注意,对于我来说,它的结果类似于0x42ffa1b02
,而不是0x02
b