我有一个简单的程序:
#include <stdio.h>
struct time
{
int hours ;
int minutes ;
int seconds ;
} t[2] = {1,2,3,4,5,6};
int main() {
struct time *tt = t;
printf("%d\n", (*tt));
printf("%d", *(tt+1));
}
现在预期的输出应该是:
1
4
但是我得到的输出是2个完全相同的内存地址。我将此程序发送给其他人,有些人具有预期的输出,但有些人没有。我认为这是C或GCC版本的问题。它可以解决吗?为什么在我的C版本中会发生这种情况?
最奇怪的是,即使我取消了指针的引用,它仍然会打印一些地址。这怎么可能?
另一方面,如果我将程序更改为此:
$include <stdio.h>
struct time
{
int hours ;
int minutes ;
int seconds ;
} t[2] = {1,2,3,4,5,6};
int main() {
struct time *tt = t;
printf("%d\n", (*tt).hours);
printf("%d", (*(tt+1)).hours);
}
它将打印预期的输出。
对此行为有何解释?谢谢。
答案 0 :(得分:2)
问题不在编译器中,而是您对C的理解。让我们使用GCC版本7.3.0(Ubuntu 7.3.0-27ubuntu1〜18.04)进行编译:
% gcc struct_time.c
struct_time.c: In function ‘main’:
struct_time.c:12:14: warning: format ‘%d’ expects argument of type ‘int’,
but argument 2 has type ‘struct time’ [-Wformat=]
printf("%d\n", (*tt));
~^ ~~~~~
struct_time.c:13:14: warning: format ‘%d’ expects argument of type ‘int’,
but argument 2 has type ‘struct time’ [-Wformat=]
printf("%d", *(tt+1));
~^ ~~~~~~~
您的格式为%d
,它期望将int
作为相应的参数,并且您要传入struct time
。程序的行为是不确定的,因为转换说明符与实际参数的类型不匹配。
位置在内存中并不重要-它们的类型也很重要。尽管tt[0]
的地址与tt[0].hours
相同,但是它们具有不同的类型。在一个中,您需要整个结构,在另一个中,您需要第一个成员中包含的值。
答案 1 :(得分:1)
您的代码无效。这是您的编译器应产生的错误(也许您没有启用警告?):
error: format specifies type 'int' but the argument has type 'struct time' [-Werror,-Wformat]
printf("%d\n", (*tt));
您根本无法编写这样的代码,然后抱怨其行为。您告诉printf()传递整数,然后传递结构。什么都可能发生。
要获得加分,您会遇到样式问题,合理的编译器也会警告您:
error: suggest braces around initialization of subobject [-Werror,-Wmissing-braces]
} t[2] = {1,2,3,4,5,6};
那是因为您要用一个数字列表来初始化2个结构。应该是{{1,2,3},{4,5,6}}
。
答案 2 :(得分:0)
它的行为正常,因为数组用作指针(100%正常)
所以tt
指向第一个数组元素(索引为0),tt + 1
指向第二个数组元素(索引1)。
当您向该指针添加一个指针(并且该指针属于该结构的类型的指针)时,结果指针将引用该类型的下一个结构。
如果取消引用结构或联合的指针,请使用->
(*tt).hours
== tt -> hours
和(tt + 1).hours
== (tt + 1) -> hours