简体   繁体   中英

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. 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. Is it resolvable ? Is there any explanation as to why this is happening in my version of 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):

% 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 . 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. 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. 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. It should be {{1,2,3},{4,5,6}} .

It behaves works ok because the array is used as a pointer (which is 100% ok)

so the tt points to the first array element (this with index 0) and tt + 1 to the second (index 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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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