{"id":5059,"date":"2021-11-20T00:01:16","date_gmt":"2021-11-20T08:01:16","guid":{"rendered":"https:\/\/c-for-dummies.com\/blog\/?p=5059"},"modified":"2021-11-13T10:47:02","modified_gmt":"2021-11-13T18:47:02","slug":"all-those-_t-data-types","status":"publish","type":"post","link":"https:\/\/c-for-dummies.com\/blog\/?p=5059","title":{"rendered":"All Those <em>_t<\/em> Data Types"},"content":{"rendered":"<p>You see them often if you code in C: <em>time_t<\/em>, <em>size_t<\/em>, and other <em>_t<\/em> data types, usually specific to some function or library. The C gurus have a method to their madness when it comes to naming these variables. The <em>_t<\/em> stands for something. It&#8217;s very consistent on purpose.<br \/>\n<!--more--><br \/>\nThe <em>_t<\/em> implies a <em>typedef<\/em>, a defined data type. The <em>typedef<\/em> is based on an existing type. Here are the basic C language data types:<\/p>\n<p><em>char<br \/>\nint<br \/>\nfloat<br \/>\ndouble<\/em><\/p>\n<p>Qualifiers applied to the basic types include <em>short<\/em>, <em>long<\/em>, <em>signed<\/em>, <em>unsigned<\/em>.<\/p>\n<p>Also included as data types are <em>void<\/em> and <em>_Bool<\/em>, though for the <em>_t<\/em> typedefs, the four basic ones plus a few of the qualifiers are used.<\/p>\n<p>The question is: <em>Why bother?<\/em><\/p>\n<p>The reason is compatibility and consistency between architectures.<\/p>\n<p>Not matter how a library or operating system measures the time, in C you use the <em>time_t<\/em> data type to declare a time value. Years ago, this value may have been a 16-bit integer. Then it became a 32-bit integer to deal with the Y2K problem. For Y36\/Y38 problem, it might be a 64-bit integer on some systems. Still, no matter what the underlying mechanics, you code compiles providing you use the <em>time_t<\/em> data type when dealing with time values.<\/p>\n<p>The question of the underlying type does play a role when using a placeholder.<\/p>\n<p>For example, the <em>sizeof<\/em> operator returns a <em>size_t<\/em> value &#8211; essentially a quantity of bytes. As I do so often in my code, I use the <code>%d<\/code> placeholder to output a <em>size_t<\/em> value. That is, until the compiler reminds me:<\/p>\n<p><code><\/p>\n<pre>warning: format specifies type 'int' but the argument has type 'unsigned long' [-Wformat]\r\n        printf(\"The array is %d bytes in size\\n\",sizeof(array));\r\n                             ~~                  ^~~~~~~~~~~~~\r\n                             %lu\r\n1 warning generated.<\/pre>\n<p><\/code><\/p>\n<p>Years ago, the <code>%d<\/code> placeholder worked! But the underlying format is <em>unsigned long<\/em>, and <em>clang<\/em> is nice enough to show me where the mistake took place, which argument is referenced, and which conversion characters to use. It&#8217;s all too often that I rely upon compiler warnings like this to discover which placeholder to use.<\/p>\n<p>Oh, by the way, the <code>%zu<\/code> placeholder can always be used to output a <em>size_t<\/em> value, whether it&#8217;s changed in the future or not.<\/p>\n<p>When you don&#8217;t know the underlying data type for a <em>_t<\/em> <em>typedef<\/em>, you can go spelunking in the header files to locate the specific definition. Sometimes you might be lucky and find the <em>typedef<\/em> immediately in the header file. With modern compilers, however, the <em>typedef<\/em> is most likely included in another header file, often in a subdirectory.<\/p>\n<p>For example, <em>time_t<\/em> is found in the <code>\/usr\/include\/bits\/types\/time_t.h<\/code> file in one of my Linux distros. But in this file, it&#8217;s included in the <code>\/usr\/include\/bits\/types.h<\/code> header file, where its definition is related to defined constants in even other header files. Ugh.<\/p>\n<p>No, it&#8217;s best to just use the <em>typedef<\/em> variable as intended. And, unfortunately, if the <em>man<\/em> page doesn&#8217;t explain which placeholder to use, best-guess it and wait for the warning to appear. This approach is disappointing, but it works.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>No, the C gurus did not add <code>_t<\/code> just to make declaring variables more difficult to type. <a href=\"https:\/\/c-for-dummies.com\/blog\/?p=5059\">Continue reading <span class=\"meta-nav\">&rarr;<\/span><\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[2],"tags":[],"class_list":["post-5059","post","type-post","status-publish","format-standard","hentry","category-main"],"_links":{"self":[{"href":"https:\/\/c-for-dummies.com\/blog\/index.php?rest_route=\/wp\/v2\/posts\/5059","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/c-for-dummies.com\/blog\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/c-for-dummies.com\/blog\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/c-for-dummies.com\/blog\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/c-for-dummies.com\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=5059"}],"version-history":[{"count":5,"href":"https:\/\/c-for-dummies.com\/blog\/index.php?rest_route=\/wp\/v2\/posts\/5059\/revisions"}],"predecessor-version":[{"id":5067,"href":"https:\/\/c-for-dummies.com\/blog\/index.php?rest_route=\/wp\/v2\/posts\/5059\/revisions\/5067"}],"wp:attachment":[{"href":"https:\/\/c-for-dummies.com\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=5059"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/c-for-dummies.com\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=5059"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/c-for-dummies.com\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=5059"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}