简体   繁体   English

结构指针-使用指针访问结构数组

[英]Structure Pointers - Accessing array of structure using pointers

I have this simple program: 我有这个简单的程序:

#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));
}

Now the expected output should be: 现在预期的输出应该是:

1
4

But the output I am getting is 2 exactly same memory addresses. 但是我得到的输出是2个完全相同的内存地址。 I sent this program to other people and some are having the expected output but some aren't. 我将此程序发送给其他人,有些人具有预期的输出,但有些人没有。 I reckon this is an issue with version of C or GCC. 我认为这是C或GCC版本的问题。 Is it resolvable ? 它可以解决吗? Is there any explanation as to why this is happening in my version of C? 关于为什么在我的C版本中会发生这种情况,是否有任何解释?

The most weird thing is that even after I have dereferenced the pointer, it still printing some address. 最奇怪的是,即使我取消了指针的引用,它仍然会打印一些地址。 How is this possible? 这怎么可能?

On the other hand if I change the program to this: 另一方面,如果我将程序更改为此:

$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);
}

It prints the expected output. 它输出预期的输出。

What is the explanation for this behaviour? 这种行为的解释是什么? Thanks. 谢谢。

The problem is not in the compiler but your understanding of C. Let's compile with GCC version 7.3.0 (Ubuntu 7.3.0-27ubuntu1~18.04): 问题不在于编译器,而是您对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));
             ~^   ~~~~~~~

Your format is %d which expects an int as the corresponding argument, and you're passing in struct time . 您的格式为%d ,它需要一个int作为相应的参数,并且您要传递struct time The behaviour of the program is undefined, because the conversion specifier does not match the type of the actual argument. 程序的行为是不确定的,因为转换说明符与实际参数的类型不匹配。

It doesn't matter where the values reside in memory - their type is also important. 值在内存中的位置无关紧要-它们的类型也很重要。 Even though the address of tt[0] is the same as tt[0].hours , they have a distinct type. 即使tt[0]的地址与tt[0].hours ,它们的类型也不同。 In one you want the whole struct, in another you want the value contained in the first member. 在一个中,您需要整个结构,在另一个中,您需要第一个成员中包含的值。

Your code is invalid. 您的代码无效。 Here's the error your compiler should be producing (maybe you are not enabling warnings?): 这是您的编译器应产生的错误(也许您未启用警告?):

error: format specifies type 'int' but the argument has type 'struct time' [-Werror,-Wformat]
    printf("%d\n", (*tt));

You simply cannot write code like this and then complain about its behavior. 您根本无法编写这样的代码,然后抱怨其行为。 You're telling printf() you're passing an integer but then you pass a struct. 您告诉printf()传递整数,然后传递结构。 Anything could happen. 什么事情都可能发生。

For bonus points, you have a style problem which a reasonable compiler will also warn about: 为了获得加分,您遇到了样式问题,合理的编译器也会警告您:

error: suggest braces around initialization of subobject [-Werror,-Wmissing-braces]
} t[2] = {1,2,3,4,5,6};

That's because you're initializing 2 structs with a single list of numbers. 那是因为您要用一个数字列表来初始化2个结构。 It should be {{1,2,3},{4,5,6}} . 它应该是{{1,2,3},{4,5,6}}

It behaves works ok because the array is used as a pointer (which is 100% ok) 它的行为正常,因为该数组用作指针(100%正常)

so the tt points to the first array element (this with index 0) and tt + 1 to the second (index 1). 因此tt指向第一个数组元素(索引为0的数组元素),而tt + 1指向第二个数组元素(索引为1)。

When you add one to this pointer (and this pointer is of the type pointer to the struct) the resulting pointer references the next structure of this type. 当您向该指针添加一个指针(并且该指针属于指向该结构的类型的指针)时,生成的指针将引用该类型的下一个结构。

If you dereference pointers to the structs or unions use -> 如果取消引用结构或联合的指针,请使用->

(*tt).hours == tt -> hours and (tt + 1).hours == (tt + 1) -> hours (*tt).hours == tt -> hours(tt + 1).hours == (tt + 1) -> hours

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

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