Path: csiph.com!eternal-september.org!reader02.eternal-september.org!.POSTED!not-for-mail From: Keith Thompson Newsgroups: comp.lang.c Subject: Re: Why does C allow structs to have a tag? Date: Tue, 27 Jul 2021 18:30:57 -0700 Organization: None to speak of Lines: 90 Message-ID: <87sfzzgr72.fsf@nosuchdomain.example.com> References: <867dijb22a.fsf@linuxsc.com> <86a6mt8g69.fsf@linuxsc.com> <20210727083246.384@kylheku.com> <87h7gfiqu0.fsf@nosuchdomain.example.com> Mime-Version: 1.0 Content-Type: text/plain Injection-Info: reader02.eternal-september.org; posting-host="092bc793105a53572bfeac6d5da9e91f"; logging-data="20065"; mail-complaints-to="abuse@eternal-september.org"; posting-account="U2FsdGVkX1+1bCM6HiU3brIqstJ0oIev" User-Agent: Gnus/5.13 (Gnus v5.13) Emacs/27.2 (gnu/linux) Cancel-Lock: sha1:X5Xbxtixl2iMsyAKmWKCICgijRY= sha1:HANzJx7sXPWgoMV3pZaBEP37K8I= Xref: csiph.com comp.lang.c:162068 Bart writes: > On 27/07/2021 23:12, Scott Lurndal wrote: [...] >> Consider abstract types such as pid_t or off_t. These allow >> the underlying field to change in size (e.g. from unsigned >> short to unsigned int) without changing the semantics of >> the use of the type. A simple recompile/relink is all that is >> necessary to switch to the new definition on a new machine with >> different fundamental types. > > I would rather see specific types, such as i16 i32 i64. C has those in (though not by those names). > If they need to vary by platform, then provide specific headers for > that platform, instead of ending up with an unmaintainable, > unreadable, fragile mess by trying to have one header for everything. The audience for most system headers is the compiler, not the programmer. I don't need to look at /usr/include/stdint.h to understand what int32_t means. > Some integer types will depend on the target so, fine, use special > types for those (size_t and intptr_t for example). But DON'T have a > dedicated integer typedef for every field of every struct! > Declarations like this are a joke: > > struct stat { > dev_t st_dev; /* ID of device containing file */ > ino_t st_ino; /* inode number */ > mode_t st_mode; /* protection */ > nlink_t st_nlink; /* number of hard links */ > uid_t st_uid; /* user ID of owner */ > gid_t st_gid; /* group ID of owner */ > dev_t st_rdev; /* device ID (if special file) */ > off_t st_size; /* total size, in bytes */ > blksize_t st_blksize; /* blocksize for file system I/O */ > blkcnt_t st_blocks; /* number of 512B blocks allocated */ > time_t st_atime; /* time of last access */ > time_t st_mtime; /* time of last modification */ > time_t st_ctime; /* time of last status change */ > }; Would you insist on using the [u]intN_t types for all those members? And if the requirements for a field vary from one system to another, what then? Would st_dev and st_ino be the same type on one platform and different types on another? > I think there are 13 fields and 10 different types! There will be a > section of header where those 10 typedefs are defined differently per > platform; just use that same mechanism to define specific stat structs > instead. Are you saying I'd have to use #include on one system and #include on another? I don't think that's really what you meant. >> When you hide a struct behind a typedef, it's not opaque, >> as the field names are not generic (there was a time when any >> field name could be used with any pointer, but that's long in >> the past now). >> I generally fall into Keith's camp on this in C, and in C++ >> I never use typedef to hide a struct (the struct tag is, >> in a sense, a typedef in C++). > > You don't need to hide it: > > typedef struct {...} struct_T; > > instead of: > > struct T {...}; > > Use typedef and you can be consistent with all other named user types. As you know, that doesn't allow for the very common case of a struct that contains a pointer to itself. And "struct_T" is (very slightly) more difficult to type than "struct T". Most "named user types" are structs. I use a consistent naming scheme for them. I don't give separate names to pointer or array types, and most named integer types that I use are defined in standard or system headers. -- Keith Thompson (The_Other_Keith) Keith.S.Thompson+u@gmail.com Working, but not speaking, for Philips void Void(void) { Void(); } /* The recursive call of the void */