1030 lines
No EOL
96 KiB
HTML
1030 lines
No EOL
96 KiB
HTML
|
||
<!DOCTYPE html>
|
||
|
||
|
||
|
||
|
||
<html lang="en">
|
||
<head>
|
||
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
|
||
|
||
<title>10.4. Arrays, Structs, Enums, and Type Definitions — Computer Systems Fundamentals</title>
|
||
|
||
<link rel="stylesheet" href="_static/css/bootstrap.min.css" integrity="sha384-ggOyR0iXCbMQv3Xipma34MD+dH/1fQ784/j6cY/iJTQUOhcWr7x9JvoRxT2MZw1T" crossorigin="anonymous" />
|
||
<link rel="stylesheet" href="_static/css/pygments.css" type="text/css" />
|
||
<link rel="stylesheet" href="_static/css/normalize.css" type="text/css" />
|
||
<link rel="stylesheet" href="../../../JSAV/css/JSAV.css" type="text/css" />
|
||
<link rel="stylesheet" href="../../../lib/odsaMOD-min.css" type="text/css" />
|
||
<link rel="stylesheet" href="_static/css/jquery-1.11.4-smoothness-ui.css" type="text/css" />
|
||
<link rel="stylesheet" href="../../../lib/odsaStyle-min.css" type="text/css" />
|
||
<link rel="stylesheet" href="_static/css/csf.css" type="text/css" />
|
||
|
||
<style>
|
||
.underline { text-decoration: underline; }
|
||
</style>
|
||
|
||
<script type="text/javascript">
|
||
var DOCUMENTATION_OPTIONS = {
|
||
URL_ROOT: './',
|
||
VERSION: '0.4.1',
|
||
COLLAPSE_INDEX: false,
|
||
FILE_SUFFIX: '.html',
|
||
HAS_SOURCE: true
|
||
};
|
||
</script>
|
||
|
||
<script type="text/x-mathjax-config">
|
||
MathJax.Hub.Config({
|
||
tex2jax: {
|
||
inlineMath: [['$','$'], ['\\(','\\)']],
|
||
displayMath: [ ['$$','$$'], ["\\[","\\]"] ],
|
||
processEscapes: true
|
||
},
|
||
"HTML-CSS": {
|
||
scale: "80"
|
||
}
|
||
});
|
||
</script>
|
||
<link rel="shortcut icon" href="_static/favicon.ico"/>
|
||
<link rel="index" title="Index" href="genindex.html" />
|
||
<link rel="search" title="Search" href="search.html" />
|
||
<link rel="index" title="Computer Systems Fundamentals" href="index.html" />
|
||
<link rel="next" title="5. Functions and Scope" href="Functions.html" />
|
||
<link rel="prev" title="3. Basic Types and Pointers" href="BasicTypes.html" />
|
||
|
||
</head><body>
|
||
|
||
<nav class="navbar navbar-expand-md navbar-dark navbar-custom fixed-top">
|
||
|
||
<a class="navbar-brand py-0" href="index.html"><img src="_static/CSF-Logo-Square-Text.png" alt="OpenCSF Logo" height="40em" class="py-1 px-2 mb-0 align-center rounded-lg bg-white" /></a>
|
||
<!-- Show a navbar toggler on mobile -->
|
||
<button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#defaultNavbars" aria-controls="defaultNavbars" aria-expanded="false" aria-label="Toggle navigation">
|
||
<span class="navbar-toggler-icon"></span>
|
||
</button>
|
||
<div class="collapse navbar-collapse" id="defaultNavbars">
|
||
<ul class="navbar-nav mr-auto">
|
||
<li class="nav-item dropdown">
|
||
<a class="nav-link dropdown-toggle jmu-gold rounded" href="Arrays.html#" id="navbarDropdownChapters" role="button" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">Contents</a>
|
||
<div class="dropdown-menu scrollable-menu" role="menu" aria-labelledby="navbarDropdownChapters">
|
||
<a class="dropdown-item" tabindex="-1" href="Arrays.html#"><b>Chapter 1</b></a>
|
||
<a class="dropdown-item" href="IntroConcSysOverview.html"> 1.1. Introduction to Concurrent Systems</a>
|
||
<a class="dropdown-item" href="SysAndModels.html"> 1.2. Systems and Models</a>
|
||
<a class="dropdown-item" href="Themes.html"> 1.3. Themes and Guiding Principles</a>
|
||
<a class="dropdown-item" href="Architectures.html"> 1.4. System Architectures</a>
|
||
<a class="dropdown-item" href="StateModels.html"> 1.5. State Models in UML</a>
|
||
<a class="dropdown-item" href="SequenceModels.html"> 1.6. Sequence Models in UML</a>
|
||
<a class="dropdown-item" href="StateModelImplementation.html"> 1.7. Extended Example: State Model Implementation</a>
|
||
<div class="dropdown-divider"></div>
|
||
<a class="dropdown-item disabled"><b>Chapter 2</b></a>
|
||
<a class="dropdown-item" href="ProcessesOverview.html"> 2.1. Processes and OS Basics</a>
|
||
<a class="dropdown-item" href="Multiprogramming.html"> 2.2. Processes and Multiprogramming</a>
|
||
<a class="dropdown-item" href="KernelMechanics.html"> 2.3. Kernel Mechanics</a>
|
||
<a class="dropdown-item" href="Syscall.html"> 2.4. System Call Interface</a>
|
||
<a class="dropdown-item" href="ProcessCycle.html"> 2.5. Process Life Cycle</a>
|
||
<a class="dropdown-item" href="UnixFile.html"> 2.6. The UNIX File Abstraction</a>
|
||
<a class="dropdown-item" href="EventsSignals.html"> 2.7. Events and Signals</a>
|
||
<a class="dropdown-item" href="Extended2Processes.html"> 2.8. Extended Example: Listing Files with Processes</a>
|
||
<div class="dropdown-divider"></div>
|
||
<a class="dropdown-item disabled"><b>Chapter 3</b></a>
|
||
<a class="dropdown-item" href="IPCOverview.html"> 3.1. Concurrency with IPC</a>
|
||
<a class="dropdown-item" href="IPCModels.html"> 3.2. IPC Models</a>
|
||
<a class="dropdown-item" href="Pipes.html"> 3.3. Pipes and FIFOs</a>
|
||
<a class="dropdown-item" href="MMap.html"> 3.4. Shared Memory With Memory-mapped Files</a>
|
||
<a class="dropdown-item" href="POSIXvSysV.html"> 3.5. POSIX vs. System V IPC</a>
|
||
<a class="dropdown-item" href="MQueues.html"> 3.6. Message Passing With Message Queues</a>
|
||
<a class="dropdown-item" href="ShMem.html"> 3.7. Shared Memory</a>
|
||
<a class="dropdown-item" href="IPCSems.html"> 3.8. Semaphores</a>
|
||
<a class="dropdown-item" href="Extended3Bash.html"> 3.9. Extended Example: Bash-lite: A Simple Command-line Shell</a>
|
||
<div class="dropdown-divider"></div>
|
||
<a class="dropdown-item disabled"><b>Chapter 4</b></a>
|
||
<a class="dropdown-item" href="SocketsOverview.html"> 4.1. Networked Concurrency</a>
|
||
<a class="dropdown-item" href="FiveLayer.html"> 4.2. The TCP/IP Internet Model</a>
|
||
<a class="dropdown-item" href="NetApps.html"> 4.3. Network Applications and Protocols</a>
|
||
<a class="dropdown-item" href="Sockets.html"> 4.4. The Socket Interface</a>
|
||
<a class="dropdown-item" href="TCPSockets.html"> 4.5. TCP Socket Programming: HTTP</a>
|
||
<a class="dropdown-item" href="UDPSockets.html"> 4.6. UDP Socket Programming: DNS</a>
|
||
<a class="dropdown-item" href="AppBroadcast.html"> 4.7. Application-Layer Broadcasting: DHCP</a>
|
||
<a class="dropdown-item" href="Extended4CGI.html"> 4.8. Extended Example: CGI Web Server</a>
|
||
<div class="dropdown-divider"></div>
|
||
<a class="dropdown-item disabled"><b>Chapter 5</b></a>
|
||
<a class="dropdown-item" href="InternetOverview.html"> 5.1. The Internet and Connectivity</a>
|
||
<a class="dropdown-item" href="AppLayer.html"> 5.2. Application Layer: Overlay Networks</a>
|
||
<a class="dropdown-item" href="TransLayer.html"> 5.3. Transport Layer</a>
|
||
<a class="dropdown-item" href="NetSec.html"> 5.4. Network Security Fundamentals</a>
|
||
<a class="dropdown-item" href="NetLayer.html"> 5.5. Network Layer: IP</a>
|
||
<a class="dropdown-item" href="LinkLayer.html"> 5.6. Link Layer</a>
|
||
<a class="dropdown-item" href="Wireless.html"> 5.7. Wireless Connectivity: Wi-Fi, Bluetooth, and Zigbee</a>
|
||
<a class="dropdown-item" href="Extended5DNS.html"> 5.8. Extended Example: DNS client</a>
|
||
<div class="dropdown-divider"></div>
|
||
<a class="dropdown-item disabled"><b>Chapter 6</b></a>
|
||
<a class="dropdown-item" href="ThreadsOverview.html"> 6.1. Concurrency with Multithreading</a>
|
||
<a class="dropdown-item" href="ProcVThreads.html"> 6.2. Processes vs. Threads</a>
|
||
<a class="dropdown-item" href="RaceConditions.html"> 6.3. Race Conditions and Critical Sections</a>
|
||
<a class="dropdown-item" href="POSIXThreads.html"> 6.4. POSIX Thread Library</a>
|
||
<a class="dropdown-item" href="ThreadArgs.html"> 6.5. Thread Arguments and Return Values</a>
|
||
<a class="dropdown-item" href="ImplicitThreads.html"> 6.6. Implicit Threading and Language-based Threads</a>
|
||
<a class="dropdown-item" href="Extended6Input.html"> 6.7. Extended Example: Keyboard Input Listener</a>
|
||
<a class="dropdown-item" href="Extended6Primes.html"> 6.8. Extended Example: Concurrent Prime Number Search</a>
|
||
<div class="dropdown-divider"></div>
|
||
<a class="dropdown-item disabled"><b>Chapter 7</b></a>
|
||
<a class="dropdown-item" href="SynchOverview.html"> 7.1. Synchronization Primitives</a>
|
||
<a class="dropdown-item" href="CritSect.html"> 7.2. Critical Sections and Peterson's Solution</a>
|
||
<a class="dropdown-item" href="Locks.html"> 7.3. Locks</a>
|
||
<a class="dropdown-item" href="Semaphores.html"> 7.4. Semaphores</a>
|
||
<a class="dropdown-item" href="Barriers.html"> 7.5. Barriers</a>
|
||
<a class="dropdown-item" href="Condvars.html"> 7.6. Condition Variables</a>
|
||
<a class="dropdown-item" href="Deadlock.html"> 7.7. Deadlock</a>
|
||
<a class="dropdown-item" href="Extended7Events.html"> 7.8. Extended Example: Event Log File</a>
|
||
<div class="dropdown-divider"></div>
|
||
<a class="dropdown-item disabled"><b>Chapter 8</b></a>
|
||
<a class="dropdown-item" href="SynchProblemsOverview.html"> 8.1. Synchronization Patterns and Problems</a>
|
||
<a class="dropdown-item" href="SynchDesign.html"> 8.2. Basic Synchronization Design Patterns</a>
|
||
<a class="dropdown-item" href="ProdCons.html"> 8.3. Producer-Consumer Problem</a>
|
||
<a class="dropdown-item" href="ReadWrite.html"> 8.4. Readers-Writers Problem</a>
|
||
<a class="dropdown-item" href="DiningPhil.html"> 8.5. Dining Philosophers Problem and Deadlock</a>
|
||
<a class="dropdown-item" href="CigSmokers.html"> 8.6. Cigarette Smokers Problem and the Limits of Semaphores and Locks</a>
|
||
<a class="dropdown-item" href="Extended8ModExp.html"> 8.7. Extended Example: Parallel Modular Exponentiation</a>
|
||
<div class="dropdown-divider"></div>
|
||
<a class="dropdown-item disabled"><b>Chapter 9</b></a>
|
||
<a class="dropdown-item" href="ParallelDistributedOverview.html"> 9.1. Parallel and Distributed Systems</a>
|
||
<a class="dropdown-item" href="ParVConc.html"> 9.2. Parallelism vs. Concurrency</a>
|
||
<a class="dropdown-item" href="ParallelDesign.html"> 9.3. Parallel Design Patterns</a>
|
||
<a class="dropdown-item" href="Scaling.html"> 9.4. Limits of Parallelism and Scaling</a>
|
||
<a class="dropdown-item" href="DistTiming.html"> 9.5. Timing in Distributed Environments</a>
|
||
<a class="dropdown-item" href="DistDataStorage.html"> 9.6. Reliable Data Storage and Location</a>
|
||
<a class="dropdown-item" href="DistConsensus.html"> 9.7. Consensus in Distributed Systems</a>
|
||
<a class="dropdown-item" href="Extended9Blockchain.html"> 9.8. Extended Example: Blockchain Proof-of-Work</a>
|
||
<div class="dropdown-divider"></div>
|
||
<a class="dropdown-item disabled"><b>Appendix A</b></a>
|
||
<a class="dropdown-item" href="CLangOverview.html"> A.1. C Language Reintroduction</a>
|
||
<a class="dropdown-item" href="Debugging.html"> A.2. Documentation and Debugging</a>
|
||
<a class="dropdown-item" href="BasicTypes.html"> A.3. Basic Types and Pointers</a>
|
||
<a class="dropdown-item" href="Arrays.html"> A.4. Arrays, Structs, Enums, and Type Definitions</a>
|
||
<a class="dropdown-item" href="Functions.html"> A.5. Functions and Scope</a>
|
||
<a class="dropdown-item" href="Pointers.html"> A.6. Pointers and Dynamic Allocation</a>
|
||
<a class="dropdown-item" href="Strings.html"> A.7. Strings</a>
|
||
<a class="dropdown-item" href="FunctionPointers.html"> A.8. Function Pointers</a>
|
||
<a class="dropdown-item" href="Files.html"> A.9. Files</a>
|
||
</div>
|
||
</li>
|
||
|
||
|
||
|
||
</ul>
|
||
</div>
|
||
|
||
<ul class="navbar-nav flex-row ml-md-auto d-none d-md-flex">
|
||
<li class="nav-item"><a class="nav-link jmu-gold" href="https://w3.cs.jmu.edu/kirkpams/OpenCSF/Books/csf/source/Arrays.rst"
|
||
target="_blank" rel="nofollow">Show Source</a></li>
|
||
|
||
</ul>
|
||
</nav>
|
||
|
||
|
||
<div class="container center">
|
||
«  <a id="prevmod" href="BasicTypes.html">10.3. Basic Types and Pointers</a>
|
||
  ::  
