GCC: how to access a member of a struct in a union (of 4 structs) in a struct - Page 1
Forum section: electronics / general

author: peter-h
author_rank: Super Contributor
timestamp: July 28, 2022, 01:16:54 pm
content: Code:/** A netconn descriptor */struct netconn {/** type of the netconn (TCP, UDP or RAW) */enum netconn_type type;/** current state of the netconn */enum netconn_state state;/** the lwIP internal protocol control block */union {struct ip_pcb *ip;struct tcp_pcb *tcp;struct udp_pcb *udp;struct raw_pcb *raw;} pcb;I am trying to get hold of remote_ip.Lots of examples online but none of them compile.There is a union of four structs called ip tcp udp raw.I've been trying e.g.uint32_t ipr;ipr = conn->pcb->ip->remote_ip;but that one produceserror: invalid type argument of '->' (have 'union <anonymous>')The actual remote_ip is ultimately defined (via about 5 more convolutions) as a uint32_t, and it contains the right value.I avoid this convoluted stuff in my own code

author: newbrain
author_rank: Super Contributor
timestamp: July 28, 2022, 01:35:10 pm
content: QuoteAssumingconnis of typestruct netconn*, the pointed object contains an actualpcbunion, not a pointer to apcbunion.Union members are accessed using the . operator (as are struct members).So:Quoteshould be what you are after.In the debug screen capture, you can notice that there is not arrow close topcb, as opposed to e.g.connorip.Ref (C11): 6.5.2.3 Structure and union members, §1.BTW: nothing to do with GCC in particular, just plain C.

author: peter-h
author_rank: Super Contributor
timestamp: July 28, 2022, 01:42:08 pm
content: Unfortunately I had already tried that one.error: incompatible types when assigning to type 'uint32_t' {aka 'long unsigned int'} from type 'ip_addr_t' {aka 'struct ip4_addr'}Code:/** This is the common part of all PCB types. It needs to be at thebeginning of a PCB type definition. It is located here so thatchanges to this common part are made in one location instead ofhaving to change all PCB structs. */#define IP_PCB \/* ip addresses in network byte order */ \ip_addr_t local_ip; \ip_addr_t remote_ip; \/* Socket options */ \u8_t so_options; \/* Type Of Service */ \u8_t tos; \/* Time To Live */ \u8_t ttl \/* link layer address resolution hint */ \IP_PCB_ADDRHINTstruct ip_pcb {/* Common members of all PCB types */IP_PCB;};/** This is the aligned version of ip4_addr_t,used as local variable, on the stack, etc. */struct ip4_addr {u32_t addr;};

author: newbrain
author_rank: Super Contributor
timestamp: July 28, 2022, 01:51:10 pm
content: Quote from: peter-h on July 28, 2022, 01:42:08 pmAh, of course, I forgot to go on in the data structure, I only noticed the problem with . and ->.Code:ipr = conn->pcb.ip->remote_ip.addr;

author: ejeffrey
author_rank: Super Contributor
timestamp: July 28, 2022, 01:53:58 pm
content: Then you have to access the members of ip_addr_t to get the bytes / integer. Since you didn't show that definition we can't tell you how to do that.

author: newbrain
author_rank: Super Contributor
timestamp: July 28, 2022, 01:55:27 pm
content: Quote from: ejeffrey on July 28, 2022, 01:53:58 pmIt's there, a bit hidden, in the picture...not so easy to spot from a phone.

author: peter-h
author_rank: Super Contributor
timestamp: July 28, 2022, 02:07:55 pm
content: You are a genius, newbrain!You can work for me anytimeFate worse than death... I hear you say.At my age, my brain can deal with just one level of indirectionld l, (ix+0)ld h, (ix+1)I missed that too; I thought ipaddr_twasa uint32_t, which for ipv4 (which is all I am supporting) is just fine. Each byte is one of the four IP numbers.

author: newbrain
author_rank: Super Contributor
timestamp: July 28, 2022, 02:24:37 pm
content: Quote from: peter-h on July 28, 2022, 02:07:55 pmIt's probably just a union between auint32_t addrand and something likeuint8_t octects, so that one can access them separately (type punning guaranteed by the standard not to be UB, but caution with endianness).QuoteLet's just say it would be...interesting.

author: ejeffrey
author_rank: Super Contributor
timestamp: July 28, 2022, 04:33:01 pm
content: Quote from: newbrain on July 28, 2022, 02:24:37 pmAnother reason to use a struct is that an IPv6 address can't fit in a single scalar type. By making it a struct you can use assignment syntax to copy an address without an explicit call to memcpy. If you are going to use a struct ipv6_addr_t you probably want to use a struct ipv4_addr_t for symmetry and so you can use macros to access them in the same way. Most of the type you treat an ip address as a black box and don't access it's numerical value which is often stored in network byte order instead of host byte order, so the extra level of indirection to get to the integer representation doesn't usually matter.

author: peter-h
author_rank: Super Contributor
timestamp: July 29, 2022, 08:11:22 am
content: Yes indeed; IPV6 is a compilation option of LWIP. In this project it is disabled because it is more work in other areas, and is generally (!) rarely used.