|
||
<a class="uplink" href="index.html">Contents</a>
|
||
  ::  
|
||
<a id="nextmod" href="Functions.html">10.5. Functions and Scope</a>  »
|
||
|
||
</div>
|
||
<br />
|
||
|
||
|
||
|
||
<script type="text/javascript" src="_static/js/jquery-2.1.4.min.js"></script>
|
||
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.1/MathJax.js?config=TeX-AMS-MML_HTMLorMML"></script>
|
||
<script type="text/javascript" src="_static/js/jquery-1.11.4-ui.min.js"></script>
|
||
<script type="text/javascript" src="_static/js/forge-0.7.0.min.js"></script>
|
||
<script type="text/javascript" src="../../../JSAV/lib/jquery.transit.js"></script>
|
||
<script type="text/javascript" src="../../../JSAV/lib/raphael.js"></script>
|
||
<script type="text/javascript" src="../../../JSAV/build/JSAV-min.js"></script>
|
||
<script type="text/javascript" src="_static/js/config.js"></script>
|
||
<script type="text/javascript" src="../../../lib/odsaUtils-min.js"></script>
|
||
<script type="text/javascript" src="../../../lib/odsaMOD-min.js"></script>
|
||
<script type="text/javascript" src="_static/js/d3-4.13.0.min.js"></script>
|
||
<script type="text/javascript" src="_static/js/d3-selection-multi.v1.min.js"></script>
|
||
<script type="text/javascript" src="../../../lib/dataStructures.js"></script>
|
||
|
||
|
||
|
||
|
||
|
||
|
||
<div class="container">
|
||
|
||
<script>ODSA.SETTINGS.DISP_MOD_COMP = true;ODSA.SETTINGS.MODULE_NAME = "Arrays";ODSA.SETTINGS.MODULE_LONG_NAME = "Arrays, Structs, Enums, and Type Definitions";ODSA.SETTINGS.MODULE_CHAPTER = "Appendix A"; ODSA.SETTINGS.BUILD_DATE = "2021-06-14 17:15:26"; ODSA.SETTINGS.BUILD_CMAP = false;JSAV_OPTIONS['lang']='en';JSAV_EXERCISE_OPTIONS['code']='java';</script><div class="section" id="arrays-structs-enums-and-type-definitions">
|
||
<h1>10.4. Arrays, Structs, Enums, and Type Definitions<a class="headerlink" href="Arrays.html#arrays-structs-enums-and-type-definitions" title="Permalink to this headline">¶</a></h1>
|
||
<p>As with other common typed languages (such as Java), C supports arrays of other types. When
|
||
declaring an array, the compiler must be able to determine the exact length. One way to do this is
|
||
to specify the length inside the brackets of the declaration (such as <code class="docutils literal notranslate"><span class="pre">int</span> <span class="pre">array[10];</span></code>). Another
|
||
way is to provide an explicit initialization array. <a class="reference external" href="Arrays.html#cla-11">Code Listing A.11</a> demonstrates this
|
||
second technique, omitting the length from inside the brackets on line 6 (although it could be
|
||
included here).</p>
|
||
<div class="highlight-c border border-dark rounded-lg bg-light px-0 mb-3 notranslate" id="cla-11"><table class="highlighttable"><tr><td class="linenos px-0 mx-0"><div class="linenodiv"><pre class="mb-0">1
|
||
2
|
||
3
|
||
4
|
||
5
|
||
6
|
||
7
|
||
8
|
||
9</pre></div></td><td class="code"><div class="highlight bg-light"><pre class="mb-0"><span></span><span class="cm">/* Code Listing A.11:</span>
|
||
<span class="cm"> C array names are implicitly pointers to their first entry</span>
|
||
<span class="cm"> */</span>
|
||
|
||
<span class="cm">/* Instantiate an array and print its starting address */</span>
|
||
<span class="kt">uint32_t</span> <span class="n">data</span><span class="p">[]</span> <span class="o">=</span> <span class="p">{</span> <span class="mi">1</span><span class="p">,</span> <span class="mi">2</span><span class="p">,</span> <span class="mi">3</span><span class="p">,</span> <span class="mi">4</span><span class="p">,</span> <span class="mi">5</span> <span class="p">};</span>
|
||
<span class="n">printf</span> <span class="p">(</span><span class="s">"data = %p</span><span class="se">\n</span><span class="s">"</span><span class="p">,</span> <span class="n">data</span><span class="p">);</span>
|
||
<span class="n">printf</span> <span class="p">(</span><span class="s">"&data = %p</span><span class="se">\n</span><span class="s">"</span><span class="p">,</span> <span class="o">&</span><span class="n">data</span><span class="p">);</span>
|
||
<span class="n">printf</span> <span class="p">(</span><span class="s">"&data[0] = %p</span><span class="se">\n\n</span><span class="s">"</span><span class="p">,</span> <span class="o">&</span><span class="n">data</span><span class="p">[</span><span class="mi">0</span><span class="p">]);</span>
|
||
</pre></div>
|
||
</td></tr></table></div>
|
||
<p><a class="reference external" href="Arrays.html#cla-11">Code Listing A.11</a> illustrates a key aspect of the relationship between arrays and
|
||
pointers: <strong>Array names are implicitly pointers to their first element</strong>. To see this, consider
|
||
lines 7 – 9; line 7 prints the <em>value</em> of <code class="docutils literal notranslate"><span class="pre">data</span></code>, line 8 prints the address of data, and line 9
|
||
prints the <em>address</em> of <code class="docutils literal notranslate"><span class="pre">data[0]</span></code>. When this program is run, these three lines produce the same
|
||
value as the output. The convention in C is that any array variable is an alias for the starting
|
||
address. All three of these notations can be used (and frequently are) depending on the context and
|
||
style preferences of the programmer.</p>
|
||
<p><a class="reference external" href="Arrays.html#cla-12">Code Listing A.12</a> extends the previous example to explore the relationship between
|
||
arrays and pointers further. Line 7 starts by declaring a pointer and initializing it to point to
|
||
the array. On this line, we could also initialize <code class="docutils literal notranslate"><span class="pre">u32ptr</span> <span class="pre">=</span> <span class="pre">&data[0]</span></code>, but (due to convoluted type
|
||
checking rules) it is a compiler warning to initialize <code class="docutils literal notranslate"><span class="pre">u32ptr</span> <span class="pre">=</span> <span class="pre">&data</span></code> (despite the fact that
|
||
data and &data are the same). Line 8 sets the <code class="docutils literal notranslate"><span class="pre">walker</span></code> pointer in the same way.</p>
|
||
<div class="highlight-c border border-dark rounded-lg bg-light px-0 mb-3 notranslate" id="cla-12"><table class="highlighttable"><tr><td class="linenos px-0 mx-0"><div class="linenodiv"><pre class="mb-0"> 1
|
||
2
|
||
3
|
||
4
|
||
5
|
||
6
|
||
7
|
||
8
|
||
9
|
||
10
|
||
11
|
||
12
|
||
13
|
||
14
|
||
15
|
||
16
|
||
17
|
||
18
|
||
19
|
||
20
|
||
21
|
||
22
|
||
23</pre></div></td><td class="code"><div class="highlight bg-light"><pre class="mb-0"><span></span><span class="cm">/* Code Listing A.12:</span>
|
||
<span class="cm"> C arrays and pointer arithmetic work identically</span>
|
||
<span class="cm"> */</span>
|
||
|
||
<span class="cm">/* Make two pointers to data, which also means they point to</span>
|
||
<span class="cm"> the first element in the array */</span>
|
||
<span class="kt">uint32_t</span> <span class="o">*</span><span class="n">u32ptr</span> <span class="o">=</span> <span class="n">data</span><span class="p">;</span> <span class="c1">// &data[0] is also ok, &data is not</span>
|
||
<span class="kt">uint32_t</span> <span class="o">*</span><span class="n">walker</span> <span class="o">=</span> <span class="n">data</span><span class="p">;</span> <span class="c1">// a second pointer to data</span>
|
||
|
||
<span class="cm">/* Loop through the elements, observing that array bracket</span>
|
||
<span class="cm"> notation and pointer arithmetic behave identically; after</span>
|
||
<span class="cm"> each time through the loop, advance the walker pointer */</span>
|
||
<span class="k">for</span> <span class="p">(</span><span class="kt">size_t</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o"><</span> <span class="mi">5</span><span class="p">;</span> <span class="n">i</span><span class="o">++</span><span class="p">,</span> <span class="n">walker</span><span class="o">++</span><span class="p">)</span>
|
||
<span class="p">{</span>
|
||
<span class="n">printf</span> <span class="p">(</span><span class="s">"data[%zd] address %p and value %08"</span> <span class="n">PRIx32</span> <span class="s">"</span><span class="se">\n</span><span class="s">"</span><span class="p">,</span>
|
||
<span class="n">i</span><span class="p">,</span> <span class="o">&</span><span class="n">data</span><span class="p">[</span><span class="n">i</span><span class="p">],</span> <span class="n">data</span><span class="p">[</span><span class="n">i</span><span class="p">]);</span>
|
||
<span class="n">printf</span> <span class="p">(</span><span class="s">"u32ptr[%zd] address %p and value %08"</span> <span class="n">PRIx32</span> <span class="s">"</span><span class="se">\n</span><span class="s">"</span><span class="p">,</span>
|
||
<span class="n">i</span><span class="p">,</span> <span class="o">&</span><span class="n">u32ptr</span><span class="p">[</span><span class="n">i</span><span class="p">],</span> <span class="n">u32ptr</span><span class="p">[</span><span class="n">i</span><span class="p">]);</span>
|
||
<span class="n">printf</span> <span class="p">(</span><span class="s">"u32ptr+%zd address %p and value %08"</span> <span class="n">PRIx32</span> <span class="s">"</span><span class="se">\n\n</span><span class="s">"</span><span class="p">,</span>
|
||
<span class="n">i</span><span class="p">,</span> <span class="n">u32ptr</span> <span class="o">+</span> <span class="n">i</span><span class="p">,</span> <span class="o">*</span><span class="p">(</span><span class="n">u32ptr</span> <span class="o">+</span> <span class="n">i</span><span class="p">));</span>
|
||
<span class="n">printf</span> <span class="p">(</span><span class="s">"walker address %p and value %08"</span> <span class="n">PRIx32</span> <span class="s">"</span><span class="se">\n\n</span><span class="s">"</span><span class="p">,</span>
|
||
<span class="n">walker</span><span class="p">,</span> <span class="o">*</span><span class="n">walker</span><span class="p">);</span>
|
||
<span class="p">}</span>
|
||
</pre></div>
|
||
</td></tr></table></div>
|
||
<p>Lines 13 – 23 in <a class="reference external" href="Arrays.html#cla-12">Code Listing A.12</a> demonstrate the equivalency between array
|
||
dereferencing and <em>pointer arithmetic</em>. That is, when C performs an operation like <code class="docutils literal notranslate"><span class="pre">u32ptr</span> <span class="pre">+</span>
|
||
<span class="pre">5</span></code>, it is not simply the value of <code class="docutils literal notranslate"><span class="pre">u32ptr</span></code> plus the number 5 in standard arithmetic; instead,
|
||
<code class="docutils literal notranslate"><span class="pre">u32ptr</span> <span class="pre">+</span> <span class="pre">5</span></code> requires taking the value of <code class="docutils literal notranslate"><span class="pre">u32ptr</span></code> (which is an address) and adding 5 times the
|
||
size of what <code class="docutils literal notranslate"><span class="pre">u32ptr</span></code> points to. In this case, if u32ptr stores the address <code class="docutils literal notranslate"><span class="pre">0x7ffee0000720</span></code>,
|
||
<code class="docutils literal notranslate"><span class="pre">u32ptr</span> <span class="pre">+</span> <span class="pre">5</span></code> would add 20 to this value (since <code class="docutils literal notranslate"><span class="pre">u32ptr</span></code> is a pointer to 4-byte <code class="docutils literal notranslate"><span class="pre">uint32_t</span></code>
|
||
values), yielding <code class="docutils literal notranslate"><span class="pre">0x7ffee0000734</span></code>. In general terms, for an arbitrary pointer <code class="docutils literal notranslate"><span class="pre">ptr</span></code>,
|
||
<code class="docutils literal notranslate"><span class="pre">&ptr[n]</span></code> and <code class="docutils literal notranslate"><span class="pre">ptr+n</span></code> are identical for any integer <code class="docutils literal notranslate"><span class="pre">n</span></code>; <code class="docutils literal notranslate"><span class="pre">ptr[n]</span></code> and <code class="docutils literal notranslate"><span class="pre">*(ptr+n)</span></code> also
|
||
yield the same value. (As the bracket notation tends to be more familiar, many C programmers use it
|
||
whenever pointer arithmetic is needed.)</p>
|
||
<p>Lines 21 and 22 do not require adding any value to the <code class="docutils literal notranslate"><span class="pre">walker</span></code> pointer so that it accesses the
|
||
correct location. Instead, walker is set up to <em>walk through</em> the array, accessing one element at a
|
||
time. Specifically, line 8 initializes <code class="docutils literal notranslate"><span class="pre">walker</span></code> to point to the first element, and the increment
|
||
field of the <code class="docutils literal notranslate"><span class="pre">for</span></code>-loop causes walker to advance after each iteration (line 13). (Observe that it is
|
||
possible to specify multiple increments in a <code class="docutils literal notranslate"><span class="pre">for</span></code>-loop, separated by a comma as shown with <code class="docutils literal notranslate"><span class="pre">i++</span></code>,
|
||
<code class="docutils literal notranslate"><span class="pre">walker++</span></code>.) A subtle aspect of this increment is that it does not simply add 1 to the address
|
||
<code class="docutils literal notranslate"><span class="pre">walker</span></code> is pointing to; rather, just like the additions on lines 18 and 20, <code class="docutils literal notranslate"><span class="pre">walker++</span></code> will
|
||
increment the address by the size of a <code class="docutils literal notranslate"><span class="pre">uint32_t</span></code>. Consequently, this incrementing style is a
|
||
common technique to use a pointer to traverse through the elements of an array.</p>
|
||
<p>Although pointer variables can be treated as arrays, the reverse is not true. That is, even though
|
||
an array name is implicitly a pointer to the first element of the array, we cannot use pointer
|
||
notation for a variable declared as an array. In <a class="reference external" href="Arrays.html#cla-11">Code Listing A.11</a> and <a class="reference external" href="Arrays.html#cla-12">A.12</a>, trying to access <code class="docutils literal notranslate"><span class="pre">*data</span></code> or <code class="docutils literal notranslate"><span class="pre">*(data+i)</span></code> would produce a compiler error.</p>
|
||
<p><a class="reference external" href="Arrays.html#cla-13">Code Listing A.13</a> illustrates a slight variation on <a class="reference external" href="Arrays.html#cla-12">Code Listing A.12</a>. In
|
||
this scenario, <code class="docutils literal notranslate"><span class="pre">data</span></code> is declared as an array of 32-bit values. Since the array consists of two of
|
||
these values, the array occupies eight consecutive bytes of memory. Line 12 declares a pointer like
|
||
before, but the pointer is a <code class="docutils literal notranslate"><span class="pre">uint8_t*</span></code>, so it points to 8-bit values. Lines 13 – 19 will traverse
|
||
through all of the bytes of the <code class="docutils literal notranslate"><span class="pre">data</span></code> array, but accessing it a byte at a time instead of just
|
||
examining the two 32-bit entries. One advantage of this approach is that using a <code class="docutils literal notranslate"><span class="pre">uint8_t*</span></code>
|
||
pointer provides a mechanism to explore the endianness of multi-byte integers. In this example,
|
||
<code class="docutils literal notranslate"><span class="pre">data[0]</span></code> stores the 32-bit value <code class="docutils literal notranslate"><span class="pre">0x01020304</span></code>, spread across four memory locations. Assuming
|
||
this runs on a little-endian architecture (such as x86), 0x04 is stored at the first of these four
|
||
byte locations; consequently, <code class="docutils literal notranslate"><span class="pre">u8ptr[0]</span></code> accesses <code class="docutils literal notranslate"><span class="pre">0x04</span></code>, <code class="docutils literal notranslate"><span class="pre">u8ptr[1]</span></code> access <code class="docutils literal notranslate"><span class="pre">0x03</span></code>, and so
|
||
on. Once the loop would get to <code class="docutils literal notranslate"><span class="pre">u8ptr[4]</span></code>, the result would be 0x08, which is the first byte
|
||
stored for <code class="docutils literal notranslate"><span class="pre">data[1]</span></code>.</p>
|
||
<div class="highlight-c border border-dark rounded-lg bg-light px-0 mb-3 notranslate" id="cla-13"><table class="highlighttable"><tr><td class="linenos px-0 mx-0"><div class="linenodiv"><pre class="mb-0"> 1
|
||
2
|
||
3
|
||
4
|
||
5
|
||
6
|
||
7
|
||
8
|
||
9
|
||
10
|
||
11
|
||
12
|
||
13
|
||
14
|
||
15
|
||
16
|
||
17
|
||
18
|
||
19</pre></div></td><td class="code"><div class="highlight bg-light"><pre class="mb-0"><span></span><span class="cm">/* Code Listing A.13:</span>
|
||
<span class="cm"> Using a pointer to traverse an array of a different size</span>
|
||
<span class="cm"> */</span>
|
||
|
||
<span class="cm">/* Instantiate an array of two 32-bit integers */</span>
|
||
<span class="kt">uint32_t</span> <span class="n">data</span><span class="p">[]</span> <span class="o">=</span> <span class="p">{</span> <span class="mh">0x01020304</span><span class="p">,</span> <span class="mh">0x05060708</span> <span class="p">};</span>
|
||
<span class="n">printf</span> <span class="p">(</span><span class="s">"data starts at %p</span><span class="se">\n</span><span class="s">"</span><span class="p">,</span> <span class="n">data</span><span class="p">);</span>
|
||
<span class="n">printf</span> <span class="p">(</span><span class="s">"data[0] address %p and value %08"</span> <span class="n">PRIx32</span> <span class="s">"</span><span class="se">\n</span><span class="s">"</span><span class="p">,</span> <span class="o">&</span><span class="n">data</span><span class="p">[</span><span class="mi">0</span><span class="p">],</span> <span class="n">data</span><span class="p">[</span><span class="mi">0</span><span class="p">]);</span>
|
||
<span class="n">printf</span> <span class="p">(</span><span class="s">"data[1] address %p and value %08"</span> <span class="n">PRIx32</span> <span class="s">"</span><span class="se">\n\n</span><span class="s">"</span><span class="p">,</span> <span class="o">&</span><span class="n">data</span><span class="p">[</span><span class="mi">1</span><span class="p">],</span> <span class="n">data</span><span class="p">[</span><span class="mi">1</span><span class="p">]);</span>
|
||
|
||
<span class="cm">/* Make a pointer to the first byte of the array */</span>
|
||
<span class="kt">uint8_t</span> <span class="o">*</span><span class="n">u8ptr</span> <span class="o">=</span> <span class="p">(</span><span class="kt">uint8_t</span> <span class="o">*</span><span class="p">)</span><span class="n">data</span><span class="p">;</span>
|
||
<span class="k">for</span> <span class="p">(</span><span class="kt">size_t</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o"><</span> <span class="mi">8</span><span class="p">;</span> <span class="n">i</span><span class="o">++</span><span class="p">)</span>
|
||
<span class="p">{</span>
|
||
<span class="n">printf</span> <span class="p">(</span><span class="s">"u8ptr[%zd] address %p and value %02"</span> <span class="n">PRIx8</span> <span class="s">"</span><span class="se">\n</span><span class="s">"</span><span class="p">,</span>
|
||
<span class="n">i</span><span class="p">,</span> <span class="o">&</span><span class="n">u8ptr</span><span class="p">[</span><span class="n">i</span><span class="p">],</span> <span class="n">u8ptr</span><span class="p">[</span><span class="n">i</span><span class="p">]);</span>
|
||
<span class="n">printf</span> <span class="p">(</span><span class="s">"u8ptr+%zd address %p and value %02"</span> <span class="n">PRIx8</span> <span class="s">"</span><span class="se">\n\n</span><span class="s">"</span><span class="p">,</span>
|
||
<span class="n">i</span><span class="p">,</span> <span class="n">u8ptr</span> <span class="o">+</span> <span class="n">i</span><span class="p">,</span> <span class="o">*</span><span class="p">(</span><span class="n">u8ptr</span> <span class="o">+</span> <span class="n">i</span><span class="p">));</span>
|
||
<span class="p">}</span>
|
||
</pre></div>
|
||
</td></tr></table></div>
|
||
<div class="topic border border-dark rounded-lg alert-danger px-2 mb-3">
|
||
<div class="figure align-left">
|
||
<a class="reference internal image-reference" href="_images/CSF-Images-BugWarning.png"><img alt="Decorative bug warning" src="_images/CSF-Images-BugWarning.png" style="width: 90%;" /></a>
|
||
</div>
|
||
<p class="topic-title first pt-2 mb-1">Bug Warning</p><hr class="mt-1" />
|
||
<p>It is critical to understand that C does not explicitly store the length of an array anywhere, so
|
||
there is no way to learn this information for a pointer to an arbitrary array. Consider the
|
||
<code class="docutils literal notranslate"><span class="pre">data</span></code> and <code class="docutils literal notranslate"><span class="pre">ptr</span></code> variables as declared below. By examining this code, we can determine that the
|
||
<code class="docutils literal notranslate"><span class="pre">data</span></code> array takes up 16 bytes and consists of four consecutive 32-bit values; i.e., this portion
|
||
of source code makes it clear that the length of the array is four.</p>
|
||
<div class="highlight-c border border-dark rounded-lg bg-light px-0 mb-3 notranslate"><table class="highlighttable"><tr><td class="linenos px-0 mx-0"><div class="linenodiv"><pre class="mb-0">1
|
||
2
|
||
3
|
||
4
|
||
5
|
||
6
|
||
7</pre></div></td><td class="code"><div class="highlight bg-light"><pre class="mb-0"><span></span><span class="kt">uint32_t</span> <span class="n">data</span><span class="p">[</span><span class="mi">4</span><span class="p">];</span> <span class="c1">// an array of four 4-byte ints</span>
|
||
<span class="kt">uint32_t</span> <span class="o">*</span><span class="n">ptr</span> <span class="o">=</span> <span class="n">data</span><span class="p">;</span>
|
||
|
||
<span class="n">printf</span> <span class="p">(</span><span class="s">"sizeof(data) = %zd</span><span class="se">\n</span><span class="s">"</span><span class="p">,</span> <span class="k">sizeof</span> <span class="p">(</span><span class="n">data</span><span class="p">));</span> <span class="c1">// 16, NOT 4</span>
|
||
<span class="n">printf</span> <span class="p">(</span><span class="s">"sizeof(ptr) = %zd</span><span class="se">\n</span><span class="s">"</span><span class="p">,</span> <span class="k">sizeof</span> <span class="p">(</span><span class="n">ptr</span><span class="p">));</span> <span class="c1">// 8, NOT 4</span>
|
||
|
||
<span class="n">printf</span> <span class="p">(</span><span class="s">"number of elemenst = %zd</span><span class="se">\n</span><span class="s">"</span><span class="p">,</span> <span class="k">sizeof</span> <span class="p">(</span><span class="n">data</span><span class="p">)</span> <span class="o">/</span> <span class="k">sizeof</span> <span class="p">(</span><span class="kt">uint32_t</span><span class="p">));</span> <span class="c1">// SUCCESS!</span>
|
||
</pre></div>
|
||
</td></tr></table></div>
|
||
<p>A very common mistake is to try to use <code class="docutils literal notranslate"><span class="pre">sizeof()</span></code> as shown on lines 4 and 5. With one exception
|
||
(shown on line 7), <code class="docutils literal notranslate"><span class="pre">sizeof()</span></code> <strong>cannot be used to determine the length of an array</strong>.
|
||
Recall that <code class="docutils literal notranslate"><span class="pre">sizeof()</span></code> returns the number of bytes for a variable; it is not aware of the
|
||
subdivision of those bytes into an array of consecutive elements. As such, the <code class="docutils literal notranslate"><span class="pre">sizeof(data)</span></code> on
|
||
line 4 returns 16, which is the total number of bytes for the array. Similarly, the <code class="docutils literal notranslate"><span class="pre">sizeof(ptr)</span></code>
|
||
on line 5 returns 8, which is the size of a pointer (i.e., an address) on a 64-bit CPU
|
||
architecture. Neither of these return the number of elements in the array.</p>
|
||
<p>Line 7 is successful because we know the total amount of space for data (<code class="docutils literal notranslate"><span class="pre">sizeof(data)</span></code> =
|
||
16 bytes) and we know data is an array of <code class="docutils literal notranslate"><span class="pre">uint32_t</span></code> items (<code class="docutils literal notranslate"><span class="pre">sizeof(uint32_t)</span></code> = 4 bytes for
|
||
each item). Having both of these pieces of information allows us to perform this calculation. We
|
||
cannot perform this same calculation using <code class="docutils literal notranslate"><span class="pre">sizeof(ptr)</span></code>, however. That is, if we are given a
|
||
pointer (such as <code class="docutils literal notranslate"><span class="pre">ptr</span></code>) and we know that it is pointing to an array of <code class="docutils literal notranslate"><span class="pre">uint32_t</span></code> items, we
|
||
cannot determine the length of the array. The problem is that ptr technically does not point to an
|
||
array; rather, it points only to the <em>first element</em> of the array. There is no way to attach the
|
||
additional information of the size of the array to the pointer.</p>
|
||
<p>This point becomes really important later, when we discuss the relationship of arrays and functions.
|
||
Specifically, arrays cannot be directly passed as an argument to a function call. Rather, arrays
|
||
are always passed as pointers. Because of this fact, the length of the array must be passed
|
||
explicitly as a separate parameter. The simplest example of this is the parameter list of
|
||
<code class="docutils literal notranslate"><span class="pre">main()</span></code>, which consists of an array (<code class="docutils literal notranslate"><span class="pre">argv</span></code>) and its array length (<code class="docutils literal notranslate"><span class="pre">argc</span></code>).</p>
|
||
<div class="highlight-c border border-dark rounded-lg bg-light px-0 mb-3 notranslate"><table class="highlighttable"><tr><td class="linenos px-0 mx-0"><div class="linenodiv"><pre class="mb-0">1
|
||
2
|
||
3
|
||
4
|
||
5</pre></div></td><td class="code"><div class="highlight bg-light"><pre class="mb-0"><span></span><span class="kt">int</span>
|
||
<span class="nf">main</span> <span class="p">(</span><span class="kt">int</span> <span class="n">argc</span><span class="p">,</span> <span class="kt">char</span> <span class="o">*</span><span class="n">argv</span><span class="p">[])</span>
|
||
<span class="p">{</span>
|
||
<span class="p">...</span>
|
||
<span class="p">}</span>
|
||
</pre></div>
|
||
</td></tr></table></div>
|
||
</div>
|
||
<div class="section" id="two-dimensional-arrays">
|
||
<h2>10.4.1. Two-dimensional Arrays<a class="headerlink" href="Arrays.html#two-dimensional-arrays" title="Permalink to this headline">¶</a></h2>
|
||
<p>One side effect of C not storing array lengths is the complexity of working with multi-dimensional
|
||
arrays. Consider <a class="reference external" href="Arrays.html#cla-14">Code Listing A.14</a> as an example. Line 6 declares an array that
|
||
contains two rows of three columns each. When declaring <code class="docutils literal notranslate"><span class="pre">data</span></code> on this line, the 3 must be
|
||
specified within the brackets to indicate the number of columns per row. That is, this declaration
|
||
could not be written as <code class="docutils literal notranslate"><span class="pre">data[][]</span></code>, even with the explicit initialization on the right side of the line.</p>
|
||
<div class="highlight-c border border-dark rounded-lg bg-light px-0 mb-3 notranslate" id="cla-14"><table class="highlighttable"><tr><td class="linenos px-0 mx-0"><div class="linenodiv"><pre class="mb-0"> 1
|
||
2
|
||
3
|
||
4
|
||
5
|
||
6
|
||
7
|
||
8
|
||
9
|
||
10
|
||
11
|
||
12
|
||
13
|
||
14
|
||
15
|
||
16
|
||
17
|
||
18
|
||
19
|
||
20
|
||
21
|
||
22
|
||
23
|
||
24
|
||
25</pre></div></td><td class="code"><div class="highlight bg-light"><pre class="mb-0"><span></span><span class="cm">/* Code Listing A.14:</span>
|
||
<span class="cm"> Traversing through a two-dimensional array</span>
|
||
<span class="cm"> */</span>
|
||
|
||
<span class="cm">/* Instantiate a2-d array and print its starting address */</span>
|
||
<span class="kt">uint32_t</span> <span class="n">data</span><span class="p">[][</span><span class="mi">3</span><span class="p">]</span> <span class="o">=</span> <span class="p">{</span> <span class="p">{</span> <span class="mi">1</span><span class="p">,</span> <span class="mi">2</span><span class="p">,</span> <span class="mi">3</span> <span class="p">},</span> <span class="p">{</span> <span class="mi">4</span><span class="p">,</span> <span class="mi">5</span><span class="p">,</span> <span class="mi">6</span> <span class="p">}</span> <span class="p">};</span>
|
||
<span class="n">printf</span> <span class="p">(</span><span class="s">"data starts at %p</span><span class="se">\n\n</span><span class="s">"</span><span class="p">,</span> <span class="n">data</span><span class="p">);</span>
|
||
|
||
<span class="cm">/* Make u32ptr point to data, but observe that this causes a</span>
|
||
<span class="cm"> compiler warning; the warning can be fixed by casting data</span>
|
||
<span class="cm"> ((uint32_t *)data) or using one layer of brackets (data[0]) */</span>
|
||
<span class="kt">uint32_t</span> <span class="o">*</span><span class="n">u32ptr</span> <span class="o">=</span> <span class="n">data</span><span class="p">;</span>
|
||
|
||
<span class="cm">/* Loop through the elements, observing that array bracket</span>
|
||
<span class="cm"> notation and pointer arithmetic behave identically */</span>
|
||
<span class="k">for</span> <span class="p">(</span><span class="kt">size_t</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o"><</span> <span class="mi">2</span><span class="p">;</span> <span class="n">i</span><span class="o">++</span><span class="p">)</span>
|
||
<span class="k">for</span> <span class="p">(</span><span class="kt">size_t</span> <span class="n">j</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">j</span> <span class="o"><</span> <span class="mi">3</span><span class="p">;</span> <span class="n">j</span><span class="o">++</span><span class="p">)</span>
|
||
<span class="p">{</span>
|
||
<span class="n">printf</span> <span class="p">(</span><span class="s">"data[%zd][%zd] address %p, value %08"</span> <span class="n">PRIx32</span> <span class="s">"</span><span class="se">\n</span><span class="s">"</span><span class="p">,</span>
|
||
<span class="n">i</span><span class="p">,</span> <span class="n">j</span><span class="p">,</span> <span class="o">&</span><span class="n">data</span><span class="p">[</span><span class="n">i</span><span class="p">][</span><span class="n">j</span><span class="p">],</span> <span class="n">data</span><span class="p">[</span><span class="n">i</span><span class="p">][</span><span class="n">j</span><span class="p">]);</span>
|
||
<span class="n">printf</span> <span class="p">(</span><span class="s">"u32ptr[%zd] address %p, value %08"</span> <span class="n">PRIx32</span> <span class="s">"</span><span class="se">\n</span><span class="s">"</span><span class="p">,</span>
|
||
<span class="n">i</span> <span class="o">*</span> <span class="mi">3</span> <span class="o">+</span> <span class="n">j</span><span class="p">,</span> <span class="o">&</span><span class="n">u32ptr</span><span class="p">[</span><span class="n">i</span> <span class="o">*</span> <span class="mi">3</span> <span class="o">+</span> <span class="n">j</span><span class="p">],</span> <span class="n">u32ptr</span><span class="p">[</span><span class="n">i</span> <span class="o">*</span> <span class="mi">3</span> <span class="o">+</span> <span class="n">j</span><span class="p">]);</span>
|
||
<span class="n">printf</span> <span class="p">(</span><span class="s">"u32ptr+%zd address %p, value %08"</span> <span class="n">PRIx32</span> <span class="s">"</span><span class="se">\n\n</span><span class="s">"</span><span class="p">,</span>
|
||
<span class="n">i</span> <span class="o">*</span> <span class="mi">3</span> <span class="o">+</span> <span class="n">j</span><span class="p">,</span> <span class="n">u32ptr</span> <span class="o">+</span> <span class="p">(</span><span class="n">i</span><span class="o">*</span><span class="mi">3</span><span class="o">+</span><span class="n">j</span><span class="p">),</span> <span class="o">*</span><span class="p">(</span><span class="n">u32ptr</span> <span class="o">+</span><span class="p">(</span><span class="n">i</span><span class="o">*</span><span class="mi">3</span><span class="o">+</span><span class="n">j</span><span class="p">)));</span>
|
||
<span class="p">}</span>
|
||
</pre></div>
|
||
</td></tr></table></div>
|
||
<div class="figure mb-2 align-right" id="id12" style="width: 40%">
|
||
<span id="twodptr"></span><a class="reference internal image-reference" href="_images/CSF-Images.A.2.png"><img class="p-3 mb-2 align-center border border-dark rounded-lg" alt="Creating a virtual 2-d array with an array of pointers" src="_images/CSF-Images.A.2.png" style="width: 95%;" /></a>
|
||
<p class="caption align-center px-3"><span class="caption-text"> Figure 10.4.2: Creating a virtual 2-d array with an array of pointers</span></p>
|
||
</div>
|
||
<p>The rest of <a class="reference external" href="Arrays.html#cla-14">Code Listing A.14</a> is modeled off of the structure of <a class="reference external" href="Arrays.html#cla-12">Code Listing A.12</a>. As in that example, there is a <code class="docutils literal notranslate"><span class="pre">u32ptr</span></code> that is set to point to the array (line 12).
|
||
Based on the declaration, though, <code class="docutils literal notranslate"><span class="pre">u32ptr</span></code> is a pointer to a <code class="docutils literal notranslate"><span class="pre">uint32_t</span></code>. Because of this
|
||
declaration, it can be used as a one-dimensional array, but not as a two dimensional array. That is
|
||
not a problem in this case, because C stores arrays in <em>row-major order</em>; in this order, the
|
||
first element of the second row is placed immediately after the last element of the first row. That
|
||
is, <code class="docutils literal notranslate"><span class="pre">data[1][0]</span></code> (the same as <code class="docutils literal notranslate"><span class="pre">u32ptr[3]</span></code>) immediately follows <code class="docutils literal notranslate"><span class="pre">data[0][2]</span></code> (the same as
|
||
<code class="docutils literal notranslate"><span class="pre">u32ptr[2]</span></code>). Thus, a one-dimensional array pointer like u32ptr can navigate the two-dimensional
|
||
structure by calculating its index as <code class="docutils literal notranslate"><span class="pre">i</span> <span class="pre">*</span> <span class="pre">3</span> <span class="pre">+</span> <span class="pre">j</span></code> (row times columns/row, plus the column number
|
||
of the current row). This requires, of course, knowledge of the number of columns per row. When
|
||
two-dimensional arrays are passed as arguments to functions, this additional information must be
|
||
passed explicitly as separate parameters.</p>
|
||
<p><a class="reference external" href="Arrays.html#cla-15">Code Listing A.15</a> demonstrates a common variation on two-dimensional arrays. In this
|
||
case, data is not declared as a two-dimensional array; rather, it is one-dimensional array of two
|
||
pointers. Its initialization in line 10 provides those two pointers: the addresses of the two arrays
|
||
<code class="docutils literal notranslate"><span class="pre">row0</span></code> and <code class="docutils literal notranslate"><span class="pre">row1</span></code>. Unlike the declaration structure of <a class="reference external" href="Arrays.html#cla-14">Code Listing A.14</a>, this
|
||
version does not guarantee that the elements can all be accessed in row-major order. The <code class="docutils literal notranslate"><span class="pre">row0</span></code>
|
||
and <code class="docutils literal notranslate"><span class="pre">row1</span></code> arrays are not guaranteed to be in any particular order in memory; consequently, we
|
||
cannot say that <code class="docutils literal notranslate"><span class="pre">row1[0]</span></code> immediately follows <code class="docutils literal notranslate"><span class="pre">row0[2]</span></code>. <a href="Arrays.html#twodptr">Figure 10.4.2</a>
|
||
illustrates the pointer structure of this declaration.</p>
|
||
<div class="highlight-c border border-dark rounded-lg bg-light px-0 mb-3 notranslate" id="cla-15"><table class="highlighttable"><tr><td class="linenos px-0 mx-0"><div class="linenodiv"><pre class="mb-0"> 1
|
||
2
|
||
3
|
||
4
|
||
5
|
||
6
|
||
7
|
||
8
|
||
9
|
||
10
|
||
11
|
||
12
|
||
13
|
||
14
|
||
15
|
||
16
|
||
17
|
||
18</pre></div></td><td class="code"><div class="highlight bg-light"><pre class="mb-0"><span></span><span class="cm">/* Code Listing A.15:</span>
|
||
<span class="cm"> Two-dimensional arrays as arrays of pointers</span>
|
||
<span class="cm"> */</span>
|
||
|
||
<span class="cm">/* Instantiate the rows separate */</span>
|
||
<span class="kt">uint32_t</span> <span class="n">row0</span><span class="p">[]</span> <span class="o">=</span> <span class="p">{</span> <span class="mi">1</span><span class="p">,</span> <span class="mi">2</span><span class="p">,</span> <span class="mi">3</span> <span class="p">};</span>
|
||
<span class="kt">uint32_t</span> <span class="n">row1</span><span class="p">[]</span> <span class="o">=</span> <span class="p">{</span> <span class="mi">4</span><span class="p">,</span> <span class="mi">5</span><span class="p">,</span> <span class="mi">6</span> <span class="p">};</span>
|
||
|
||
<span class="cm">/* data is an array of two pointers, NOT a 2-d array */</span>
|
||
<span class="kt">uint32_t</span> <span class="o">*</span><span class="n">data</span><span class="p">[]</span> <span class="o">=</span> <span class="p">{</span> <span class="n">row0</span><span class="p">,</span> <span class="n">row1</span> <span class="p">};</span>
|
||
|
||
<span class="cm">/* But we can still treat data as a 2-d array */</span>
|
||
<span class="k">for</span> <span class="p">(</span><span class="kt">size_t</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o"><</span> <span class="mi">2</span><span class="p">;</span> <span class="n">i</span><span class="o">++</span><span class="p">)</span>
|
||
<span class="p">{</span>
|
||
<span class="n">printf</span> <span class="p">(</span><span class="s">"data[%zd] = %p</span><span class="se">\n</span><span class="s">"</span><span class="p">,</span> <span class="n">i</span><span class="p">,</span> <span class="n">data</span><span class="p">[</span><span class="n">i</span><span class="p">]);</span>
|
||
<span class="k">for</span> <span class="p">(</span><span class="kt">size_t</span> <span class="n">j</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">j</span> <span class="o"><</span> <span class="mi">3</span><span class="p">;</span> <span class="n">j</span><span class="o">++</span><span class="p">)</span>
|
||
<span class="n">printf</span> <span class="p">(</span><span class="s">"&data[%zd][%zd] = %d <%p></span><span class="se">\n</span><span class="s">"</span><span class="p">,</span> <span class="n">i</span><span class="p">,</span> <span class="n">j</span><span class="p">,</span> <span class="n">data</span><span class="p">[</span><span class="n">i</span><span class="p">][</span><span class="n">j</span><span class="p">],</span> <span class="o">&</span><span class="n">data</span><span class="p">[</span><span class="n">i</span><span class="p">][</span><span class="n">j</span><span class="p">]);</span>
|
||
<span class="p">}</span>
|
||
</pre></div>
|
||
</td></tr></table></div>
|
||
<div class="figure mb-2 align-right" id="id13" style="width: 40%">
|
||
<span id="argvptrs"></span><a class="reference internal image-reference" href="_images/CSF-Images.A.3.png"><img class="p-3 mb-2 align-center border border-dark rounded-lg" alt="The argv array of command-line arguments is an array of pointers" src="_images/CSF-Images.A.3.png" style="width: 95%;" /></a>
|
||
<p class="caption align-center px-3"><span class="caption-text"> Figure 10.4.3: The <code class="docutils literal notranslate"><span class="pre">argv</span></code> array of command-line arguments is an array of pointers</span></p>
|
||
</div>
|
||
<p>Despite this more complex inner structure, lines 13 – 18 illustrate that the array can still be
|
||
treated like a two-dimensional array for accessing elements. This code works as an artifact of an
|
||
earlier point in this section: pointers can be dereferenced using bracket notation. In this case,
|
||
data is declared as an array of <code class="docutils literal notranslate"><span class="pre">uint32_t*</span></code> elements, so <code class="docutils literal notranslate"><span class="pre">data[0]</span></code> is a pointer storing the
|
||
address of <code class="docutils literal notranslate"><span class="pre">row0</span></code>. Accessing <code class="docutils literal notranslate"><span class="pre">data[0][1]</span></code>, then, is the same as accessing <code class="docutils literal notranslate"><span class="pre">row0[1]</span></code> because of
|
||
the pointer dereferencing.</p>
|
||
<p><a href="Arrays.html#argvptrs">Figure 10.4.3</a> illustrates a familiar example for this same concept. Consider the
|
||
command line to list files as <code class="docutils literal notranslate"><span class="pre">"ls</span> <span class="pre">-ltr"</span></code>. In this case, <code class="docutils literal notranslate"><span class="pre">argv[0]</span></code> is <code class="docutils literal notranslate"><span class="pre">"ls"</span></code> and <code class="docutils literal notranslate"><span class="pre">argv[1]</span></code>
|
||
is <code class="docutils literal notranslate"><span class="pre">"-ltr"</span></code> internal in the process that runs this program. Since the parameter is declared <code class="docutils literal notranslate"><span class="pre">char</span>
|
||
<span class="pre">*argv[]</span></code> (i.e., an array of pointers to <code class="docutils literal notranslate"><span class="pre">chars</span></code>), we can see that each element is a pointer to a
|
||
string.</p>
|
||
</div>
|
||
<div class="section" id="structs-and-packing">
|
||
<h2>10.4.2. Structs and Packing<a class="headerlink" href="Arrays.html#structs-and-packing" title="Permalink to this headline">¶</a></h2>
|
||
<p>Elements in an array are, by definition, all of the same type. Given the declaration <code class="docutils literal notranslate"><span class="pre">int</span>
|
||
<span class="pre">data[5]</span></code>, we know that the five elements are <code class="docutils literal notranslate"><span class="pre">int</span></code>s and these elements occupy a single block of
|
||
consecutive bytes in memory. The total size of this block is exactly the number of elements (5)
|
||
times the size of each element (an int is typically 4 bytes). To distinguish the elements within an
|
||
array, each element has a unique index that can be used in the bracket notation. As described
|
||
previously, bracket notation is semantically equivalent to calculating the offset to a memory
|
||
location using pointer arithmetic. That is, <code class="docutils literal notranslate"><span class="pre">data[2]</span></code> is equivalent to <code class="docutils literal notranslate"><span class="pre">*(data</span> <span class="pre">+</span> <span class="pre">2)</span></code>, and both
|
||
notations refer to the calculation of a particular offset from the starting address of <code class="docutils literal notranslate"><span class="pre">data</span></code>.</p>
|
||
<p>Like arrays, structs are used to create a chunk of contiguous data in memory, but with two
|
||
differences. First, the fields (rather than elements) of a <code class="docutils literal notranslate"><span class="pre">struct</span></code> are accessed with a name,
|
||
rather than an index. Second, the fields in a <code class="docutils literal notranslate"><span class="pre">struct</span></code> do not have to adhere to the same type.
|
||
<a class="reference external" href="Arrays.html#cla-16">Code Listing A.16</a> illustrates both of these facts with a <code class="docutils literal notranslate"><span class="pre">struct</span></code> declaration for
|
||
keeping track of time records. It is important to emphasize that lines 5 – 8 only define the
|
||
structure of one of these structs (similar to defining a class in an object-oriented language like
|
||
Java), rather than creating an instance of a <code class="docutils literal notranslate"><span class="pre">struct</span></code> in memory. In contrast, line 13 creates an
|
||
instance as a local variable, with lines 14 and 15 initializing the fields of this struct. This
|
||
declaration and initialization could be done on a single line, similar to initializing an array;
|
||
line 13 could be extended to read <code class="docutils literal notranslate"><span class="pre">ts</span> <span class="pre">=</span> <span class="pre">{</span> <span class="pre">100,</span> <span class="pre">258.9275</span> <span class="pre">}</span></code>, though this style requires knowing the
|
||
specific order of elements in the <code class="docutils literal notranslate"><span class="pre">struct</span></code>.</p>
|
||
<div class="highlight-c border border-dark rounded-lg bg-light px-0 mb-3 notranslate" id="cla-16"><table class="highlighttable"><tr><td class="linenos px-0 mx-0"><div class="linenodiv"><pre class="mb-0"> 1
|
||
2
|
||
3
|
||
4
|
||
5
|
||
6
|
||
7
|
||
8
|
||
9
|
||
10
|
||
11
|
||
12
|
||
13
|
||
14
|
||
15
|
||
16
|
||
17
|
||
18
|
||
19
|
||
20</pre></div></td><td class="code"><div class="highlight bg-light"><pre class="mb-0"><span></span><span class="cm">/* Code Listing A.16:</span>
|
||
<span class="cm"> A struct declaration to keep track of a time record</span>
|
||
<span class="cm"> */</span>
|
||
|
||
<span class="k">struct</span> <span class="n">timestamp</span> <span class="p">{</span>
|
||
<span class="kt">int</span> <span class="n">date</span><span class="p">;</span> <span class="c1">// days since a given start data</span>
|
||
<span class="kt">double</span> <span class="n">time</span><span class="p">;</span> <span class="c1">// seconds since midnight of the current day</span>
|
||
<span class="p">};</span>
|
||
|
||
<span class="kt">int</span>
|
||
<span class="nf">main</span> <span class="p">(</span><span class="kt">void</span><span class="p">)</span>
|
||
<span class="p">{</span>
|
||
<span class="k">struct</span> <span class="n">timestamp</span> <span class="n">ts</span><span class="p">;</span>
|
||
<span class="n">ts</span><span class="p">.</span><span class="n">date</span> <span class="o">=</span> <span class="mi">100</span><span class="p">;</span>
|
||
<span class="n">ts</span><span class="p">.</span><span class="n">time</span> <span class="o">=</span> <span class="mf">258.9275</span><span class="p">;</span>
|
||
|
||
<span class="n">printf</span> <span class="p">(</span><span class="s">"Time stamp: %d:%lf</span><span class="se">\n</span><span class="s">"</span><span class="p">,</span> <span class="n">ts</span><span class="p">.</span><span class="n">date</span><span class="p">,</span> <span class="n">ts</span><span class="p">.</span><span class="n">time</span><span class="p">);</span>
|
||
|
||
<span class="k">return</span> <span class="mi">0</span><span class="p">;</span>
|
||
<span class="p">}</span>
|
||
</pre></div>
|
||
</td></tr></table></div>
|
||
<p>In the computer systems field, this view of structs as <em>objects without methods</em> is not necessarily
|
||
sufficient. In particular, when two different machines are exchanging data, the two systems need to
|
||
agree on the layout and interpretation of the bytes without the <code class="docutils literal notranslate"><span class="pre">struct</span></code>. This agreement is not
|
||
necessarily guaranteed, even if the same source code is used. Different compilers may arrange the
|
||
fields in different orders, and the CPU may interpret multi-byte sequences differently due to
|
||
endianness issues. <a class="reference external" href="Arrays.html#cla-17">Code Listing A.17</a> demonstrates how to perform introspection into the
|
||
layout of a <code class="docutils literal notranslate"><span class="pre">struct</span></code> in code.</p>
|
||
<div class="highlight-c border border-dark rounded-lg bg-light px-0 mb-3 notranslate" id="cla-17"><table class="highlighttable"><tr><td class="linenos px-0 mx-0"><div class="linenodiv"><pre class="mb-0"> 1
|
||
2
|
||
3
|
||
4
|
||
5
|
||
6
|
||
7
|
||
8
|
||
9
|
||
10
|
||
11
|
||
12
|
||
13
|
||
14
|
||
15
|
||
16
|
||
17
|
||
18</pre></div></td><td class="code"><div class="highlight bg-light"><pre class="mb-0"><span></span><span class="cm">/* Code Listing A.17:</span>
|
||
<span class="cm"> Exploring the size and layout of a struct</span>
|
||
<span class="cm"> */</span>
|
||
|
||
<span class="k">struct</span> <span class="n">alternating</span> <span class="p">{</span>
|
||
<span class="kt">uint8_t</span> <span class="n">a</span><span class="p">;</span>
|
||
<span class="kt">uint32_t</span> <span class="n">b</span><span class="p">;</span>
|
||
<span class="kt">uint16_t</span> <span class="n">c</span><span class="p">;</span>
|
||
<span class="kt">uint8_t</span> <span class="n">d</span><span class="p">;</span>
|
||
<span class="p">};</span>
|
||
|
||
<span class="k">struct</span> <span class="n">alternating</span> <span class="n">alt</span> <span class="o">=</span> <span class="p">{</span> <span class="mi">1</span><span class="p">,</span> <span class="mi">2</span><span class="p">,</span> <span class="mi">3</span><span class="p">,</span> <span class="mi">4</span> <span class="p">};</span>
|
||
|
||
<span class="n">printf</span> <span class="p">(</span><span class="s">"sizeof(alt) = %zd</span><span class="se">\n</span><span class="s">"</span><span class="p">,</span> <span class="k">sizeof</span> <span class="p">(</span><span class="n">alt</span><span class="p">));</span>
|
||
<span class="n">printf</span> <span class="p">(</span><span class="s">"alt.a at %p, value %"</span> <span class="n">PRId8</span> <span class="s">"</span><span class="se">\n</span><span class="s">"</span><span class="p">,</span> <span class="o">&</span><span class="n">alt</span><span class="p">.</span><span class="n">a</span><span class="p">,</span> <span class="n">alt</span><span class="p">.</span><span class="n">a</span><span class="p">);</span>
|
||
<span class="n">printf</span> <span class="p">(</span><span class="s">"alt.b at %p, value %"</span> <span class="n">PRId32</span> <span class="s">"</span><span class="se">\n</span><span class="s">"</span><span class="p">,</span> <span class="o">&</span><span class="n">alt</span><span class="p">.</span><span class="n">b</span><span class="p">,</span> <span class="n">alt</span><span class="p">.</span><span class="n">b</span><span class="p">);</span>
|
||
<span class="n">printf</span> <span class="p">(</span><span class="s">"alt.c at %p, value %"</span> <span class="n">PRId16</span> <span class="s">"</span><span class="se">\n</span><span class="s">"</span><span class="p">,</span> <span class="o">&</span><span class="n">alt</span><span class="p">.</span><span class="n">c</span><span class="p">,</span> <span class="n">alt</span><span class="p">.</span><span class="n">c</span><span class="p">);</span>
|
||
<span class="n">printf</span> <span class="p">(</span><span class="s">"alt.d at %p, value %"</span> <span class="n">PRId8</span> <span class="s">"</span><span class="se">\n</span><span class="s">"</span><span class="p">,</span> <span class="o">&</span><span class="n">alt</span><span class="p">.</span><span class="n">d</span><span class="p">,</span> <span class="n">alt</span><span class="p">.</span><span class="n">d</span><span class="p">);</span>
|
||
</pre></div>
|
||
</td></tr></table></div>
|
||
<p>Line 14 prints the size of one <code class="docutils literal notranslate"><span class="pre">struct</span> <span class="pre">alternating</span></code> instance, <code class="docutils literal notranslate"><span class="pre">alt</span></code>. Reading lines 5 – 10
|
||
suggests that line 14 will indicate that the size of <code class="docutils literal notranslate"><span class="pre">alt</span></code> is 8 bytes (4 for <code class="docutils literal notranslate"><span class="pre">a</span></code>, 1 for <code class="docutils literal notranslate"><span class="pre">b</span></code>, 2
|
||
for <code class="docutils literal notranslate"><span class="pre">c</span></code>, and 1 for <code class="docutils literal notranslate"><span class="pre">d</span></code>). This intuition is wrong for typical compilers and modern hardware.
|
||
Using both the <code class="docutils literal notranslate"><span class="pre">clang</span></code> and <code class="docutils literal notranslate"><span class="pre">gcc</span></code> compilers on an x86 architecture, the compiled code indicates
|
||
that <code class="docutils literal notranslate"><span class="pre">alt</span></code> is 12 bytes in size. The specific layout of the memory for <code class="docutils literal notranslate"><span class="pre">alt</span></code> is shown in <a class="reference external" href="Arrays.html#tblA-4">Table A.4</a>.
|
||
To be precise, the address of <code class="docutils literal notranslate"><span class="pre">alt</span></code> is the address of the byte on the left,
|
||
containing the value <code class="docutils literal notranslate"><span class="pre">0x01</span></code>; the memory addresses increase from left to right in this table. As
|
||
x86 is a little-endian architecture, the bytes of the multi-byte fields <code class="docutils literal notranslate"><span class="pre">b</span></code> and <code class="docutils literal notranslate"><span class="pre">c</span></code> are
|
||
structured with the least-significant byte on the left (indicating a lower address offset within the
|
||
<code class="docutils literal notranslate"><span class="pre">struct</span></code>).</p>
|
||
<center>
|
||
<table class="table table-bordered">
|
||
<thead class="jmu-dark-purple-bg text-light">
|
||
<tr>
|
||
<th class="py-0 center"><code class="text-light">a</code></th>
|
||
<th class="py-0 center"><code class="text-light">??</code></th>
|
||
<th class="py-0 center"><code class="text-light">??</code></th>
|
||
<th class="py-0 center"><code class="text-light">??</code></th>
|
||
<th class="py-0 center" colspan="4"><code class="text-light">b</code></th>
|
||
<th class="py-0 center" colspan="2"><code class="text-light">c</code></th>
|
||
<th class="py-0 center"><code class="text-light">d</code></th>
|
||
<th class="py-0 center"><code class="text-light">??</code></th>
|
||
</tr>
|
||
</thead>
|
||
<tbody>
|
||
<tr>
|
||
<td class="py-0 center" width="8.3%"><code>01</code></td>
|
||
<td class="py-0 center" width="8.3%"><code>??</code></td>
|
||
<td class="py-0 center" width="8.3%"><code>??</code></td>
|
||
<td class="py-0 center" width="8.3%"><code>??</code></td>
|
||
<td class="py-0 center" width="8.3%"><code>02</code></td>
|
||
<td class="py-0 center" width="8.3%"><code>00</code></td>
|
||
<td class="py-0 center" width="8.3%"><code>00</code></td>
|
||
<td class="py-0 center" width="8.3%"><code>00</code></td>
|
||
<td class="py-0 center" width="8.3%"><code>03</code></td>
|
||
<td class="py-0 center" width="8.3%"><code>00</code></td>
|
||
<td class="py-0 center" width="8.3%"><code>04</code></td>
|
||
<td class="py-0 center"><code>??</code></td>
|
||
</tr>
|
||
</tbody>
|
||
</table>
|
||
<p>Table A.4: The layout of an unpacked struct with padding bytes</p>
|
||
</center>
|
||
<br /><p>The fields shown as <code class="docutils literal notranslate"><span class="pre">??</span></code> in <a class="reference external" href="Arrays.html#tblA-4">Table A.4</a> indicate additional bytes of padding. The
|
||
compiler injects this padding because of how memory is physically access by the CPU. The compiler
|
||
can also (but does not in this case, re-order the fields if necessary. Generally speaking, bytes
|
||
that are stored in the same <em>memory word</em> can be accessed in a single CPU cycle. A memory word
|
||
is a sequence of four consecutive bytes, but these bytes need to begin at a <em>word boundary</em>
|
||
(an address that is evenly divisible by four). If we assume that alt begins at address
|
||
<code class="docutils literal notranslate"><span class="pre">0x7ffe000027c0</span></code> (which is a word boundary), the three bytes of padding just after the <code class="docutils literal notranslate"><span class="pre">a</span></code>
|
||
ensure that <code class="docutils literal notranslate"><span class="pre">b</span></code> starts at another word boundary, <code class="docutils literal notranslate"><span class="pre">0x7ffe000027c4</span></code>. If b, instead, began
|
||
immediately after <code class="docutils literal notranslate"><span class="pre">a</span></code> at address <code class="docutils literal notranslate"><span class="pre">0x7ffe000027c1</span></code>, then the contents of <code class="docutils literal notranslate"><span class="pre">b</span></code> would span two
|
||
distinct memory words. As a result, accessing <code class="docutils literal notranslate"><span class="pre">b</span></code> would now require two CPU cycles instead of just
|
||
one. This additional cycle might sound trivial (since there are billions of cycles per second), but
|
||
the cumulative effect over all programs would be significant. The padding after the d rounds up the
|
||
size of the <code class="docutils literal notranslate"><span class="pre">struct</span></code> to be an exact multiple of three words. This padding helps ensure other data
|
||
on the stack around the <code class="docutils literal notranslate"><span class="pre">alt</span></code> variable also begin at word boundaries.</p>
|
||
<p>But what if the code needs to adhere to a specification that the <code class="docutils literal notranslate"><span class="pre">struct</span> <span class="pre">alternating</span></code> cannot have
|
||
padding? That is, each <code class="docutils literal notranslate"><span class="pre">struct</span></code> instance needs to be exactly eight bytes, interpreted in the order
|
||
defined by the <code class="docutils literal notranslate"><span class="pre">struct</span></code>. In this case, the <code class="docutils literal notranslate"><span class="pre">struct</span></code> needs to be declared as <em>packed</em>,
|
||
meaning that there is no padding or re-ordering allowed. To declare the <code class="docutils literal notranslate"><span class="pre">struct</span></code> as packed, the
|
||
only change is to modify the first line of <a class="reference external" href="Arrays.html#cla-17">Code Listing A.17</a> with the packed attribute:</p>
|
||
<div class="highlight-c border border-dark rounded-lg bg-light px-2 mb-3 notranslate"><div class="highlight bg-light"><pre class="mb-0"><span></span><span class="k">struct</span> <span class="nf">__attribute__</span><span class="p">((</span><span class="n">__packed__</span><span class="p">))</span> <span class="n">alternating</span> <span class="p">{</span>
|
||
</pre></div>
|
||
</div>
|
||
<div class="topic border border-dark rounded-lg bg-light px-2 mb-3">
|
||
<div class="figure align-left">
|
||
<a class="reference internal image-reference" href="_images/CSF-Images-Note.png"><img alt="Decorative note icon" src="_images/CSF-Images-Note.png" style="width: 100%;" /></a>
|
||
</div>
|
||
<p class="topic-title first pt-2 mb-1">Note</p><hr class="mt-1" />
|
||
<p>Computer systems frequently take advantage of very compact data representations, particular in the
|
||
networking domain. Bit masks, for instance, use the individual bits within a byte to represent
|
||
distinct pieces of information. Within the <code class="docutils literal notranslate"><span class="pre">struct</span></code> declaration, the individual field names are
|
||
append with <code class="docutils literal notranslate"><span class="pre">:n</span></code> to indicate that the field occupies <code class="docutils literal notranslate"><span class="pre">n</span></code> bits. Packed structs also help with
|
||
this data compression by ensuring that there is no padding added. Consider the following example:</p>
|
||
<div class="highlight-c border border-dark rounded-lg bg-light px-0 mb-3 notranslate"><table class="highlighttable"><tr><td class="linenos px-0 mx-0"><div class="linenodiv"><pre class="mb-0"> 1
|
||
2
|
||
3
|
||
4
|
||
5
|
||
6
|
||
7
|
||
8
|
||
9
|
||
10
|
||
11
|
||
12
|
||
13
|
||
14
|
||
15
|
||
16</pre></div></td><td class="code"><div class="highlight bg-light"><pre class="mb-0"><span></span><span class="k">struct</span> <span class="nf">__attribute__</span><span class="p">((</span><span class="n">__packed__</span><span class="p">))</span> <span class="n">bits</span> <span class="p">{</span>
|
||
<span class="kt">unsigned</span> <span class="nl">type</span><span class="p">:</span><span class="mi">2</span><span class="p">;</span> <span class="c1">// can be 0, 1, 2, or 3</span>
|
||
<span class="kt">unsigned</span> <span class="nl">urgent</span><span class="p">:</span><span class="mi">1</span><span class="p">;</span> <span class="c1">// can be true (1) or false (0)</span>
|
||
<span class="kt">unsigned</span> <span class="nl">length</span><span class="p">:</span><span class="mi">7</span><span class="p">;</span> <span class="c1">// anywhere from 0 to 31</span>
|
||
<span class="p">};</span>
|
||
|
||
<span class="k">struct</span> <span class="n">bits</span> <span class="n">data</span><span class="p">;</span>
|
||
<span class="n">memset</span> <span class="p">(</span><span class="o">&</span><span class="n">data</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="k">sizeof</span> <span class="p">(</span><span class="n">data</span><span class="p">));</span> <span class="c1">// ensure all bits init to 0</span>
|
||
<span class="n">data</span><span class="p">.</span><span class="n">type</span> <span class="o">=</span> <span class="mi">3</span><span class="p">;</span>
|
||
<span class="n">data</span><span class="p">.</span><span class="n">urgent</span> <span class="o">=</span> <span class="nb">false</span><span class="p">;</span>
|
||
<span class="n">data</span><span class="p">.</span><span class="n">length</span> <span class="o">=</span> <span class="mi">27</span><span class="p">;</span>
|
||
|
||
<span class="n">printf</span> <span class="p">(</span><span class="s">"Size of data is %zd</span><span class="se">\n</span><span class="s">"</span><span class="p">,</span> <span class="k">sizeof</span> <span class="p">(</span><span class="n">data</span><span class="p">));</span>
|
||
|
||
<span class="cm">/* Cast the address of data to a uint16_t* and dereference it */</span>
|
||
<span class="n">printf</span> <span class="p">(</span><span class="s">"data as a hex int is %04"</span> <span class="n">PRIx16</span> <span class="s">"</span><span class="se">\n</span><span class="s">"</span><span class="p">,</span> <span class="o">*</span><span class="p">((</span><span class="kt">uint16_t</span><span class="o">*</span><span class="p">)</span> <span class="o">&</span><span class="n">data</span><span class="p">));</span>
|
||
</pre></div>
|
||
</td></tr></table></div>
|
||
<p>The declaration of <code class="docutils literal notranslate"><span class="pre">struct</span> <span class="pre">bits</span></code> indicates that one instance requires 10 bits. Since we cannot
|
||
actually allocate data at this bit level, this instance would be padded to make it exactly two
|
||
bytes (16 bits) in size. Among those 16 bits, the C standard does not specify an exact order. The
|
||
fields should only be accessed through their names, as shown in line 9 – 11. It is possible,
|
||
however, to determine the layout on a particular system through trial and error. The <code class="docutils literal notranslate"><span class="pre">printf()</span></code>
|
||
call on lines 15 and 16 reveal that one possible layout is as follows:</p>
|
||
<center>
|
||
<table class="table table-bordered">
|
||
<thead class="jmu-dark-purple-bg text-light">
|
||
<tr>
|
||
<th class="py-0 center" colspan="8">First byte</th>
|
||
<th class="py-0 center" colspan="8">Second byte</th>
|
||
</tr>
|
||
<tr>
|
||
<th class="py-0 center" colspan="6"><em>[unnamed and unused]</em></th>
|
||
<th class="py-0 center" colspan="7"><code class="text-light">length</code></th>
|
||
<th class="py-0 center"><code class="text-light">urg</code></th>
|
||
<th class="py-0 center" colspan="2"><code class="text-light">type</code></th>
|
||
</tr>
|
||
</thead>
|
||
<tbody>
|
||
<tr>
|
||
<td class="py-0 center" width="6.25%"><code>0</code></td>
|
||
<td class="py-0 center" width="6.25%"><code>0</code></td>
|
||
<td class="py-0 center" width="6.25%"><code>0</code></td>
|
||
<td class="py-0 center" width="6.25%"><code>0</code></td>
|
||
<td class="py-0 center" width="6.25%"><code>0</code></td>
|
||
<td class="py-0 center" width="6.25%"><code>0</code></td>
|
||
<td class="py-0 center" width="6.25%"><code>0</code></td>
|
||
<td class="py-0 center" width="6.25%"><code>0</code></td>
|
||
<td class="py-0 center" width="6.25%"><code>1</code></td>
|
||
<td class="py-0 center" width="6.25%"><code>1</code></td>
|
||
<td class="py-0 center" width="6.25%"><code>0</code></td>
|
||
<td class="py-0 center" width="6.25%"><code>1</code></td>
|
||
<td class="py-0 center" width="6.25%"><code>1</code></td>
|
||
<td class="py-0 center" width="6.25%"><code>0</code></td>
|
||
<td class="py-0 center" width="6.25%"><code>1</code></td>
|
||
<td class="py-0 center" width="6.25%"><code>1</code></td>
|
||
</tr>
|
||
<tr>
|
||
<td class="py-0 center" colspan="4"><code>0</code></td>
|
||
<td class="py-0 center" colspan="4"><code>0</code></td>
|
||
<td class="py-0 center" colspan="4"><code>d</code></td>
|
||
<td class="py-0 center" colspan="4"><code>b</code></td>
|
||
</tr>
|
||
</tbody>
|
||
</table>
|
||
</center><p>Based on this illustration, the seven bits of the <code class="docutils literal notranslate"><span class="pre">length</span></code> field spans the two bytes, whereas
|
||
<code class="docutils literal notranslate"><span class="pre">urgent</span></code> and <code class="docutils literal notranslate"><span class="pre">type</span></code> both reside in the second byte. The bottom line shows the hexadecimal
|
||
representation of four bits at a time. Printing the full value, as on lines 15 and 16, produces the
|
||
output <code class="docutils literal notranslate"><span class="pre">0x00db</span></code>.</p>
|
||
</div>
|
||
</div>
|
||
<div class="section" id="enums-and-type-definitions">
|
||
<h2>10.4.3. Enums and Type Definitions<a class="headerlink" href="Arrays.html#enums-and-type-definitions" title="Permalink to this headline">¶</a></h2>
|
||
<p>From the programmer’s perspective, C’s built-in types and <code class="docutils literal notranslate"><span class="pre">struct</span></code>s are low-level primitives that
|
||
make it difficult to read and understand the code. For instance, in the case of <code class="docutils literal notranslate"><span class="pre">struct</span></code>s, the
|
||
type is always the full name consisting of <code class="docutils literal notranslate"><span class="pre">struct</span></code> and the identifier following it. In the case
|
||
of <code class="docutils literal notranslate"><span class="pre">alt</span></code> from <a class="reference external" href="Arrays.html#cla-17">Code Listing A.17</a>, its type is <code class="docutils literal notranslate"><span class="pre">struct</span> <span class="pre">alternating</span></code>; its type is not
|
||
<code class="docutils literal notranslate"><span class="pre">struct</span></code>, nor is its type <code class="docutils literal notranslate"><span class="pre">alternating</span></code>. Copying the word <code class="docutils literal notranslate"><span class="pre">struct</span></code> around gets tedious and it
|
||
detracts from the readability. As for the primitive types, an int indicates an integer value, but
|
||
what if there are only certain integers that are valid? For instance, consider a variable that is
|
||
used to keep track of the day of the week (Sunday through Saturday) as an integer (Sunday is 1,
|
||
Saturday is 7). Referring to day 37 might lead to an unpredictable error.</p>
|
||
<p>To start with the latter problem, the solution is to define an enumerated type, or <code class="docutils literal notranslate"><span class="pre">enum</span></code>. An
|
||
<code class="docutils literal notranslate"><span class="pre">enum</span></code> is a custom integer type that allows the programmer to use names instead of numeric
|
||
constants. <a class="reference external" href="Arrays.html#cla-18">Code Listing A.18</a> declares an <code class="docutils literal notranslate"><span class="pre">enum</span></code> for the days of the week as
|
||
previously described. In the declaration, the values in the <code class="docutils literal notranslate"><span class="pre">enum</span></code> are automatically incremented.
|
||
By setting <code class="docutils literal notranslate"><span class="pre">SUN</span></code> = 1 (instead of allowing the default starting value of 0), <code class="docutils literal notranslate"><span class="pre">MON</span></code> would be 2,
|
||
<code class="docutils literal notranslate"><span class="pre">TUE</span></code> would be 3, and so on. The advantage of the <code class="docutils literal notranslate"><span class="pre">enum</span></code> is that we can use these meaningful
|
||
names (<code class="docutils literal notranslate"><span class="pre">MON</span></code>, <code class="docutils literal notranslate"><span class="pre">TUE</span></code>, <code class="docutils literal notranslate"><span class="pre">WED</span></code>, …) instead of memorizing numeric values. We can also declare
|
||
variables using the <code class="docutils literal notranslate"><span class="pre">enum</span></code> type as shown on line 6.</p>
|
||
<div class="highlight-c border border-dark rounded-lg bg-light px-0 mb-3 notranslate" id="cla-18"><table class="highlighttable"><tr><td class="linenos px-0 mx-0"><div class="linenodiv"><pre class="mb-0">1
|
||
2
|
||
3
|
||
4
|
||
5
|
||
6
|
||
7</pre></div></td><td class="code"><div class="highlight bg-light"><pre class="mb-0"><span></span><span class="cm">/* Code Listing A.18:</span>
|
||
<span class="cm"> Declaring the days of the week as an enumerated type</span>
|
||
<span class="cm"> */</span>
|
||
|
||
<span class="k">enum</span> <span class="n">days</span> <span class="p">{</span> <span class="n">SUN</span> <span class="o">=</span> <span class="mi">1</span><span class="p">,</span> <span class="n">MON</span><span class="p">,</span> <span class="n">TUE</span><span class="p">,</span> <span class="n">WED</span><span class="p">,</span> <span class="n">THU</span><span class="p">,</span> <span class="n">FRI</span><span class="p">,</span> <span class="n">SAT</span> <span class="p">};</span>
|
||
<span class="k">enum</span> <span class="n">days</span> <span class="n">today</span> <span class="o">=</span> <span class="n">WED</span><span class="p">;</span>
|
||
<span class="n">printf</span> <span class="p">(</span><span class="s">"Tomorrow is %d</span><span class="se">\n</span><span class="s">"</span><span class="p">,</span> <span class="n">today</span> <span class="o">+</span> <span class="mi">1</span><span class="p">);</span>
|
||
</pre></div>
|
||
</td></tr></table></div>
|
||
<p>To be clear, <code class="docutils literal notranslate"><span class="pre">enum</span></code>s are a syntactical mechanism of convenience, not security. Internally, an
|
||
<code class="docutils literal notranslate"><span class="pre">enum</span></code> is just an <code class="docutils literal notranslate"><span class="pre">int</span></code>, and C does not perform any bounds checking to ensure that the values of
|
||
an <code class="docutils literal notranslate"><span class="pre">enum</span></code> variable (such as today) match the names or the range in the definition. Line 6 could
|
||
initialize today to be 37, or line 7 could be changed to use <code class="docutils literal notranslate"><span class="pre">today</span> <span class="pre">-</span> <span class="pre">452</span></code>; either would be allowed,
|
||
as today is ultimately just an <code class="docutils literal notranslate"><span class="pre">int</span></code> variable.</p>
|
||
<p>The <code class="docutils literal notranslate"><span class="pre">enum</span></code> keyword has the same problem as the <code class="docutils literal notranslate"><span class="pre">struct</span></code> keyword, in that it must be included in
|
||
the type name and passed around throughout the code. In <a class="reference external" href="Arrays.html#cla-18">Code Listing A.18</a>, the type of
|
||
the today variable is <code class="docutils literal notranslate"><span class="pre">enum</span> <span class="pre">days</span></code>, not <code class="docutils literal notranslate"><span class="pre">enum</span></code> or <code class="docutils literal notranslate"><span class="pre">days</span></code>. To make the code more readable for
|
||
both <code class="docutils literal notranslate"><span class="pre">enum</span></code>s and <code class="docutils literal notranslate"><span class="pre">struct</span></code>s, we can declare a new custom type name with the <code class="docutils literal notranslate"><span class="pre">typedef</span></code>
|
||
keyword. <a class="reference external" href="Arrays.html#cla-19">Code Listing A.19</a> uses <code class="docutils literal notranslate"><span class="pre">typedef</span></code> on the <code class="docutils literal notranslate"><span class="pre">enum</span></code> from <a class="reference external" href="Arrays.html#cla-18">A.18</a> and
|
||
the <code class="docutils literal notranslate"><span class="pre">struct</span></code> from <a class="reference external" href="Arrays.html#cla-17">A.17</a>.</p>
|
||
<div class="highlight-c border border-dark rounded-lg bg-light px-0 mb-3 notranslate" id="cla-19"><table class="highlighttable"><tr><td class="linenos px-0 mx-0"><div class="linenodiv"><pre class="mb-0"> 1
|
||
2
|
||
3
|
||
4
|
||
5
|
||
6
|
||
7
|
||
8
|
||
9
|
||
10
|
||
11
|
||
12
|
||
13
|
||
14
|
||
15</pre></div></td><td class="code"><div class="highlight bg-light"><pre class="mb-0"><span></span><span class="cm">/* Code Listing A.19:</span>
|
||
<span class="cm"> Simplifying enum and struct type names with a typedef</span>
|
||
<span class="cm"> */</span>
|
||
|
||
<span class="k">typedef</span> <span class="k">enum</span> <span class="n">days</span> <span class="p">{</span> <span class="n">SUN</span> <span class="o">=</span> <span class="mi">1</span><span class="p">,</span> <span class="n">MON</span><span class="p">,</span> <span class="n">TUE</span><span class="p">,</span> <span class="n">WED</span><span class="p">,</span> <span class="n">THU</span><span class="p">,</span> <span class="n">FRI</span><span class="p">,</span> <span class="n">SAT</span> <span class="p">}</span> <span class="n">day_t</span><span class="p">;</span>
|
||
<span class="n">day_t</span> <span class="n">today</span> <span class="o">=</span> <span class="n">WED</span><span class="p">;</span>
|
||
|
||
<span class="k">typedef</span> <span class="k">struct</span> <span class="n">alternating</span> <span class="p">{</span>
|
||
<span class="kt">uint8_t</span> <span class="n">a</span><span class="p">;</span>
|
||
<span class="kt">uint32_t</span> <span class="n">b</span><span class="p">;</span>
|
||
<span class="kt">uint16_t</span> <span class="n">c</span><span class="p">;</span>
|
||
<span class="kt">uint8_t</span> <span class="n">d</span><span class="p">;</span>
|
||
<span class="p">}</span> <span class="n">alt_t</span><span class="p">;</span>
|
||
|
||
<span class="n">alt_t</span> <span class="n">alt</span> <span class="o">=</span> <span class="p">{</span> <span class="mi">1</span><span class="p">,</span> <span class="mi">2</span><span class="p">,</span> <span class="mi">3</span><span class="p">,</span> <span class="mi">4</span> <span class="p">};</span>
|
||
</pre></div>
|
||
</td></tr></table></div>
|
||
<p>The general structure for declaring a new type is <code class="docutils literal notranslate"><span class="pre">typedef</span> <span class="pre">[existing</span> <span class="pre">type]</span> <span class="pre">[new</span> <span class="pre">type</span> <span class="pre">name];</span></code>. By
|
||
convention, the new type name typically ends with <code class="docutils literal notranslate"><span class="pre">_t</span></code> to indicate that this is a type. Observe
|
||
that there are many such type definitions in the C standard library. For instance, the <code class="docutils literal notranslate"><span class="pre">size_t</span></code>
|
||
type is defined (indirectly, as there are several chained type definitions involved) in the
|
||
<code class="docutils literal notranslate"><span class="pre">ctype.h</span></code> header as shown below. The advantage of using the type definition is that it provides
|
||
additional semantics. A variable declared as a <code class="docutils literal notranslate"><span class="pre">size_t</span></code> is not just being used as an integer, but
|
||
as the size of something.</p>
|
||
<div class="highlight-c border border-dark rounded-lg bg-light px-2 mb-3 notranslate"><div class="highlight bg-light"><pre class="mb-0"><span></span><span class="k">typedef</span> <span class="kt">int32_t</span> <span class="kt">size_t</span><span class="p">;</span>
|
||
</pre></div>
|
||
</div>
|
||
<p>One common problem with type definitions for <code class="docutils literal notranslate"><span class="pre">struct</span></code>s,`in particular, is when there are circular
|
||
dependencies. Consider <a class="reference external" href="Arrays.html#cla-20">Code Listing A.20</a> that defines a <code class="docutils literal notranslate"><span class="pre">person_t</span></code> type and an
|
||
<code class="docutils literal notranslate"><span class="pre">age_t</span></code> type. In this application, each person (<code class="docutils literal notranslate"><span class="pre">person_t</span></code>) has a unique name and age, but each
|
||
<code class="docutils literal notranslate"><span class="pre">age_t</span></code> has and unique year and pointers to up to 5 people. In other words, the person_t
|
||
definition needs to know about the <code class="docutils literal notranslate"><span class="pre">age_t</span></code> type, while the <code class="docutils literal notranslate"><span class="pre">age_t</span></code> definition needs to know
|
||
about the <code class="docutils literal notranslate"><span class="pre">person_t</span></code> type. The problem is that the definition of <code class="docutils literal notranslate"><span class="pre">person_t</span></code> (lines 7 – 10) comes
|
||
before the C compiler has learned about the <code class="docutils literal notranslate"><span class="pre">age_t</span></code> type (line 15); the C compiler cannot look
|
||
ahead, so using age_t on line 9 would be a compiler error.</p>
|
||
<div class="highlight-c border border-dark rounded-lg bg-light px-0 mb-3 notranslate" id="cla-20"><table class="highlighttable"><tr><td class="linenos px-0 mx-0"><div class="linenodiv"><pre class="mb-0"> 1
|
||
2
|
||
3
|
||
4
|
||
5
|
||
6
|
||
7
|
||
8
|
||
9
|
||
10
|
||
11
|
||
12
|
||
13
|
||
14
|
||
15</pre></div></td><td class="code"><div class="highlight bg-light"><pre class="mb-0"><span></span><span class="cm">/* Code Listing A.20:</span>
|
||
<span class="cm"> Defining two structs with a circular definition</span>
|
||
<span class="cm"> */</span>
|
||
|
||
<span class="k">struct</span> <span class="n">age</span><span class="p">;</span> <span class="c1">// dummy struct definition</span>
|
||
|
||
<span class="k">typedef</span> <span class="k">struct</span> <span class="n">person</span> <span class="p">{</span>
|
||
<span class="kt">char</span> <span class="o">*</span><span class="n">name</span><span class="p">;</span>
|
||
<span class="k">struct</span> <span class="n">age</span> <span class="o">*</span><span class="n">age</span><span class="p">;</span>
|
||
<span class="p">}</span> <span class="n">person_t</span><span class="p">;</span>
|
||
|
||
<span class="k">typedef</span> <span class="k">struct</span> <span class="n">age</span> <span class="p">{</span>
|
||
<span class="kt">int</span> <span class="n">year</span><span class="p">;</span>
|
||
<span class="n">person_t</span> <span class="o">*</span><span class="n">people</span><span class="p">[</span><span class="mi">5</span><span class="p">];</span>
|
||
<span class="p">}</span> <span class="n">age_t</span><span class="p">;</span>
|
||
</pre></div>
|
||
</td></tr></table></div>
|
||
<p>The solution is to use a dummy <code class="docutils literal notranslate"><span class="pre">struct</span></code> definition on line 5 that matches the name on line 12. (It
|
||
is vital that the name of both <code class="docutils literal notranslate"><span class="pre">struct</span></code> types match.) By structuring the code this way, the
|
||
compiler is able to correctly link the type of the age field within <code class="docutils literal notranslate"><span class="pre">person_t</span></code> as a pointer to an
|
||
<code class="docutils literal notranslate"><span class="pre">age_t</span></code> instance later. Once this is done, the circular definition can be ignored, as shown in
|
||
<a class="reference external" href="Arrays.html#cla-21">Code Listing A.21</a>. The <code class="docutils literal notranslate"><span class="pre">person_t</span></code> instance is able to set its age field to the
|
||
address of an <code class="docutils literal notranslate"><span class="pre">age_t</span></code> instance without causing a compiler error or warning.</p>
|
||
<div class="highlight-c border border-dark rounded-lg bg-light px-0 mb-3 notranslate" id="cla-21"><table class="highlighttable"><tr><td class="linenos px-0 mx-0"><div class="linenodiv"><pre class="mb-0"> 1
|
||
2
|
||
3
|
||
4
|
||
5
|
||
6
|
||
7
|
||
8
|
||
9
|
||
10
|
||
11
|
||
12</pre></div></td><td class="code"><div class="highlight bg-light"><pre class="mb-0"><span></span><span class="cm">/* Code Listing A.21:</span>
|
||
<span class="cm"> When using the structs, the circular definition is not visible</span>
|
||
<span class="cm"> */</span>
|
||
|
||
<span class="n">person_t</span> <span class="n">person</span><span class="p">;</span>
|
||
<span class="n">age_t</span> <span class="n">age</span><span class="p">;</span>
|
||
|
||
<span class="n">person</span><span class="p">.</span><span class="n">name</span> <span class="o">=</span> <span class="s">"Gustavo"</span><span class="p">;</span>
|
||
<span class="n">person</span><span class="p">.</span><span class="n">age</span> <span class="o">=</span> <span class="o">&</span><span class="n">age</span><span class="p">;</span>
|
||
|
||
<span class="n">age</span><span class="p">.</span><span class="n">year</span> <span class="o">=</span> <span class="mi">35</span><span class="p">;</span>
|
||
<span class="n">age</span><span class="p">.</span><span class="n">people</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">=</span> <span class="o">&</span><span class="n">person</span><span class="p">;</span>
|
||
</pre></div>
|
||
</td></tr></table></div>
|
||
</div>
|
||
</div>
|
||
|
||
|
||
</div>
|
||
|
||
|
||
|
||
<div class="container">
|
||
|
||
<div class="mt-4 container center">
|
||
«  <a id="prevmod1" href="BasicTypes.html">10.3. Basic Types and Pointers</a>
|
||
  ::  
|
||
<a class="uplink" href="index.html">Contents</a>
|
||
  ::  
|
||
<a id="nextmod1" href="Functions.html">10.5. Functions and Scope</a>  »
|
||
</div>
|
||
|
||
|
||
</div>
|
||
|
||
<br />
|
||
|
||
<div class="row jmu-dark-purple-bg">
|
||
<div class="col-md-12">
|
||
<center>
|
||
<a id="contact_us" class="btn button-link-no-blue jmu-gold" rel="nofollow" href="mailto:webmaster@opencsf.org" role="button">Contact Us</a>
|
||
<a id="license" class="btn button-link-no-blue jmu-gold" rel="nofollow" href="https://w3.cs.jmu.edu/kirkpams/OpenCSF/lib/license.html" target="_blank">License</a>
|
||
</center>
|
||
</div>
|
||
</div>
|
||
|
||
|
||
|
||
|
||
|
||
|
||
<script src="_static/js/popper.js-1.14.7-min.js" integrity="sha384-UO2eT0CpHqdSJQ6hJty5KVphtPhzWj9WO1clHTMGa3JDZwrnQq4sF86dIHNDz0W1" crossorigin="anonymous"></script>
|
||
<script src="_static/js/bootstrap.min.js" integrity="sha384-JjSmVgyd0p3pXB1rRibZUAYoIIy6OrQ6VrjIEaFf/nJGzIxFDsf4x0xIM+B07jRM" crossorigin="anonymous"></script>
|
||
</body>
|
||
</html> |