﻿<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>C/C++ - Linux迷</title>
	<atom:link href="https://www.linuxmi.com/c/feed" rel="self" type="application/rss+xml" />
	<link>https://www.linuxmi.com</link>
	<description>分享Linux和编程</description>
	<lastBuildDate>Sat, 18 Nov 2023 01:07:08 +0000</lastBuildDate>
	<language>zh-Hans</language>
	<sy:updatePeriod>
	hourly	</sy:updatePeriod>
	<sy:updateFrequency>
	1	</sy:updateFrequency>
	<generator>https://wordpress.org/?v=7.0.3</generator>

<image>
	<url>https://www.linuxmi.com/wp-content/uploads/2020/02/cropped-Favicon-32x32.png</url>
	<title>C/C++ - Linux迷</title>
	<link>https://www.linuxmi.com</link>
	<width>32</width>
	<height>32</height>
</image> 
	<item>
		<title>Linux 内核中使用或依赖的 GCC 扩展代码示例</title>
		<link>https://www.linuxmi.com/linux-use-gcc.html?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=linux-use-gcc</link>
					<comments>https://www.linuxmi.com/linux-use-gcc.html#respond</comments>
		
		<dc:creator><![CDATA[linuxmi]]></dc:creator>
		<pubDate>Sat, 18 Nov 2023 00:44:12 +0000</pubDate>
				<category><![CDATA[C/C++]]></category>
		<category><![CDATA[GCC]]></category>
		<guid isPermaLink="false">https://www.linuxmi.com/?p=23223</guid>

					<description><![CDATA[<p>Linux内核因其高效性和灵活性而受到广泛赞誉，而在其基础中广泛利用了GNU编译器集合（GCC）的许 &#8230;</p>
<p>The post <a href="https://www.linuxmi.com/linux-use-gcc.html">Linux 内核中使用或依赖的 GCC 扩展代码示例</a> first appeared on <a href="https://www.linuxmi.com">Linux迷</a>.</p>]]></description>
										<content:encoded><![CDATA[<p>Linux内核因其高效性和灵活性而受到广泛赞誉，而在其基础中广泛利用了GNU编译器集合（GCC）的许多扩展功能。这些扩展在优化内核性能和确保在不同平台上的兼容性方面发挥着重要作用。在这里，我们将介绍一些主要的GCC扩展，附带代码示例，并解释它们的使用方法和优势。</p>
<p>GNU Compiler Collection（GCC）是由GNU项目开发的一套程序语言编译器集合。GCC由自由软件基金（FSF）发布，并在GNU通用公共许可证（GPL）下提供。</p>
<p>最初是为了C语言而启动的编译器，但目前支持多种编程语言，包括C++、Objective-C、Fortran、Ada、Go、D等。GCC提供了先进的优化功能，可在多个平台上提供可移植性，并使终端用户能够在许多平台上编译代码。</p>
<p>GCC具有以下特点：</p>
<ol>
<li><strong>可移植性:</strong> GCC可以在各种类型的处理器和操作系统上运行，使开发人员能够在不同的架构上使用相同的代码基础。</li>
<li><strong>优化:</strong> GCC提供广泛的优化选项，可用于最大化性能。</li>
<li><strong>语言支持:</strong> 除了C/C++之外，由于支持许多其他语言，因此可以满足各种项目的需求。</li>
<li><strong>调试和错误报告:</strong> GCC通过错误消息和警告指出代码问题，使调试变得容易。</li>
<li><strong>可扩展性:</strong> GCC支持语言和体系结构特定的扩展，可以访问非标准化语言功能和体系结构特定的指令。</li>
<li><strong>自由软件:</strong> 由于在GPL下发布，可以自由使用、修改和重新分发。</li>
</ol>
<p>GCC作为一个标准的编译器被广泛应用于许多开源项目，包括编译Linux内核，其稳健性和可靠性使其成为行业标准。</p>
<h2><strong>属性（Attributes）</strong></h2>
<p>示例：打包的结构体</p>
<pre class="pure-highlightjs"><code class="null">struct __attribute__((packed)) tcp_header {
    uint16_t source_port;
    uint16_t dest_port;
    uint32_t sequence;
    uint32_t ack_sequence;
    uint16_t flags;
    uint16_t window_size;
    uint16_t checksum;
    uint16_t urgent_pointer;
};</code></pre>
<p>解释：</p>
<p>在这里，我们对表示TCP头的结构体应用了<code>__attribute__((packed))</code>属性。该属性防止编译器在结构体成员之间插入填充，从而可以精确地控制内存上的布局，以适应网络通信的需要。</p>
<p>其他属性：</p>
<ul>
<li><code>__attribute__((packed))</code>: 在结构体成员之间紧密地打包，避免插入填充。</li>
<li><code>__attribute__((aligned(x)))</code>: 将变量或结构体对齐到指定的边界。</li>
<li><code>__attribute__((noreturn))</code>: 通知编译器函数不会返回。</li>
<li><code>__attribute__((section("...")))</code>: 将变量或函数放置在特定的节(section)中。</li>
</ul>
<h2><strong>内建函数（Built-in Functions）：</strong></h2>
<p>例如：计算最高位。</p>
<pre class="pure-highlightjs"><code class="null">unsigned int value = 0xFF00;
int msb = 32 - __builtin_clz(value);</code></pre>
<p>解释：</p>
<p><code>__builtin_clz</code>函数用于计算从值的开头开始的连续零的数量。在这个例子中，它被用于找到变量<code>value</code>的最高位（即最左侧的非零位），常用于位字段操作、资源分配等许多低级操作。它还可用于在位图中搜索空闲槽等场景。</p>
<p>例子：使用GCC内建函数进行内存操作</p>
<pre class="pure-highlightjs"><code class="null">void *my_memcpy(void *dest, const void *src, size_t n) {
    return __builtin_memcpy(dest, src, n);
}</code></pre>
<p>解释：</p>
<p>GCC内建函数<code>__builtin_memcpy</code>可能比标准的<code>memcpy</code>函数更高效，并且在特定的优化情况下可能进行了特殊处理。在内核中，使用这样的内建函数可以加速内存复制操作。</p>
<p>其他内建函数：</p>
<ul>
<li><code>__builtin_popcount</code>: 计算整数中1的位数。</li>
<li><code>__builtin_clz</code>: 计算整数中开头的0的位数（Count Leading Zeros）。</li>
<li><code>__builtin_expect</code>: 为了优化分支预测，向编译器提示某个条件最有可能是真的。</li>
</ul>
<h2><strong>编译时断言 </strong></h2>
<p>例子：编译时断言。</p>
<pre class="pure-highlightjs"><code class="null">BUILD_BUG_ON(sizeof(mystruct) != expected_size);</code></pre>
<p>解释：</p>
<p><code>BUILD_BUG_ON</code> 是一个宏，在特定条件为真的情况下生成编译错误，这是在编译时进行的。借助于GCC的功能，内核开发者使用这个宏来确保数据结构具有期望的大小。</p>
<h2><code>typeof</code> 操作符</h2>
<p>例子：变量类型的自动推断</p>
<pre class="pure-highlightjs"><code class="null">#define min(x, y) ({             \
    typeof(x) _min1 = (x);       \
    typeof(y) _min2 = (y);       \
    (void) (&amp;_min1 == &amp;_min2);   \
    _min1 &lt; _min2 ? _min1 : _min2; \
})</code></pre>
<p>解释：</p>
<p><code>typeof</code> 是一种由GCC引入的自动获取变量类型的扩展。在上述的 <code>min</code> 宏中，使用 <code>typeof</code> 推断了参数 <code>x</code> 和 <code>y</code> 的类型，然后基于这些类型进行了比较。这种技巧允许在保持类型安全性的同时进行通用操作。</p>
<h2><strong>寄存器变量</strong></h2>
<p>例子：将变量分配到特定寄存器</p>
<pre class="pure-highlightjs"><code class="null">register unsigned long sp asm ("sp");</code></pre>
<p>解释：</p>
<p>使用这个语法，内核开发人员可以直接将变量分配到特定的CPU寄存器。这在提高关键函数性能时可能会被使用，但需要非常谨慎。</p>
<h2><strong>用于多线程的扩展</strong></h2>
<p>例子：使用线程本地存储</p>
<pre class="pure-highlightjs"><code class="null">__thread int my_thread_variable;</code></pre>
<p>解释：</p>
<p><code>__thread</code> 存储类说明符表示变量位于线程本地存储（TLS）中。这确保每个线程都有其自己的变量实例，对于需要每个内核线程都有其独特上下文的情况非常有用。</p>
<h2><strong>语句表达式（Statement Expressions） </strong></h2>
<p>例子：在宏内进行复杂计算</p>
<pre class="pure-highlightjs"><code class="null">#define MAX(a, b) ({ \
    typeof(a) _a = (a); \
    typeof(b) _b = (b); \
    _a &gt; _b ? _a : _b; \
})</code></pre>
<p>解释：</p>
<p>通过使用这个语句表达式，可以在 <code>MAX</code> 宏内评估 <code>a</code> 和 <code>b</code> 的最大值，并返回结果。这种技巧在需要在宏内执行多个步骤并返回一个值的情况下非常有用。</p>
<p><strong>更详细的解释：</strong></p>
<p>如果不使用语句表达式，宏可能在某些情况下无法按预期工作。在不使用语句表达式的传统宏的情况下，如果参数包含具有副作用的表达式或者被多次评估，可能会导致问题。</p>
<p>例如，考虑以下简单的 <code>MAX</code> 宏：</p>
<pre class="pure-highlightjs"><code class="null">#define MAX(a, b) ((a) &gt; (b) ? (a) : (b))</code></pre>
<p>这个宏在通常情况下可以正常工作，但如果包含有副作用的表达式，可能会导致意外的行为，例如，如果 <code>a</code> 或 <code>b</code> 中包含增量运算符（++）。</p>
<pre class="pure-highlightjs"><code class="null">int x = 5;
int y = 10;
int z = MAX(x++, y++);</code></pre>
<p>在上述代码中，由于 <code>MAX</code> 宏两次评估 <code>x</code> 和 <code>y</code>，可能导致与期望的结果不同的行为，即 <code>x</code> 和 <code>y</code> 的值以意外的方式更改。</p>
<p>相比之下，使用语句表达式的 <code>MAX</code> 宏如下：</p>
<pre class="pure-highlightjs"><code class="null">#define MAX(a, b) ({ \
    typeof(a) _a = (a); \
    typeof(b) _b = (b); \
    _a &gt; _b ? _a : _b; \
})</code></pre>
<p>在这里，<code>a</code> 和 <code>b</code> 仅被评估一次，其结果分别存储在 <code>_a</code> 和 <code>_b</code> 中。这样，即使参数包含带有副作用的表达式，也只会评估一次，从而避免了意外的副作用问题。</p>
<p>例如，考虑以下的宏：</p>
<pre class="pure-highlightjs"><code class="null">#define MAX(a, b) ((a) &gt; (b) ? (a) : (b))</code></pre>
<p>这个宏如果传递包含 ++ 的表达式，例如 <code>MAX(x++, y++)</code>，则可能被预处理器展开为以下形式：</p>
<pre class="pure-highlightjs"><code class="null">((x++) &gt; (y++) ? (x++) : (y++))</code></pre>
<p>在展开的结果中，<code>x</code> 和 <code>y</code> 在宏内部被多次引用。在评估条件表达式 <code>(x++) &gt; (y++)</code> 时，<code>x</code> 和 <code>y</code> 各自增加一次。然后，根据条件表达式的结果，<code>x</code> 或 <code>y</code> 将再次增加一次。因此，<code>x</code> 或 <code>y</code> 中的一个可能会意外地增加两次。</p>
<p>这种多次评估的问题，特别是涉及到具有副作用的操作（例如增量或减量）时，容易导致错误。因此，在将带有副作用的表达式作为宏的参数使用时，需要格外小心。通过使用语句表达式，每个参数只被评估一次并存储在临时变量中，可以防止这类问题的发生。</p>
<h2><strong>内联汇编语法（Inline Assembly） </strong></h2>
<p>例子：使用特定的汇编指令</p>
<pre class="pure-highlightjs"><code class="null">void disable_interrupts() {
    __asm__ __volatile__("cli": : :"memory");
}</code></pre>
<div class="flex-1 overflow-hidden">
<div class="react-scroll-to-bottom--css-iytws-79elbk h-full">
<div class="react-scroll-to-bottom--css-iytws-1n7m0yu">
<div class="flex flex-col text-sm gizmo:pb-9 dark:bg-gray-800 gizmo:dark:bg-transparent">
<div class="group w-full text-token-text-primary border-b border-black/10 gizmo:border-0 dark:border-gray-900/50 gizmo:dark:border-0 bg-gray-50 gizmo:bg-transparent dark:bg-[#444654] gizmo:dark:bg-transparent" data-testid="conversation-turn-74">
<div class="p-4 gizmo:py-2 justify-center text-base md:gap-6 md:py-6 m-auto">
<div class="flex flex-1 gap-4 text-base mx-auto md:gap-6 gizmo:gap-3 gizmo:md:px-5 gizmo:lg:px-1 gizmo:xl:px-5 md:max-w-2xl lg:max-w-[38rem] gizmo:md:max-w-3xl gizmo:lg:max-w-[40rem] gizmo:xl:max-w-[48rem] xl:max-w-3xl }">
<div class="relative flex w-[calc(100%-50px)] flex-col gizmo:w-full lg:w-[calc(100%-115px)] agent-turn">
<div class="flex-col gap-1 md:gap-3">
<div class="flex flex-grow flex-col max-w-full gap-3 gizmo:gap-0">
<div class="min-h-[20px] text-message peer flex flex-col items-start gap-3 whitespace-pre-wrap break-words peer-[.text-message]:mt-5 overflow-x-auto" data-message-author-role="assistant" data-message-id="d3428496-9132-4a5f-b457-c3bebd287f02">
<div class="markdown prose w-full break-words dark:prose-invert light">
<p>解释：</p>
<p>这个内联汇编命令 <code>cli</code> 会禁用 CPU 的中断。内核使用这样的低级别指令直接控制硬件，确保在关键操作期间不会发生中断。</p>
<h2><strong>指定初始化（Designated Initializers）</strong></h2>
<p>例子：结构体的初始化</p>
<pre class="pure-highlightjs"><code class="null">struct point {
    int x;
    int y;
};

struct point p = {
    .x = 10,
    .y = 20
};</code></pre>
<p>解释：</p>
<p>指定初始化器允许直接为结构体的特定成员分配值，使初始化更具可读性且减少错误。这种方法在只想初始化结构体的部分成员或者需要明确初始化顺序的情况下特别有用。</p>
<p>GCC 的扩展广泛用于 Linux 内核代码库的各个部分，通过有效地利用这些扩展，Linux 在各种硬件上展现出卓越性能。通过使用这些扩展，开发者能够更细粒度地控制内核的行为，实现高效的系统调用、硬件操作和数据处理。</p>
<p>为了实现 Linux 内核的高级功能和性能，它充分利用了 GCC（GNU Compiler Collection）的多样化扩展。这些扩展对于提升内核的性能、稳定性以及在不同平台上的兼容性至关重要。</p>
<p><strong>相关：</strong></p>
<ul>
<li>Linux 下进行 C 或 C++ 编程时重要的 GCC 标志 <a href="https://www.linuxmi.com/gcc-flags.html">https://www.linuxmi.com/gcc-flags.html</a></li>
<li>如何在 Ubuntu 20.04/22.04 上安装 GCC 编译器 <a href="https://www.linuxmi.com/ubuntu-20-04-22-04-gcc.html">https://www.linuxmi.com/ubuntu-20-04-22-04-gcc.html</a></li>
</ul>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div><p>The post <a href="https://www.linuxmi.com/linux-use-gcc.html">Linux 内核中使用或依赖的 GCC 扩展代码示例</a> first appeared on <a href="https://www.linuxmi.com">Linux迷</a>.</p>]]></content:encoded>
					
					<wfw:commentRss>https://www.linuxmi.com/linux-use-gcc.html/feed</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>C 编程中指针的基本指南</title>
		<link>https://www.linuxmi.com/c-programming-pointers.html?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=c-programming-pointers</link>
					<comments>https://www.linuxmi.com/c-programming-pointers.html#respond</comments>
		
		<dc:creator><![CDATA[linuxmi]]></dc:creator>
		<pubDate>Tue, 03 Oct 2023 00:51:28 +0000</pubDate>
				<category><![CDATA[C/C++]]></category>
		<category><![CDATA[C 编程]]></category>
		<guid isPermaLink="false">https://www.linuxmi.com/?p=22976</guid>

					<description><![CDATA[<p>指针对许多 C 编程至关重要，但它们可能很难理解。本文通过实际示例来复习它们的语法以及它们的工作原理 &#8230;</p>
<p>The post <a href="https://www.linuxmi.com/c-programming-pointers.html">C 编程中指针的基本指南</a> first appeared on <a href="https://www.linuxmi.com">Linux迷</a>.</p>]]></description>
										<content:encoded><![CDATA[<p><strong><em>指针对许多 C 编程至关重要，但它们可能很难理解。本文通过实际示例来复习它们的语法以及它们的工作原理。</em></strong></p>
<p>指针是 C 编程中不可或缺的一部分，您需要深入理解它们才能有效使用这种编程语言。它们有助于高效的内存管理、通过引用传递数据、处理数组和字符串等等。然而，为了避免错误，需要谨慎使用它们。</p>
<p>探讨C指针的详细内容，从理解内存和地址到精通指针算术。</p>
<h2><strong>内存和地址</strong></h2>
<p>内存——通常用作RAM（随机访问存储器）的缩写——是计算机中用于存储程序运行所需数据和指令的空间。它充当程序的工作区。内存的最小单位通常是一个字节，相当于八位。</p>
<p>每个内存位置都有唯一的地址，并且可以根据计算机的不同存储不同数量的数据。当您在C中声明一个变量时，实际上是在为其分配一个内存位置来存储其数据。可以将其视为一栋房子，每栋房子都有一个唯一的地址，您可以使用该地址来找到它。</p>
<p>想象一下您计算机内存是一系列存储单元，每个存储单元包含一个字节的数据。假设在C程序中有两个变量x和y：</p>
<p>int x = 5;<br />
int y = 10;</p>
<p>在内存中，它可能看起来像这样：</p>
<table style="height: 208px;" border="1" width="165" cellspacing="1" cellpadding="1">
<thead>
<tr>
<th scope="col">Address</th>
<th scope="col">Data</th>
</tr>
</thead>
<tbody>
<tr>
<td>1000</td>
<td>5</td>
</tr>
<tr>
<td>1004</td>
<td>10</td>
</tr>
</tbody>
</table>
<p>在这里，单独的内存位置存储了这些变量。变量x表示的数据位于内存地址1000，而y的数据占据了内存地址1004。</p>
<p>当您使用指针时，了解内存和地址是至关重要的，因为它们是存储内存地址的变量。它们允许您访问和操作存储在特定内存位置的数据。</p>
<h2><strong>在C中声明和初始化指针</strong></h2>
<p>在C中使用指针修改数据之前，您需要声明和初始化它。</p>
<h3><strong>声明</strong></h3>
<p>要声明一个指针，您需要指定它指向的数据类型，然后是一个星号(*)，然后是指针的名称。例如：</p>
<pre class="pure-highlightjs"><code class="null">int *ptr;</code></pre>
<p>在这里，int *ptr 声明了一个名为ptr的指针，它可以存储整数的内存地址。</p>
<h3><strong>初始化</strong></h3>
<p>声明后，您应该用它将要指向的内存地址进行初始化。可以像这样进行初始化：</p>
<pre class="pure-highlightjs"><code class="null">int x = 5;
int *ptr = &amp;x;</code></pre>
<p>在这个声明中，&amp; 运算符获取了x变量的地址。这段代码实际上表示&#8221;ptr是一个变量，它存储整数值的内存位置，而该位置就是x当前引用的位置&#8221;。</p>
<p>现在，ptr保存了整数变量x的地址。例如：</p>
<table border="1" cellspacing="1" cellpadding="1">
<thead>
<tr>
<th scope="col">Variable</th>
<th scope="col">Address</th>
<th scope="col">Value</th>
</tr>
</thead>
<tbody>
<tr>
<td>x</td>
<td>1000</td>
<td>5</td>
</tr>
<tr>
<td>ptr</td>
<td>&#8212;-</td>
<td>1000</td>
</tr>
</tbody>
</table>
<h2><strong>解引用指针</strong></h2>
<p>在C中，解引用指针意味着访问由指针指向的内存地址中存储的值。</p>
<p>假设您有一个指针 int *ptr，它指向一个整数变量，并且该变量的值为10。要通过指针访问该值，您可以使用星号(*)运算符：</p>
<pre class="pure-highlightjs"><code class="null">int x = 10;

int *ptr = &amp;x; // ptr指向x的地址

int value = *ptr; // 解引用ptr以获取值</code></pre>
<p>这个例子使用了ptr变量来检索它指向的内存地址中的值。因此，value现在保存了值10，这是x的内容。</p>
<h2><strong>指针算术</strong></h2>
<p>指针算术是C中的一个强大特性，特别适用于处理数组和字符串（它们是字符数组）等工作。它允许您对指针执行算术操作，以在内存中移动。</p>
<p>下面是一个示例，展示了如何使用它。</p>
<p>首先声明一个整数数组：</p>
<pre class="pure-highlightjs"><code class="null">int numbers[] = {10, 20, 30};</code></pre>
<p>声明一个指向整数的指针，并将numbers数组的内存位置分配给它：</p>
<pre class="pure-highlightjs"><code class="null">int *ptr = numbers;</code></pre>
<p>在这里，您不需要使用“&amp;”运算符，因为numbers已经是一个隐式的指针类型。</p>
<p>现在，ptr变量指向数组的第一个元素：</p>
<pre class="pure-highlightjs"><code class="null">printf("%d\n", *ptr); // 10</code></pre>
<p>您可以通过将其增加2来将指针移到数组的第三个元素：</p>
<pre class="pure-highlightjs"><code class="null">ptr += 2;
printf("%d\n", *ptr); // 30</code></pre>
<p>您可以通过减去它来将指针向后移动：</p>
<pre class="pure-highlightjs"><code class="null">ptr--;
printf("%d\n", *ptr); ;// 20</code></pre>
<p>指针算术在导航数组和处理动态内存分配时特别有用。</p>
<h2><strong>C中的指针和函数</strong></h2>
<p>如果您了解C编程中函数的工作原理，那么您就可以很好地使用函数指针。以下是您可以使用它们的一些方法。</p>
<h3><strong>函数指针</strong></h3>
<p>您可以声明和使用函数指针来动态使用函数，就像使用任何其他值一样。这对于回调和动态函数执行特别有用。</p>
<pre class="pure-highlightjs"><code class="null">int (*operation)(int, int); // 声明一个函数指针
operation = add; // 指向add函数的指针
int result = operation(5, 3); // 通过指针调用函数</code></pre>
<p>这段代码声明了一个名为operation的函数指针，它可以指向一个接受两个整数并返回一个整数的函数。它将add函数（的指针）分配给了operation。然后，它使用operation变量间接调用add(5, 3)。</p>
<h3><strong>通过引用传递</strong></h3>
<p>指针允许您通过引用将参数传递给函数，使您能够在函数内修改原始数据。这对于需要更改变量值的函数而言非常重要，因为它们需要在其范围之外更改变量的值。</p>
<pre class="pure-highlightjs"><code class="null">void modifyValue(int *x) {
*x = 42; // 修改调用代码中x的值
}</code></pre>
<p>modifyValue函数改变了调用代码提供给它的任何参数的值，将其设置为42。</p>
<h3><strong>动态内存分配</strong></h3>
<p>函数可以返回指向动态分配内存的指针。当您需要创建和返回无界数据结构（如数组或链表）时，这是常见的情况。您需要对栈内存和堆内存有很好的了解才能使用它。</p>
<pre class="pure-highlightjs"><code class="null">int *createArray(int size) {
int *arr = (int *)malloc(size * sizeof(int));
return arr;
}</code></pre>
<p>这段代码定义了一个名为createArray的函数，该函数以一个整数size作为输入。在函数内部，它使用malloc动态分配了指定大小的整数数组的内存。在初始化数组后，它返回对这个新创建的数组的指针。</p>
<h3><strong>常见用途</strong></h3>
<p>指针在C中是非常重要的，它们是区分C和其他编程语言（如Python）的要素。以下是一些常见用途：</p>
<ul>
<li>动态内存分配</li>
<li>数组操作</li>
<li>通过引用传递</li>
<li>数据结构</li>
<li>资源管理</li>
</ul>
<p>了解指针的这些常见用途可以增强您的C编程技能。练习其中一些可以提高您对指针的理解。</p>
<h2><strong>在C编程中练习使用指针</strong></h2>
<p>掌握C编程中的指针是一项有价值的技能，它使您能够高效地管理内存、操作数据并执行高级操作。练习和熟练使用指针将极大地提高您创建强大且资源高效的C程序的能力。</p><p>The post <a href="https://www.linuxmi.com/c-programming-pointers.html">C 编程中指针的基本指南</a> first appeared on <a href="https://www.linuxmi.com">Linux迷</a>.</p>]]></content:encoded>
					
					<wfw:commentRss>https://www.linuxmi.com/c-programming-pointers.html/feed</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>C 和 C++ 之间的 10 个主要区别</title>
		<link>https://www.linuxmi.com/c-c-plus-plus.html?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=c-c-plus-plus</link>
					<comments>https://www.linuxmi.com/c-c-plus-plus.html#respond</comments>
		
		<dc:creator><![CDATA[linuxmi]]></dc:creator>
		<pubDate>Sun, 03 Sep 2023 11:38:02 +0000</pubDate>
				<category><![CDATA[C/C++]]></category>
		<category><![CDATA[C++]]></category>
		<guid isPermaLink="false">https://www.linuxmi.com/?p=22697</guid>

					<description><![CDATA[<p>C 和 C++ 是两种因其低级别强大而广泛认可的编程语言。尽管这两种语言听起来很相似，在后者上只多了 &#8230;</p>
<p>The post <a href="https://www.linuxmi.com/c-c-plus-plus.html">C 和 C++ 之间的 10 个主要区别</a> first appeared on <a href="https://www.linuxmi.com">Linux迷</a>.</p>]]></description>
										<content:encoded><![CDATA[<p>C 和 C++ 是两种因其低级别强大而广泛认可的编程语言。尽管这两种语言听起来很相似，在后者上只多了一个 &#8220;++&#8221;，但它们的特点和用法却有很大的不同。</p>
<p>C 是一种过程式编程语言，具有静态系统，而 C++ 是 C 的扩展版本，支持面向对象编程。因此，学习C是相关的，并有助于改善 C++ 编程。在热门编程语言中，C 和 C++ 是学习和技能发展的两种最受欢迎的语言之一。</p>
<p><img fetchpriority="high" decoding="async" class="alignnone size-full wp-image-14734" src="https://www.linuxmi.com/wp-content/uploads/2022/04/0.png" alt="" width="1166" height="856" /></p>
<p>相关：在Ubuntu 20.04/22.04 中安装配置 IDE 集成开发环境 Code::Blocks 20.03  <a href="https://www.linuxmi.com/ubuntu-codeblocks-20-03.html">https://www.linuxmi.com/ubuntu-codeblocks-20-03.html</a></p>
<h2><strong>C 编程语言：</strong></h2>
<p>C 是一种重要的通用计算机编程语言，支持结构化编程、典型的机器指令、递归和静态系统下的变量。C 编程语言提供低级别访问，可以处理地址、位和字节，并能对开发过程进行迅速控制。</p>
<p>Dennis M. Ritchie于1972年开发了C编程语言，用于UNIX操作系统。最初，程序员们使用C语言设计系统，主要关注操作系统。渐渐地，他们开始将其应用于开发编译器、汇编器、文本编辑器、数据库等。</p>
<p>在学习C编程之前，你应该了解相关的术语，如参数、函数、变量、类、内置类型、循环、数组等。这有助于进行一些代码练习。程序员们将C代码写在扩展名为&#8221;.c&#8221;或&#8221;.h&#8221;的文本文件中。</p>
<h2><strong>C++编程语言：</strong></h2>
<p>C++是C语言的增强版本，由Bjarne Stroustrup于1986年开发。它包含了C的所有部分，并添加了面向对象编程等功能。游戏开发人员经常使用C++，但它在软件基础设施和桌面应用程序中也有广泛的用途。</p>
<p>C++可以处理硬件任务，并在几乎任何环境中运行代码。因此，C++是创建动态和灵活的软件的首选之一，可以管理系统资源和关键任务。</p>
<p>与其他编程语言一样，C++支持类、方法、对象、多态、继承等特性。它通常使用文件扩展名&#8221;.cpp&#8221;和&#8221;.cxx&#8221;，你还可能看到像&#8221;.c++&#8221;、&#8221;.h&#8221;、&#8221;.hpp&#8221;、&#8221;.hxx&#8221;、&#8221;.h++&#8221;等扩展名用于头文件。</p>
<p>C++的最新版本是C++23，于2021年6月18日发布。</p>
<p><strong>相关：</strong></p>
<ul>
<li>为什么要学 C++？ <a href="https://www.linuxmi.com/c-plus-plus-learn.html">https://www.linuxmi.com/c-plus-plus-learn.html</a></li>
<li>认识 4 个用 C++ 制作的终端游戏和动画 <a href="https://www.linuxmi.com/c-terminal-games.html">https://www.linuxmi.com/c-terminal-games.html</a></li>
</ul>
<h2><strong>C 与 C++：10个核心区别</strong></h2>
<p>C 和 C++ 都是通用的过程式语言。然而，它们之间的核心区别在于 C 编程语言不支持类和对象，而 C++ 体现了面向对象的编程范式。让我们找出 C 和 C++ 之间的核心区别。</p>
<h3><strong>过程</strong></h3>
<p>C 编程语言不支持面向对象编程。因此，它不允许多态性、继承等。作为一种面向对象的语言，C++ 支持多态性和继承。</p>
<h3><strong>安全性</strong></h3>
<p>由于 C 语言不允许封装，数据变得可访问，其他实体可以破坏它。然而，C++ 支持封装，可以保护数据结构并根据需要使用它。</p>
<h3><strong>方法</strong></h3>
<p>C 编程语言鼓励自顶向下的方法，首先定义一个通用问题，然后将其分解为较小的任务。另一方面，C++ 鼓励自底向上的方法。这涉及首先识别和定义类，然后使用它们执行最初的任务。</p>
<h3><strong>输入/输出函数</strong></h3>
<p>在 C 中，I/O 操作主要通过 C 标准库的标准 I/O 函数进行处理，如 printf() 和 scanf()。这些函数提供基本的格式化和读取功能，但缺少 C++ 中的一些高级功能。</p>
<p>另一方面，C++ 通过使用 iostream 库中的对象扩展了 I/O 功能，这些对象称为标准 I/O 流。cout 流允许进行简单而灵活的输出操作，而 cin 流提供了增强的输入功能。C++ 流支持运算符重载，可方便地输出复杂数据类型并启用自定义格式选项。</p>
<h3><strong>重载和覆盖</strong></h3>
<p>方法覆盖允许子类重新定义从其祖先继承的函数。重载允许同一个函数有多个版本，每个版本具有唯一的参数。C 不支持这两者，但 C++ 支持。</p>
<h3><strong>内存分配</strong></h3>
<p>C编程依赖于两个关键函数——calloc()和malloc()——用于内存分配。相应的free()函数用于内存释放。C++使用new运算符进行动态内存分配，使用delete运算符进行释放。</p>
<h3><strong>编译</strong></h3>
<p>C和C++的软件开发始于编写源代码。C文件的源代码具有.c扩展名，而C++使用扩展名如.cpp或.cxx。这些源代码文件包含程序的指令和逻辑。</p>
<p>下一步是预处理，预处理器处理#include指令并执行宏处理。此步骤确保源代码经过解析依赖关系和宏处理准备好进行编译。预处理阶段对C和C++都是相同的。</p>
<p>在编译阶段，源代码被传递给相应的编译器，例如C使用gcc，C++使用g++。编译器检查语法和语义，并报告错误。这一步对C和C++都适用。</p>
<p>主要区别在于C++中的额外功能，尤其是面向对象编程（OOP）概念。C++编译器处理所有类似C的语法，还包括封装、继承和多态性等OOP特性。</p>
<p>连接，在编译之后，通过组合对象文件、库文件和依赖项来创建可执行文件。它解决了外部引用，确保独立执行。连接对C和C++都是相同的。</p>
<h3><strong>平台</strong></h3>
<p>C和C++都有广泛的平台支持，可以在Windows、macOS、Linux以及不同的UNIX衍生系统等各种操作系统上运行。这种平台多样性允许开发人员在多个平台上无缝编译和运行C和C++代码。</p>
<p>许多集成开发环境（IDE）都支持C和C++。你可以使用一些流行的IDE，如Visual Studio、Code::Blocks、Dev-C++、Eclipse、Xcode和Qt Creator。这些IDE简化了代码编写、调试、编译和其他开发过程，提供了便捷高效的软件开发环境。</p>
<p>总之，C和C++具有广泛的平台支持，提供了多种IDE选择。这两种语言在不同平台和IDE上运行的能力帮助你轻松构建多功能应用程序。</p>
<h3><strong>变量</strong></h3>
<p>通常，C编程语言使用两种类型的值：字面值和变量。C使用四种基本的变量类型：int、float、char和double。C++的主要变量类型包括bool、void和wchar_t。</p>
<h3><strong>特点</strong></h3>
<p>C编程语言是一种过程式、快速和高效的语言，具有模块化和丰富的内置运算符。与C不同，C++是一种过程式语言，具有OOP。此外，它是机器无关的、简单的和区分大小写的。</p>
<p>C编程语言是一种中级语言，而C++是一种高级语言。</p>
<table style="height: 350px;" border="1" width="697" cellspacing="1" cellpadding="1">
<thead>
<tr>
<th scope="col">C语言</th>
<th scope="col">C++ 编程语言</th>
</tr>
</thead>
<tbody>
<tr>
<td>无法运行 C++ 代码。</td>
<td>可以运行几乎所有的C代码。</td>
</tr>
<tr>
<td>不支持引用变量。</td>
<td>支持引用变量。</td>
</tr>
<tr>
<td>该语言有 32 个关键字。</td>
<td>95个关键词。他们中的一些人可能会被分到几个小组中。</td>
</tr>
<tr>
<td>通过&lt;stdio.h&gt;头文件输入和输出。</td>
<td>使用 &lt;iostream.h&gt; 头文件。</td>
</tr>
<tr>
<td>不允许在结构中使用函数。</td>
<td>允许结构中的函数。</td>
</tr>
<tr>
<td>分为程序和模块。</td>
<td>分为类和函数。</td>
</tr>
</tbody>
</table>
<h2><strong>C编程语言示例</strong></h2>
<p>这个 C 程序使用了标准输入输出库 stdio.h。这个库提供了 printf 函数，程序使用它来输出消息 &#8220;Hello, Linux迷 www.linuxmi.com&#8221;，后面跟着一个换行字符 \n。</p>
<pre class="pure-highlightjs"><code class="null">#include &lt;stdio.h&gt;
// Linux迷 www.linuxmi.com

int main () {
  printf("Hello, Linux迷 www.linuxmi.com\n");
  return 0;
}</code></pre>
<p><img decoding="async" class="alignnone size-full wp-image-22702" src="https://www.linuxmi.com/wp-content/uploads/2023/09/c.png" alt="" width="1054" height="721" /></p>
<h2><strong>C++ 编程语言示例</strong></h2>
<p>这个 C++ 程序使用了输入输出流库iostream。这个库允许程序使用流运算符，如 <code class="null">std::cout &lt;&lt;</code> 对象代表标准输出，通常情况下将是控制台。</p>
<p>包含 <code class="null">std::endl</code> 会导致消息后面添加一个换行字符。这比C 的  &#8220;\n&#8221;  字符是一个更高级的抽象，因此这个程序将在使用不同字符表示换行的系统上运行。</p>
<pre class="pure-highlightjs"><code class="null">#include &lt;iostream&gt;
// Linux迷 www.linuxmi.com

int main () {
  std::cout &lt;&lt; "Hello, Linux迷 www.linuxmi.com" &lt;&lt; std::endl;
  return 0;
}</code></pre>
<p><img decoding="async" class="alignnone size-medium wp-image-22703" src="https://www.linuxmi.com/wp-content/uploads/2023/09/cpp.png" alt="" width="1054" height="721" /></p>
<h2><strong>C 和 C++ 在可预见的未来仍然具有潜力</strong></h2>
<p>许多程序员和技术爱好者曾预期 C 和 C++ 将失去重要性。然而，由于它们的开发特性和广泛的应用领域，C 和 C++ 仍然是令人兴奋的职业道路。</p>
<p>其他编程语言不断涌现，但通常满足特定需求，如 Web 开发或游戏编程。C 和 C++ 是更通用的语言，学习它们将对你的职业非常有价值，即使只是作为学习其他语言的基础。</p><p>The post <a href="https://www.linuxmi.com/c-c-plus-plus.html">C 和 C++ 之间的 10 个主要区别</a> first appeared on <a href="https://www.linuxmi.com">Linux迷</a>.</p>]]></content:encoded>
					
					<wfw:commentRss>https://www.linuxmi.com/c-c-plus-plus.html/feed</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>在 C++ 中比较数字时要小心</title>
		<link>https://www.linuxmi.com/c-plus-plus-compare-numbers.html?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=c-plus-plus-compare-numbers</link>
					<comments>https://www.linuxmi.com/c-plus-plus-compare-numbers.html#respond</comments>
		
		<dc:creator><![CDATA[linuxmi]]></dc:creator>
		<pubDate>Sun, 23 Apr 2023 06:04:36 +0000</pubDate>
				<category><![CDATA[C/C++]]></category>
		<category><![CDATA[C++]]></category>
		<guid isPermaLink="false">https://www.linuxmi.com/?p=21088</guid>

					<description><![CDATA[<p>C++ 是一种广泛使用的编程语言，但也是编程错误最常见的语言之一。其中许多错误是由于逻辑错误造成的。 &#8230;</p>
<p>The post <a href="https://www.linuxmi.com/c-plus-plus-compare-numbers.html">在 C++ 中比较数字时要小心</a> first appeared on <a href="https://www.linuxmi.com">Linux迷</a>.</p>]]></description>
										<content:encoded><![CDATA[<p>C++ 是一种广泛使用的编程语言，但也是编程错误最常见的语言之一。其中许多错误是由于逻辑错误造成的。特别是，比较操作中的错误可能会影响代码的准确性和可靠性。</p>
<p>C++ 语言中有一种特定的比较错误，许多新开发人员会忽略这种错误。这种错误是由于对操作符在执行多个比较时的工作原理的错误理解而导致的。了解如何避免这个常见错误以及为什么会发生这个错误。</p>
<h2><strong>C++ 中的比较</strong></h2>
<p>C++编程语言提供了许多不同的功能和工具，包括基本的操作，如比较运算符。比较运算符是编程语言中的特殊操作，您可以使用它们将数据与彼此进行比较。开发人员经常使用这些运算符，特别是在创建算法时。</p>
<p>在日常生活中，您可以在许多不同的例子中看到比较运算符。例如，当您在杂货店购物时，您会心里比较价格。如果一种产品的价格比另一种低，您会选择那种产品。</p>
<p>在 if-else 语句中经常会看到比较运算符。比较运算符是检查一个值是否大于、小于或等于另一个值的地方。有一个非常小但重要的细节不应该忽视，即比较表达式的结果返回true或false，这是布尔值。这些值是编程中控制结构的基本组成部分之一。</p>
<p>例如，在C++编程语言中，“==”运算符检查两个值是否相等。如果这两个值相等，结果返回 true，否则结果将是 false。</p>
<pre class="pure-highlightjs"><code class="null">if (a == b)
{
    return true;
} 
else
{
    return false;
}</code></pre>
<h2><strong>比较问题的示例 </strong></h2>
<p>C++ 初学者常犯的一个错误是使用比较运算符。这些运算符允许程序员比较两个值，并根据比较结果执行不同的操作。然而，如果使用这些运算符不正确，可能会导致意想不到的错误。</p>
<p>例如，尽管表达式 3 &lt; 15 &lt; 10 在数学上是不正确的，但是 C++ 将其结果视为 true。您可以通过编写以下简单的测试程序来证明这一点。</p>
<p>首先，创建一个名为 linuxmi.cpp 的文件。使用您喜欢的代码编辑器打开此文件，并添加以下代码：</p>
<pre class="pure-highlightjs"><code class="null">#include &lt;iostream&gt;
int a = 15;

int main()
{
    if (3 &lt; a &lt; 10)
    {
        std::cout &lt;&lt; "foo" &lt;&lt; std::endl;
    }
    else
    {
        std::cout &lt;&lt; "boo" &lt;&lt; std::endl;
    }

    return 0;
}</code></pre>
<p>您可以使用此命令来编译和运行代码：</p>
<pre class="pure-highlightjs"><code class="null">linuxmi@linuxmi:~/www.linuxmi.com$ g++ linuxmi.cpp -o linuxmi</code></pre>
<p><img loading="lazy" decoding="async" class="alignnone size-full wp-image-21250" src="https://www.linuxmi.com/wp-content/uploads/2023/04/cc1.png" alt="" width="1042" height="783" /></p>
<p>现在你有一个名为 linuxmi 的程序。运行程序并检查其输出。</p>
<p>C++ 认为 3 &lt; 15 &lt; 10 是正确的，即使它在数学上是不正确的。那么造成这种结果的原因是什么？</p>
<h2><strong>C++中的比较问题原因</strong></h2>
<p>和大多数编程语言一样，C++ 从左到右读取代码。每个比较运算符都会产生一个布尔值。布尔值不仅代表 true 和 false，还有一个数学等价物。</p>
<p>计算机的工作原理依赖于 0 和 1。对于计算机来说，某件事情的结果只能是 true 或 false。计算机程序通常将数字 1 视为 true，数字 0 视为 false。</p>
<p>再次仔细查看比较问题，并从左到右阅读该语句，你会发现有两个不同的比较。第一个比较是在数字 3 和 15 之间。这是一个 true 值，因为 3 小于 15。</p>
<p>第二个比较是针对该结果和数字 10 之间的比较。由于需要进行数字比较，C++ 会将布尔值 true 静默转换为 1。1 小于 10，因此总的结果是 true。</p>
<p><img loading="lazy" decoding="async" class="alignnone size-full wp-image-21251" src="https://www.linuxmi.com/wp-content/uploads/2023/04/cc.jpeg" alt="" width="1278" height="585" /></p>
<p>总之，虽然这看起来像是一个数学谬误，但对于 C++ 和计算机来说，这种说法是正确的。</p>
<h2><strong>如何解决 C++ 中的比较问题</strong></h2>
<p>C++ 和其他大多数编程语言在逻辑比较方面使用了与传统数学不同的语法。数学表达式 3 &lt; a &lt; 15 的意思是“ 3 小于 a 且 a 小于 15”。然而，正如你所看到的，C++ 对这个表达式的解释是不同的。</p>
<p>要在 C++ 中表示“and”，可以使用“&amp;&amp;”运算符。然后，您可以将布尔表达式链接在一起，并使用像“&amp;&amp;”表示 AND，“||”表示OR和“！”表示 NOT 等运算符构建逻辑。像 Java 这样的语言使用相同的逻辑运算符。</p>
<p>使用正确的逻辑运算符，可以修复前面示例中的错误：</p>
<pre class="pure-highlightjs"><code class="null">#include &lt;iostream&gt;
int a = 15;

int main()
{
    if (3 &lt; a &amp;&amp; a &lt; 10)
    {
	std::cout &lt;&lt; "foo" &lt;&lt; std::endl;
    }
    else
    {
	std::cout &lt;&lt; "boo" &lt;&lt; std::endl;
    }
    
    return 0;
}</code></pre>
<p>现在这段代码将测试 a 值是否大于 3 以及 a 值是否小于 10。编译并运行程序并观察结果。</p>
<p><img loading="lazy" decoding="async" class="alignnone size-full wp-image-21255" src="https://www.linuxmi.com/wp-content/uploads/2023/04/cc2.png" alt="" width="1042" height="783" /></p>
<p>前面的例子输出了“foo”，但现在程序输出了预期的“boo”。比较的左侧（3 &lt; a）的布尔值为true。右侧的值（a &lt; 10）为false。由于true和false始终是false，因此整个表达式的结果为false，因此条件失败，else块运行。</p>
<p style="padding-left: 40px;"><em>提示：你也可以尝试将 AND (&amp;&amp;) 运算符切换为 OR (||) 并观察不同的结果。</em></p>
<h2><strong>在 C++ 中逻辑检查的重要性</strong></h2>
<p>在C++中，逻辑比较涉及使用布尔值和比较运算符。确保使用正确的布尔值和比较运算符来控制程序的运行。因为C++通常不会完全失败，而是执行不同的行为，所以很难发现格式不正确的表达式。</p>
<p>现在您知道编译器如何忽略这个问题，并在从左到右读取每个比较时将其视为布尔值。在使用任何语言时都要注意这个问题，并学会识别其影响，以便提前一步。</p><p>The post <a href="https://www.linuxmi.com/c-plus-plus-compare-numbers.html">在 C++ 中比较数字时要小心</a> first appeared on <a href="https://www.linuxmi.com">Linux迷</a>.</p>]]></content:encoded>
					
					<wfw:commentRss>https://www.linuxmi.com/c-plus-plus-compare-numbers.html/feed</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>C# 专家：有经验的开发者必须掌握的三个高级特性</title>
		<link>https://www.linuxmi.com/c-sharp-prodigy.html?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=c-sharp-prodigy</link>
					<comments>https://www.linuxmi.com/c-sharp-prodigy.html#respond</comments>
		
		<dc:creator><![CDATA[linuxmi]]></dc:creator>
		<pubDate>Sat, 25 Mar 2023 23:39:31 +0000</pubDate>
				<category><![CDATA[C/C++]]></category>
		<category><![CDATA[C++]]></category>
		<guid isPermaLink="false">https://www.linuxmi.com/?p=20863</guid>

					<description><![CDATA[<p>C# 就像约会一样，既令人沮丧又充满回报。在我作为一名 C# 开发人员的经历中，我被高水平的程序员所 &#8230;</p>
<p>The post <a href="https://www.linuxmi.com/c-sharp-prodigy.html">C# 专家：有经验的开发者必须掌握的三个高级特性</a> first appeared on <a href="https://www.linuxmi.com">Linux迷</a>.</p>]]></description>
										<content:encoded><![CDATA[<p>C# 就像约会一样，既令人沮丧又充满回报。在我作为一名 C# 开发人员的经历中，我被高水平的程序员所包围，他们推动我认识到在这个行业中取得成功需要付出多大的努力。</p>
<p>本文将介绍 3 个高级的、必须掌握的 C# 特性，这些特性将让您成为一个编程专家，并将您的面向对象编程和 C# 技能提升到新的高度。</p>
<p><strong>1、LINQ（语言集成查询）</strong>：简单来说，这是一组工具，可以方便地操作可枚举类型（例如 List、Dictionary 等）的数据。这个工具包括基于预设的 predicates/requirements 的方法来修改变量：</p>
<pre class="pure-highlightjs"><code class="null">using System;
using System.Collections.Generic;
using Systems.Linq;

public class LinqMethodExample
{
  public static void Main(string[] args)
  {
    // 创建一个整数列表。
    var listOfNumbers = new List&lt;int&gt; { 10, 5, 20, 15, 30, 25, 33, 66 };
    
    // 执行各种LINQ方法。
    var result = listOfNumbers
      .Where(num =&gt; num % 5== 0)             // 得到可被5整除的数字。
      .Select(num =&gt; (int)Math.Pow(num, 2))  // 将每个数字平方。
      .Skip(1)                               // 跳过第一个元素。
      .Last(num =&gt; num % 2 == 0)             // 得到最后一个偶数。
    
    Console.WriteLine($"{result}");

    // 样例输出：
    // 900
  }
}</code></pre>
<p>还有其他方法，比如：</p>
<ul>
<li>OrderBy() -&gt; 根据谓词按升序对序列进行排序。</li>
<li>GroupBy() -&gt; 根据谓词对元素进行分组。</li>
<li>SelectMany() -&gt; 扁平化嵌套列表（即从 List&lt;List&lt;int&gt;&gt; 提取 List&lt;int&gt;）。</li>
<li>Join() -&gt; 根据谓词连接两个序列。</li>
<li>Zip() -&gt; 将两个序列组合成元组的单个序列。</li>
<li>Distinct() -&gt; 从序列中返回不同的元素。</li>
</ul>
<p>这只是一个简单的示例，展示了 LINQ 方法的强大之处。这些方法的可扩展性和应用取决于您作为一名工程师的决策。在 LINQ 库中存在许多更多的方法。</p>
<p><strong>2、异步编程</strong>: 这是一种简单的技术，允许程序在不阻塞主线程的情况下运行多个不同过程的任务。</p>
<p>与等待任务完成不同，异步任务允许其他任务同时继续执行。这有助于提高应用程序的响应性和性能，通常可以使用 async 或 await 关键字来实现。下面的代码以异步方式执行三个任务。也就是说，如果编译此代码，您将看到这三个任务将同时运行，并在不同的时间完成：</p>
<pre class="pure-highlightjs"><code class="null">using System;
using System.Threading.Tasks;

public class AsyncProgramming
{
  public static async Task RandomDelayAsync(int workId)
  {
    // 为此给定任务设置一个随机延迟值（1s-5s）。
    var rand = new Random();
    var delay = rand.Next(1000, 5000);
    await Task.Delay(delay);

    // 打印消息，以便用户知道此任务何时完成。
    Console.WriteLine($"Work {workId} completed in {delay}ms.");
  }

  public static async Task Main()
  {
    // 创建一个由3个任务组成的数组以异步执行。
    var tasks = new Task[3];

    for (var idx=0; idx &lt; tasks.Length; idx++)
    {
      tasks[idx] = RandomDelayAsync(idx);
    }

    // 等待所有任务完成。
    await Task.WhenAll(tasks);
    Console.WriteLine("All tasks completed.");

    // 示例输出:
    // Work 2 completed in 1014ms.
    // Work 0 completed in 2329ms.
    // Work 1 completed in 4392ms.
    // All tasks completed.
  }
}</code></pre>
<p><img loading="lazy" decoding="async" class="alignnone size-full wp-image-20866" src="https://www.linuxmi.com/wp-content/uploads/2023/03/cs2.png" alt="" width="1029" height="362" /></p>
<p><strong>3、委托和事件</strong>: 简单来说，这些工具提供了一种定义回调方法签名的方式，并提供了一种将事件处理程序附加/分离到事件的方式。</p>
<p>换句话说，委托就像你给别人的电话号码，事件就像通话后出现的语音邮件。当事件发生时，它是由电话号码通话引起的，代码会响应并做出相应的操作，比如触发一个语音邮件：</p>
<pre class="pure-highlightjs"><code class="null">using System;

public class DelegateAndEventExample
{
    // 声明表示方法的委托类型
    // 不接受任何参数并返回void。
    public delegate void PhoneNumber();

    public class Class
    {
        // 声明类型为PhoneNumber的事件。
        public event PhoneNumber VoiceMail;

        // 定义引发事件的方法。
        public void CallPhoneNumber()
        {
            Console.WriteLine("Calling the phone number...");
            MyEvent?.Invoke();
        }
    }

    public static void Main()
    {
        var instance = new MyClass();

        // 使用lambda表达式将方法附加到语音邮件事件。
        instance.VoiceMail += () =&gt; Console.WriteLine("Event handler called!");

        // 调用CallPhoneNumber方法，该方法会引发语音邮件事件。
        instance.CallPhoneNumber();

        // 示例输出:
        // Calling the phone number...
        // Event handler called!
    }
}</code></pre>
<p>&nbsp;</p>
<p>总之，掌握 LINQ、异步编程和委托/事件对于经验丰富的 C# 开发人员来说是必不可少的，他们的目标是提高编码技能。通过利用这些强大的功能，开发人员可以编写更高效、简洁和灵活的代码，轻松处理复杂操作。因此，如果您是一个 C# 专家或渴望成为一个专家，一定要将这些功能添加到您的工具箱中，并将您的编码水平提升到更高的水平。</p><p>The post <a href="https://www.linuxmi.com/c-sharp-prodigy.html">C# 专家：有经验的开发者必须掌握的三个高级特性</a> first appeared on <a href="https://www.linuxmi.com">Linux迷</a>.</p>]]></content:encoded>
					
					<wfw:commentRss>https://www.linuxmi.com/c-sharp-prodigy.html/feed</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>释放 C++ 中 Lambda 表达式的强大威力</title>
		<link>https://www.linuxmi.com/c-lambda.html?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=c-lambda</link>
					<comments>https://www.linuxmi.com/c-lambda.html#respond</comments>
		
		<dc:creator><![CDATA[linuxmi]]></dc:creator>
		<pubDate>Thu, 23 Mar 2023 08:30:28 +0000</pubDate>
				<category><![CDATA[C/C++]]></category>
		<category><![CDATA[资讯]]></category>
		<category><![CDATA[C++]]></category>
		<guid isPermaLink="false">https://www.linuxmi.com/?p=20820</guid>

					<description><![CDATA[<p>Lambda 是 C++ 中的匿名函数（即没有函数名的函数），可以在定义和使用时内联。它们提供了一种 &#8230;</p>
<p>The post <a href="https://www.linuxmi.com/c-lambda.html">释放 C++ 中 Lambda 表达式的强大威力</a> first appeared on <a href="https://www.linuxmi.com">Linux迷</a>.</p>]]></description>
										<content:encoded><![CDATA[<p>Lambda 是 C++ 中的匿名函数（即没有函数名的函数），可以在定义和使用时内联。它们提供了一种方便的方式，将小的代码块作为参数传递给其他函数，或者在不需要创建命名函数的情况下定义一个函数。</p>
<p>Lambda 在 C++ 中提供了一种灵活而简洁的方式来编写类似函数的对象，并在现代 C++ 编程中被广泛使用。</p>
<p>Lambda 的定义使用以下语法：</p>
<pre class="pure-highlightjs"><code class="null">[ capture list ] ( argument list ) -&gt; return type { function body }</code></pre>
<ul>
<li>捕获列表（capture list）用于指定 lambda 中可访问的来自外部作用域的变量。变量可以通过值捕获、引用捕获或使用 this 捕获。</li>
<li>参数列表（<code class="null">argument list</code>）指定将递给 lambda 的参数。</li>
<li>返回类型（<code class="null">return type</code>）指定 lambda 将返回的值的类型。如果未指定，则编译器将尝试推断其类型。</li>
<li>函数体（<code class="null">function body</code>）指定 lambda 被调用时将执行的代码。</li>
</ul>
<p>以下是在C++中使用 lambda 的几种不同方式：</p>
<ol>
<li>函数回调（Function Callbacks）</li>
<li>默认捕获（Capturing default）</li>
<li>值捕获（Capturing by value）</li>
<li>引用捕获（Capturing by reference）</li>
<li>可变 lambda（Mutable Lambdas）</li>
</ol>
<p><strong>1、函数回调</strong></p>
<p>函数回调是将一个函数作为参数传递给另一个函数，并在接收函数稍后的时间调用该函数。您可以将 lambda 作为函数参数传递，其中它将在发生某个事件时执行。</p>
<p>示例：</p>
<pre class="pure-highlightjs"><code class="null">#include &lt;iostream&gt;
#include &lt;algorithm&gt;
#include &lt;vector&gt;

int main() {
  std::vector&lt;int&gt; numbers = {1, 2, 3, 4, 5};

  // Lambda 表达式，用于查找两个数字的和
  auto sum = [](int a, int b) { return a + b; };

  int result = std::accumulate(numbers.begin(), numbers.end(), 0, sum);
  std::cout &lt;&lt; "Sum of elements in the vector: " &lt;&lt; result &lt;&lt; std::endl;

  return 0;
}</code></pre>
<p>在这个例子中，sum 变量是一个Lambda表达式，它接受两个参数 a 和 b，并返回它们的总和。std::accumulate 函数接受数字向量、结果的初始值和 sum 函数（Lambda 表达式）。该函数计算向量中所有元素的总和并返回结果，该结果被打印在屏幕上。</p>
<p>另一个例子：</p>
<pre class="pure-highlightjs"><code class="null">#include &lt;iostream&gt;
#include &lt;algorithm&gt;
#include &lt;vector&gt;

int main()
{
    std::vector&lt;int&gt; vec = { 1, 2, 3, 4, 5 };
    int sum = 0;
    std::for_each(vec.begin(), vec.end(), [&amp;sum](int x) { sum += x; });
    std::cout &lt;&lt; "The sum is: " &lt;&lt; sum &lt;&lt; std::endl;
    return 0;
}</code></pre>
<p>在这种情况下，lambda 表达式 [&amp;sum](int x) { sum += x; } 被传递作为要应用于每个元素的函数。lambda 通过引用 &amp; 捕获变量 sum，以便可以在 lambda 主体中进行修改。</p>
<p>两个例子都达到了相同的结果，但第二个例子使用了 std::for_each 算法和 lambda 表达式，这是在 C++ 中更现代、更简洁的技术。</p>
<p><strong>2、默认捕获</strong></p>
<p>当一个 lambda 表达式被声明时没有任何显式的捕获，其默认行为是通过引用捕获周围作用域中的变量。这被称为默认捕获。</p>
<p>例子：</p>
<pre class="pure-highlightjs"><code class="null">#include &lt;iostream&gt;

int main() {
  int x = 42;
  auto f = [ ]() { std::cout &lt;&lt; x &lt;&lt; std::endl; };
  f();
  return 0;
}</code></pre>
<pre class="pure-highlightjs"><code class="null">#include &lt;iostream&gt;

int main()
{
    auto square = [](int x) { return x * x; };
    std::cout &lt;&lt; "The square of 5 is: " &lt;&lt; square(5) &lt;&lt; std::endl;
    return 0;
}</code></pre>
<p>在第二个例子中，定义了一个 lambda 表达式并将其存储在名为 square 的变量中。这个 lambda 表达式接受一个 int 类型的参数 x，并返回 x * x 的值，即参数的平方。</p>
<p>在主函数中，这个 lambda 表达式被用作函数对象。通过传递一个值为 5 的参数来调用它，并使用 cout 流显示结果。</p>
<p><strong>3、按值捕获</strong></p>
<p>这是 lambda 表达式的最简单形式，其中你通过值传递变量给函数。当一个变量被按值捕获时，它的当前值被存储在闭包中，而当周围作用域中的变量发生改变时，它的值不会被更新。这可以通过将变量包含在方括号 [ ] 中来实现。</p>
<p>例子：</p>
<pre class="pure-highlightjs"><code class="null">#include &lt;iostream&gt;

int main() {
  int x = 42;
  auto f = [x]() { std::cout &lt;&lt; x &lt;&lt; std::endl; };
  f();
  return 0;
}</code></pre>
<pre class="pure-highlightjs"><code class="null">#include &lt;iostream&gt;

int main() {
    int x = 42;
    auto f = [x](int y) { std::cout &lt;&lt; x+y &lt;&lt; std::endl;};
    f(1);
    return 0;
}</code></pre>
<p><strong>4、按引用捕获</strong></p>
<p>你可以通过使用 &amp; 符号将变量传递给 lambda 表达式来按引用捕获变量。当一个变量被按引用捕获时，它的当前值被存储在闭包中，并且在周围作用域中变量发生变化时被更新。这是通过在方括号[ ]中在变量前加上取地址运算符 &amp; 来实现的。</p>
<p>例子：</p>
<pre class="pure-highlightjs"><code class="null">#include &lt;iostream&gt;

int main() {
  int x = 42;
  auto f = [&amp;x]() { std::cout &lt;&lt; x &lt;&lt; std::endl; };
  f();
  return 0;
}</code></pre>
<pre class="pure-highlightjs"><code class="null">#include &lt;iostream&gt;

int main() {
  int x = 10;

  auto add_one = [&amp;x]() { ++x; };
  add_one();
  std::cout &lt;&lt; x &lt;&lt; "\n";

  return 0;
}</code></pre>
<pre class="pure-highlightjs"><code class="null">#include &lt;iostream&gt;

int main() {
  int x = 42;
  auto f = [&amp;x]() { std::cout &lt;&lt; x &lt;&lt; std::endl; };
  f();
  return 0;
}</code></pre>
<p><strong>5、可变Lambda表达式</strong></p>
<p>默认情况下，由 lambda 表达式捕获的变量是常量，不能在 lambda 表达式体内修改。如果你想要在 lambda 表达式中修改捕获的变量，你可以将 lambda 表达式设为可变。可变lambda允许捕获的变量被修改。这是通过在方括号 [ ] 中包含可变关键字来实现的。</p>
<p>例子：</p>
<pre class="pure-highlightjs"><code class="null">#include &lt;iostream&gt;

int main() {
  int x = 42;
  auto f = [x]() mutable { std::cout &lt;&lt; ++x &lt;&lt; std::endl; };
  f();
  return 0;
}</code></pre>
<p>lambda 表达式类似于普通函数，但它们有一些关键的区别。例如，lambda 表达式的类型没有被显式指定，但可以由编译器推断出来。此外，lambda 表达式可以从周围的作用域中捕获变量，这使得它们非常适用于创建闭包和在 C++ 中使用函数式编程概念。</p>
<p>与传统函数相比，lambda 表达式具有一些性能优势：</p>
<ul>
<li>内联函数：编译器会自动将 lambda 表达式内联，这意味着它们的代码直接插入到调用函数中。这可以减少函数调用的开销并提高性能。</li>
<li>避免命名函数的开销：lambda 表达式没有名称，因此它们不必被声明和存储在符号表中，这可以减少开销并提高性能。</li>
<li>改善高速缓存局部性：lambda 表达式可以在同一个函数中定义和使用，这意味着lambda使用的代码和数据将存储在与调用代码相同的高速缓存行中。这可以改善高速缓存局部性并降低高速缓存失效的成本。</li>
<li>减小代码大小：lambda 表达式通常比命名函数小，并且它们不需要外部函数调用，这可以减小编译代码的大小并提高性能。</li>
<li>增加灵活性：lambda 表达式可以用来将函数作为参数传递给其他函数，这提供了更大的灵活性，可以改善性能，减少重复代码的需求。</li>
<li>提高可读性：lambda 表达式可以通过以紧凑而自包含的方式封装复杂的逻辑来使代码更易于阅读。这可以通过使代码更易于理解和维护来提高性能。</li>
</ul>
<p>总之，与传统函数相比，lambdas 可以通过减少开销、提高缓存位置、减少代码大小、提高灵活性和提高可读性来提高性能。</p><p>The post <a href="https://www.linuxmi.com/c-lambda.html">释放 C++ 中 Lambda 表达式的强大威力</a> first appeared on <a href="https://www.linuxmi.com">Linux迷</a>.</p>]]></content:encoded>
					
					<wfw:commentRss>https://www.linuxmi.com/c-lambda.html/feed</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>C 语言分支结构五题</title>
		<link>https://www.linuxmi.com/c-language-branch-structure.html?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=c-language-branch-structure</link>
					<comments>https://www.linuxmi.com/c-language-branch-structure.html#respond</comments>
		
		<dc:creator><![CDATA[渔 火]]></dc:creator>
		<pubDate>Mon, 13 Feb 2023 11:30:06 +0000</pubDate>
				<category><![CDATA[C/C++]]></category>
		<guid isPermaLink="false">https://www.linuxmi.com/?p=20150</guid>

					<description><![CDATA[<p>Hi！这里是渔火，今天我们来做有关分支结构的代码题目，每道题都需要用到分支结构。 【1】编写程序，输 &#8230;</p>
<p>The post <a href="https://www.linuxmi.com/c-language-branch-structure.html">C 语言分支结构五题</a> first appeared on <a href="https://www.linuxmi.com">Linux迷</a>.</p>]]></description>
										<content:encoded><![CDATA[<p>Hi！这里是渔火，今天我们来做有关分支结构的代码题目，每道题都需要用到分支结构。</p>
<p>【1】编写程序，输入有关月份值，输出该月份是第几季度。</p>
<p>【2】根据键盘输入的年、月，输出该年该月的天数。</p>
<p>【3】编写程序，判断输入的年份是否为闰年。</p>
<p>【4】由键盘输入一个3位的整数，判断该数是否位升序数。如果输入的不是3位数，输出“输入错误”。升序是指高位数依次小于其低位数。</p>
<p>【5】编写程序，输入一个整数，判断它是奇数还是偶数。</p>
<p>【1】编写程序，输入有关月份值，输出该月份是第几季度。</p>
<pre class="pure-highlightjs"><code class="cpp">#include&lt;stdio.h&gt;
//2023.2.3渔火 Linux迷 www.linuxmi.com
int main()
{
	
	int month;
	printf("输入月份：");
	scanf("%d",&amp;month);
	switch((month-1)/3)
	{
		case 0:
			printf("%d月是第1季度\n",month);
			break;
		case 1:
			printf("%d月是第2季度\n",month);
			break;
		case 2:
			printf("%d月是第3季度\n",month);
			break;
		case 3:
			printf("%d月是第4季度\n",month);
			break;
		default:
			printf("输入错误\n");
			break;
	 } 
					//2023.2.3渔火 Linux迷 www.linuxmi.com
	return 0;
}</code></pre>
<p>运行结果如下：//输入2，结果是第1季度</p>
<p><img loading="lazy" decoding="async" class="alignnone size-full wp-image-20326" src="https://www.linuxmi.com/wp-content/uploads/2023/02/cc31.png" alt="" width="1213" height="753" /></p>
<p>分析：本题中构造的表达式为“<code class="cpp">(month-1)/3</code>”。当输入月份1、2、3时，表达值为0，以此类推。</p>
<p>【2】根据键盘输入的年、月，输出该年该月的天数。</p>
<pre class="pure-highlightjs"><code class="cpp">#include&lt;stdio.h&gt;
//2023.2.3渔火 Linux迷 www.linuxmi.com
int main()
{
	
	int year,month,days;
	printf("请输入年,月：");
	scanf("%d,%d",&amp;year,&amp;month);
	switch(month)
	{
		case 1:
		case 3:
		case 5:
		case 7:
		case 8:
		case 10:
		case 12:
			days=31;
			break;
		case 4:
		case 6:
		case 9:
		case 11:
			days=30;
			break;
		case 2:
			if(year%400==0||year%4==0&amp;&amp;year%100!=0)
				days=29;
			else
				days=28;
				break;
			
	}
	printf("%d年%d月的天数是%d天\n",year,month,days);
						//2023.2.3渔火 Linux迷 www.linuxmi.com
	return 0;
}</code></pre>
<p>运行结果如下：//输入2023,2 输出结果是2023年2月的天数是28天</p>
<p><img loading="lazy" decoding="async" class="alignnone size-full wp-image-20327" src="https://www.linuxmi.com/wp-content/uploads/2023/02/cc32.png" alt="" width="1213" height="753" /></p>
<p>【3】编写程序，判断输入的年份是否为闰年。</p>
<pre class="pure-highlightjs"><code class="cpp">#include&lt;stdio.h&gt;
/2023.2.3渔火 Linux迷 www.linuxmi.com
int main()
{
	
	int year,k;
	printf("输入年份:");
	scanf("%d",&amp;year);
	if((year%4==0&amp;&amp;year%100!=0)||(year%400==0))
		k=1;
	else
		k=0;
	if(k)
		printf("%d是闰年\n",year);
	else
		printf("%d不是闰年\n",year);
						//2023.2.3渔火 Linux迷 www.linuxmi.com
	return 0;
}</code></pre>
<p>运行结果如下：//输入2023输出结果为2023年不是闰年</p>
<p><img loading="lazy" decoding="async" class="alignnone size-full wp-image-20328" src="https://www.linuxmi.com/wp-content/uploads/2023/02/cc33.png" alt="" width="1213" height="753" /></p>
<p>分析：k作为“标志变量”，用于表示输入的年份是否为闰年。如果是闰年，就使k的值为1，如果不是闰年，就使k的值为0。最后检查k的值，如果是1，就是闰年，输出”是闰年“的信息；如果是0，就不是闰年，输出”不是闰年“的信息。</p>
<p>【4】由键盘输入一个3位的整数，判断该数是否位升序数。如果输入的不是3位数，输出“输入错误”。升序是指高位数依次小于其低位数。</p>
<pre class="pure-highlightjs"><code class="cpp">#include&lt;stdio.h&gt;
//2023.2.3渔火 Linux迷 www.linuxmi.com
int main()
{
	
	int n,x,y,z;
	scanf("%d",&amp;n);
	if(n&lt;100||n&gt;999)
		printf("输入错误！\n");
	else
	{
		x=n/100;
		y=n/10%10;
		z=n%10;
		if(x&lt;y&amp;&amp;y&lt;z)
			printf("%d是升序数\n",n);
		else
			printf("%d不是升序数\n",n);
	 } 
					//2023.2.3渔火 Linux迷 www.linuxmi.com
	return 0;
}</code></pre>
<p>运行结果如下：//输入789，输出结果为789为升序数</p>
<p><img loading="lazy" decoding="async" class="alignnone size-full wp-image-20329" src="https://www.linuxmi.com/wp-content/uploads/2023/02/cc34.png" alt="" width="1213" height="753" /></p>
<p>【5】编写程序，输入一个整数，判断它是奇数还是偶数，并输出判断结构。</p>
<pre class="pure-highlightjs"><code class="cpp">#include&lt;stdio.h&gt;
//2023.2.3渔火 Linux迷 www.linuxmi.com
int main()
{
	
	int x;
	printf("请输入一个整数：");
	scanf("%d",&amp;x);
	if(x%2!=0)
		printf("%d是奇数\n",x);
	else
		printf("%d是偶数\n",x);
							//2023.2.3渔火 Linux迷 www.linuxmi.com
	return 0;
}</code></pre>
<p>运行结果如下：输入0，输出结果为0是偶数</p>
<p><img loading="lazy" decoding="async" class="alignnone size-full wp-image-20330" src="https://www.linuxmi.com/wp-content/uploads/2023/02/cc35.png" alt="" width="1213" height="696" /></p><p>The post <a href="https://www.linuxmi.com/c-language-branch-structure.html">C 语言分支结构五题</a> first appeared on <a href="https://www.linuxmi.com">Linux迷</a>.</p>]]></content:encoded>
					
					<wfw:commentRss>https://www.linuxmi.com/c-language-branch-structure.html/feed</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>C 语言之循环结构（下）</title>
		<link>https://www.linuxmi.com/c-language-cyclic-structure-2.html?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=c-language-cyclic-structure-2</link>
					<comments>https://www.linuxmi.com/c-language-cyclic-structure-2.html#respond</comments>
		
		<dc:creator><![CDATA[渔 火]]></dc:creator>
		<pubDate>Sun, 12 Feb 2023 05:19:27 +0000</pubDate>
				<category><![CDATA[C/C++]]></category>
		<guid isPermaLink="false">https://www.linuxmi.com/?p=20282</guid>

					<description><![CDATA[<p>Hi！这里是渔火。今天我们来讲用while语句和do-while语句实现循环结构。 在C语言中，使用 &#8230;</p>
<p>The post <a href="https://www.linuxmi.com/c-language-cyclic-structure-2.html">C 语言之循环结构（下）</a> first appeared on <a href="https://www.linuxmi.com">Linux迷</a>.</p>]]></description>
										<content:encoded><![CDATA[<p>Hi！这里是渔火。今天我们来讲用while语句和do-while语句实现循环结构。</p>
<p>在C语言中，使用while语句完成不定次数的循环，如果满足循环条件，则反复执行循环体语句，当循环条件不满足时退出循环。while语句在使用时，总是先要判断一个条件，使用可以用while语句实现“当型”循环。while语句的一般形式如下：while（表达式）循环体；。接下来我们来看一个例子。</p>
<h2><strong>【由键盘输入一串字符，分别统计输入字符中数字字符、字母字符以及其他字符的个数。】</strong></h2>
<pre class="pure-highlightjs"><code class="cpp">#include&lt;stdio.h&gt;
//2023.2.5渔火 Linux迷 www.linuxmi.com
int main()
{
	int d,l,o;
	char ch;
	d=l=o=0;
	printf("请输入一串字符:");
	while((ch=getchar())!='\n')
		if((ch&gt;='0')&amp;&amp;(ch&lt;='9'))
			d++;
		else if ((ch&gt;='a')&amp;&amp;(ch&lt;='z')||(ch&gt;='A')&amp;&amp;(ch&lt;='Z'))
			l++;
		else 
			o++;
	printf("数字%d个，字母%d个，其他%d个\n",d,l,o);
					//2023.2.5渔火 Linux迷 www.linuxmi.com
	return 0;
}</code></pre>
<p>运行结果如下：//随便输入字母字符数字</p>
<p><img loading="lazy" decoding="async" class="alignnone size-full wp-image-20291" src="https://www.linuxmi.com/wp-content/uploads/2023/02/cc21.png" alt="" width="1213" height="753" /></p>
<p>分析：按照题意，由键盘输入一行字符是一个重复的动作，每输入一个字符都需要判断属于哪种字符，分别进行统计。若输入的是一个回车符时，程序运行结束。<code class="cpp">(ch=getchar())!='\n'</code> 不能写成<code class="cpp">ch=getchar()!='\n'</code> 两者不等价。循环体为为一条完整的if语句，若有多条语句时，必须使用复合语句的形式。while后面的括号“（）”不可省略。</p>
<p>在C语言中，do-while语句也用于完成不定次数的循环，与while语句不同的是，do-while语句首先执行一次循环体，然后判断循环条件，如果满足，则反复执行循环语句，否则结束循环。do-while语句的一般形式如下：do 循环体 while（表达式）；。接下来我们来看两个例子。</p>
<h2><strong>【求自然数的最大公约数和最小公倍数】</strong></h2>
<pre class="pure-highlightjs"><code class="cpp">#include&lt;stdio.h&gt;
//2023.2.5渔火 Linux迷 www.linuxmi.com
int main()
{
	int a,b,r,n,m;
	printf("请输入两个整数：");
	scanf("%d%d",&amp;a,&amp;b);
	m=a,n=b;
	do
	{
		r=a%b;
		a=b;
		b=r;
	 } while(r!=0);
	 printf("%d和%d的最大公约数是：%d\n",m,n,a);
	 printf("最小公倍数是：%d",m*n/a);
					//2023.2.5渔火 Linux迷 www.linuxmi.com
	return 0;
}</code></pre>
<p>运行结果如下：//输入12 72</p>
<p><img loading="lazy" decoding="async" class="alignnone size-full wp-image-20292" src="https://www.linuxmi.com/wp-content/uploads/2023/02/cc22.png" alt="" width="1213" height="753" /></p>
<h2>【输入一个整数，统计该数的位数】</h2>
<pre class="pure-highlightjs"><code class="cpp">#include&lt;stdio.h&gt;
//2023.2.5渔火 Linux迷 www.linuxmi.com
int main()
{
	long n,m;
	int count=0;
	printf("请输入一个整数：");
	scanf("%ld",&amp;n);
	m=n;
	if(n&lt;0)n=-m;
	do{
		n=n/10;
		count++;
	} while(n!=0);
	printf("整数%ld有%d位数\n",m,count);
						//2023.2.5渔火 Linux迷 www.linuxmi.com 
	return 0;
}</code></pre>
<p>运行结果如下：//输入1235698</p>
<p><img loading="lazy" decoding="async" class="alignnone size-full wp-image-20293" src="https://www.linuxmi.com/wp-content/uploads/2023/02/cc23.png" alt="" width="1213" height="753" /></p>
<p>许多时候当循环结构中出现多个循环条件时，要求当某个条件满足时会立即结束循环，或者循环结构中根据条件会跳过某些语句继续循环，这就要在循环结构中配合使用break语句和continue语句。</p>
<p>break语句的一般形式如下：break;。当break语句用于循环语句中时，可使程序终止循环而转去执行循环语句的后继语句。通常break语句总是与if语句一起配合使用，即满足条件时便跳出循环。</p>
<p>continue语句的作用是跳过循环体continue后面的语句，继续下一次循环。continue语句只能用在循环语句中，常与if语句一起使用。continue语句的一般形式如下：continue；。我们来看一个用到continue语句的程序设计。</p>
<h2>【把1~100之间能被7整除的数，以每行5个的形式在屏幕上输出。】</h2>
<pre class="pure-highlightjs"><code class="cpp">#include&lt;stdio.h&gt;
//2023.2.5渔火 Linux迷 www.linuxmi.com
int main()
{
	int i,n=1;
	for(i=1;i&lt;=100;i++)
	{
		if(i%7!=0)
			continue;
		printf("%4d",i);
		if(n++%5==0)printf("\n");
	}
					//2023.2.5渔火 Linux迷 www.linuxmi.com
	return 0;
}</code></pre>
<p><img loading="lazy" decoding="async" class="alignnone size-full wp-image-20294" src="https://www.linuxmi.com/wp-content/uploads/2023/02/cc25.png" alt="" width="1213" height="753" /></p>
<p>在C语言中，还有一种可以实现循环控制的语句，即goto语句。goto语句的一般形式如下：goto语句标号；。</p>
<p>说明：语句标号是一个有效的标识符，使用时在语句的后面跟一个“；”出现在函数中某语句的前面。程序执行到goto语句时，会控制跳转到该语句标号处，达到控制循环的目的。语句标号必须与goto语句处于同一个函数中。通常goto语句与if语句连用实现循环控制。大型程序中由于goto语句可能存在不合理的使用，会使程序结构变坏，所以结构化程序设计中，不建议使用goto语句。</p><p>The post <a href="https://www.linuxmi.com/c-language-cyclic-structure-2.html">C 语言之循环结构（下）</a> first appeared on <a href="https://www.linuxmi.com">Linux迷</a>.</p>]]></content:encoded>
					
					<wfw:commentRss>https://www.linuxmi.com/c-language-cyclic-structure-2.html/feed</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>C 语言之循环结构（上）</title>
		<link>https://www.linuxmi.com/c-language-cyclic-structure-1.html?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=c-language-cyclic-structure-1</link>
					<comments>https://www.linuxmi.com/c-language-cyclic-structure-1.html#respond</comments>
		
		<dc:creator><![CDATA[渔 火]]></dc:creator>
		<pubDate>Wed, 08 Feb 2023 12:13:58 +0000</pubDate>
				<category><![CDATA[C/C++]]></category>
		<guid isPermaLink="false">https://www.linuxmi.com/?p=20219</guid>

					<description><![CDATA[<p>Hi！这里是渔火。今天我们来学校C语言中的循环结构。循环结构是结构化程序设计中的基本结构之一。循环结 &#8230;</p>
<p>The post <a href="https://www.linuxmi.com/c-language-cyclic-structure-1.html">C 语言之循环结构（上）</a> first appeared on <a href="https://www.linuxmi.com">Linux迷</a>.</p>]]></description>
										<content:encoded><![CDATA[<p>Hi！这里是渔火。今天我们来学校C语言中的循环结构。循环结构是结构化程序设计中的基本结构之一。循环结构在程序设计中的应用很普遍，几乎所有具有实用价值的应用程序中都包含着循环结构。循环结构的特点是，可以完成有规律的、需要重复计算或处理的任务。C语言提供了for语句、while语句和do-while三种循环语句。我们来看一个用到循环结构的程序设计。</p>
<p>【1】假设今年我国的人口总数为13亿，若按每年2%增长，计算从现在开始10年内每年人口的数量。</p>
<pre class="pure-highlightjs"><code class="cpp">#include&lt;stdio.h&gt;
#include&lt;math.h&gt; 
//2023.2.4渔火 Linux迷 www.linuxmi.com
int main()
{
	int n=13,year;
	double number,rate=0.02;
	for(year=1;year&lt;=10;year++)
	{
		number=n*pow((1+rate),year);
		printf("%2d年后，人数为：%.2f亿\n",year,number);
	}
	
				//2023.2.4渔火 Linux迷 www.linuxmi.com
	return 0;
}</code></pre>
<p>运行结果如下：</p>
<pre class="pure-highlightjs"><code class="null">linuxmi@linuxmi /home/linuxmi/www.linuxmi.com                                     
⚡ gcc  linuxmi.c -lm -o  linuxmi

linuxmi@linuxmi /home/linuxmi/www.linuxmi.com                                     
⚡ ./linuxmi
 1年后，人数为：13.26亿
 2年后，人数为：13.53亿
 3年后，人数为：13.80亿
 4年后，人数为：14.07亿
 5年后，人数为：14.35亿
 6年后，人数为：14.64亿
 7年后，人数为：14.93亿
 8年后，人数为：15.23亿
 9年后，人数为：15.54亿
10年后，人数为：15.85亿</code></pre>
<p><img loading="lazy" decoding="async" class="alignnone size-full wp-image-20243" src="https://www.linuxmi.com/wp-content/uploads/2023/02/cc1.png" alt="" width="1038" height="587" /></p>
<p>分析：程序中的for循环控制语句中，年份year的初始值为1，终值为10，增量用year++实现。</p>
<p><code class="cpp">{<br />
number=n*pow((1+rate),year);<br />
printf("%2d年后，人数为：%.2f亿\n",year,number);<br />
}</code></p>
<p>是需要重复执行的语句，称为循环语句。在重复执行的过程中，使用了同一个计算公式，但年份year每次递增1，因此计算出的人口数量number会不同。</p>
<p>for语句是C语言提供的功能强大、使用广泛的一种循环结构，不仅可以解决循环次数未知的循环问题，特别适合解决循环次数已知的循环问题。for语句的一般形式为：for(表达式1：表达式2：表达式3） 循环体语句；</p>
<p>1、可以应用于计数型的循环。格式是：for(循环变量赋初值；循环条件，循环变量增量） 循环体语句；</p>
<p>说明：循环变量赋初值是一个赋值语句，用于给循环变量赋初值；循环条件是一个关系表达式，决定何时终止循环；循环变量增量决定循环变量在完成一次循环后如何变化。三部分之间以”；“隔开。</p>
<p>【2】输入一个正整数，求n!。</p>
<pre class="pure-highlightjs"><code class="cpp">#include&lt;stdio.h&gt;
//2023.2.4渔火 Linux迷 www.linuxmi.com
int main()
{
	int i,n;
	double fac;
	printf("输入n的值：");
	scanf("%d",&amp;n);
	fac=1;
	for(i=1;i&lt;=n;i++)
		fac=fac*i;
	printf("%d!=%.0f\n",n,fac);
	
					//2023.2.4渔火 Linux迷 www.linuxmi.com 
	return 0;
}</code></pre>
<p>运行结果如下：//输入10</p>
<p><img loading="lazy" decoding="async" class="alignnone size-full wp-image-20244" src="https://www.linuxmi.com/wp-content/uploads/2023/02/cc2.png" alt="" width="1038" height="398" /></p>
<p>2、for语句的一般形式中省略表达式1，格式为：for(;表达式2；表达式3)  循环体语句；。</p>
<p>说明：省略表达式1时，可以将循环变量赋初值放在for之前。注意，此时不能省略第一个”；“。</p>
<p>3、for语句的一般形式中省略表达式2，格式为：for(;表达式1；；表达式3)  循环体语句；。</p>
<p>说明”省略表达式2时，表示不对循环进行控制，这时如果没有其他处理的话。会形成死循环。应避免这样使用for结构。</p>
<p>4、for语句的一般形式中省略表达式3，格式为：for(;表达式1；表达式2)  循环体语句；。</p>
<p>说明：省略表达式3时，可以在循环体语句中加入修改循环变量的值的语句。</p>
<p>5、for语句的一般形式中表达式1和表达式3也可以是逗号表达式。</p>
<p>6、for语句的一般形式中表达式2 的值只要非0，就执行循环体。</p>
<p>7、for语句的一般形式中循环体语句可以省略。</p>
<p>for使用循环例子。</p>
<p>【编写程序，输入10个数，输出其中的最大值】</p>
<pre class="pure-highlightjs"><code class="cpp">#include&lt;stdio.h&gt;
//2023.2.4渔火 Linux迷 www.linuxmi.com
int main()
{
	int i;
	float x,max;
	printf("请输入第1个数："); 
	scanf("%f",&amp;x);
	max=x;
	for(i=1;i&lt;=9;i++)
	{
		printf("请输入第%d个数",i+1);
		scanf("%f",&amp;x);
		if(x&gt;max)
			max=x;
	}
	printf("10个数的最大值是：%.0f",max);
				//2023.2.4渔火 Linux迷 www.linuxmi.com 
	return 0;
}</code></pre>
<p><img loading="lazy" decoding="async" class="alignnone size-full wp-image-20245" src="https://www.linuxmi.com/wp-content/uploads/2023/02/cc3.png" alt="" width="1038" height="641" /></p>
<p>分析：这是典型的最值问题，求解的思路是：定义变量max存放最大数，将输入的第一个数赋给max作为最大数，在后续循环中，每输入一个数，都与max进行比较，若比max大，则将其赋给max,循环结束后，变量max中即为最大数。</p>
<p>【编写程序，输出所有的水仙花】</p>
<pre class="pure-highlightjs"><code class="cpp">#include&lt;stdio.h&gt;
//2023.2.4渔火 Linux迷 www.linuxmi.com
int main()
{
	int num,a,b,c;
	for(num=100;num&lt;=999;num++)
	{
		a=num/100;
		b=num%100/10;
		c=num%10;
		if(num==a*a*a+b*b*b+c*c*c)
			printf("%5d",num);
	}
				//2023.2.4渔火 Linux迷 www.linuxmi.com 
	return 0;
}</code></pre>
<p>运行结果如下：</p>
<p><img loading="lazy" decoding="async" class="alignnone size-full wp-image-20246" src="https://www.linuxmi.com/wp-content/uploads/2023/02/cc4.png" alt="" width="1038" height="371" /></p>
<p>【由键盘输入3个数字，将其组合成一个整型数并输出】</p>
<pre class="pure-highlightjs"><code class="cpp">#include&lt;stdio.h&gt;
//2023.2.4渔火 Linux迷 www.linuxmi.com
int main()
{
	int n=0,i;
	char ch;
	printf("输入3个数字：");
	for(i=1;i&lt;=3;i++)
	{
		scanf("%c",&amp;ch);
		n=n*10+ch-'0';
	 } 
	 printf("%d\n",n);
					//2023.2.4渔火 Linux迷 www.linuxmi.com 
	return 0;
}</code></pre>
<p>运行结果如下：</p>
<p><img loading="lazy" decoding="async" class="alignnone size-full wp-image-20248" src="https://www.linuxmi.com/wp-content/uploads/2023/02/cc5.png" alt="" width="1038" height="317" /></p><p>The post <a href="https://www.linuxmi.com/c-language-cyclic-structure-1.html">C 语言之循环结构（上）</a> first appeared on <a href="https://www.linuxmi.com">Linux迷</a>.</p>]]></content:encoded>
					
					<wfw:commentRss>https://www.linuxmi.com/c-language-cyclic-structure-1.html/feed</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>C 语言之分支结构（下）</title>
		<link>https://www.linuxmi.com/c-language-branch-structure-2.html?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=c-language-branch-structure-2</link>
					<comments>https://www.linuxmi.com/c-language-branch-structure-2.html#respond</comments>
		
		<dc:creator><![CDATA[渔 火]]></dc:creator>
		<pubDate>Sun, 05 Feb 2023 02:22:11 +0000</pubDate>
				<category><![CDATA[C/C++]]></category>
		<guid isPermaLink="false">https://www.linuxmi.com/?p=20143</guid>

					<description><![CDATA[<p>Hi！这里是渔火。今天我们继续来讲C语言的分支结构。在C语言里，可以使用if-else实现分支结构。 &#8230;</p>
<p>The post <a href="https://www.linuxmi.com/c-language-branch-structure-2.html">C 语言之分支结构（下）</a> first appeared on <a href="https://www.linuxmi.com">Linux迷</a>.</p>]]></description>
										<content:encoded><![CDATA[<p>Hi！这里是渔火。今天我们继续来讲C语言的分支结构。在C语言里，可以使用if-else实现分支结构。</p>
<p>1、双分支if语句。其一般形式为：if（表达式）语句1；else  语句2；。</p>
<p>我们来用双分支if语句来做一道简单的题目。</p>
<p>【1.1】使用双分支语句求两个数中较大的数。</p>
<pre class="pure-highlightjs"><code class="cpp">#include&lt;stdio.h&gt;
//2023.2.1渔火 Linux迷 www.linuxmi.com
int main()
{
	
	int a,b;
	printf("请输入两个整数："); 
	scanf("%d%d",&amp;a,&amp;b);
	if(a&gt;b)
		printf("两个整数中的最大数为：%d\n",a);
	else
		printf("两个整数中的最大数为：%d\n",b);
					//2023.2.1渔火 Linux迷 www.linuxmi.com
	return 0;
}</code></pre>
<p>运行结果1：</p>
<p><img loading="lazy" decoding="async" class="alignnone size-full wp-image-20188" src="https://www.linuxmi.com/wp-content/uploads/2023/02/c90.png" alt="" width="1213" height="673" /><br />
运行结果2：</p>
<p><img loading="lazy" decoding="async" class="alignnone size-full wp-image-20189" src="https://www.linuxmi.com/wp-content/uploads/2023/02/c91.png" alt="" width="1213" height="673" /><br />
2、单分支语句。其一般形式为：if（表达式） 语句；</p>
<p>我们用单分支语句来解决一道题目。</p>
<p>【2.1】编写程序任意输入一个实数，输出其绝对值。</p>
<pre class="pure-highlightjs"><code class="cpp">#include&lt;stdio.h&gt;
//2023.2.1渔火 Linux迷 www.linuxmi.com
int main()
{
	
	float x;
	scanf("%f",&amp;x);
	if(x&lt;0)
		x=-x;
	printf("%f",x);
					//2023.2.1渔火 Linux迷 www.linuxmi.com
	return 0;
}</code></pre>
<p>运行结果如下：<br />
<img loading="lazy" decoding="async" class="alignnone size-full wp-image-20190" src="https://www.linuxmi.com/wp-content/uploads/2023/02/c95.png" alt="" width="1213" height="673" /><br />
分析：无论在双分支还是单分支if语句的格式中，“表达式”都是用来描述判断的条件，语法上可以是任意类型的表达式。表达式的结果如果为“0”，表示“假”；结果为“1”，表示“真”。<br />
无论在双分支还是单分支if语句的格式中，被执行的语句均为单个语句，如果想要执行一组语句时，则必须将这一组语句用{}括起来形成复合语句，但在“}”之后不能再加括号。注意：复合语句中的语句执行时会全部被执行。<br />
我们来看一个复合语句的例子。<br />
【3.1】输入3个实数，要求按从小到大的顺序输出。</p>
<pre class="pure-highlightjs"><code class="cpp">#include&lt;stdio.h&gt;
//2023.2.1渔火 Linux迷 www.linuxmi.com
int main()
{
	
	float x,y,z,k;
	scanf("%f %f %f",&amp;x,&amp;y,&amp;z);
	if(x&gt;y)
		{k=x;x=y;y=k;}
	if(x&gt;z)
		{k=x;x=z;z=k;}
	if(y&gt;z)
		{k=y;y=z;z=k;}
	printf("%5.2f,%5.2f,%5.2f\n",x,y,z);
					//2023.2.1渔火 Linux迷 www.linuxmi.com
	return 0;
}</code></pre>
<p>运行结果如下：</p>
<p><img loading="lazy" decoding="async" class="alignnone size-full wp-image-20191" src="https://www.linuxmi.com/wp-content/uploads/2023/02/c96.png" alt="" width="1213" height="753" /><br />
分析：{k=x;x=z;z=k;}的作用是交换变量x和y的值，变量k为中间变量。</p>
<p>使用if语句的基本形式解决分支少于两个的问题十分方便，而经常遇到的是多于两个分支，或者需要再多个不同条件下执行不同语句的问题，这就需要掌握if语句的嵌套以及多分支结果。一个if语句中又包含一个或多个if语句的现象称为if语句的嵌套。if语句的基本形式：if(表达式) 语句1；else 语句2；。其中“语句1”或“语句2”都可以嵌套另一个if语句，在缺省else部分的if语句中的“语句”也可以嵌套另一个if语句。在if语句嵌套的结构中一定要注意else与if之间的对应关系。为了避免二义性，在C语言中规定其对应原则是：else总是与它前面最近的一个未匹配的if相匹配。</p>
<p>【4.1】输入3个任意数，找出其中的最大值。</p>
<pre class="pure-highlightjs"><code class="cpp">#include&lt;stdio.h&gt;
//2023.2.1渔火 Linux迷 www.linuxmi.com
int main()
{
	
	int x,y,z,max;
	scanf("%d %d %d",&amp;x,&amp;y,&amp;z);
	if(x&gt;y)
		if(x&gt;z)
			max=x;
		else
			max=z;
	else
		if(y&gt;z)
			max=y;
		else
			max=z;
	printf("max=%d\n",max);
					//2023.2.1渔火 Linux迷 www.linuxmi.com
	return 0;
}</code></pre>
<p>运行结果如下：<br />
<img loading="lazy" decoding="async" class="alignnone size-full wp-image-20192" src="https://www.linuxmi.com/wp-content/uploads/2023/02/c98.png" alt="" width="1213" height="753" /><br />
多分支if语句是最常用的实现多路分支的方法，其一般形式为：if(表达式1） 语句1；else if（表达式2）···else if(表达式n-1) 语句n-1;else 语句n;.<br />
在C语言中还提供了一种switch语句也可以实现多分支的选择。switch的一般形式为：switch(表达式){case 常量表达式1；语句1；break；case 常量表达式2；语句2；break；···case 常量表达式n;语句n;break;default:语句n+1；break；}<br />
注意：1、switch后的表达式可以是任何表达式，其值只能为整型、字符型、枚举型。2、每个case后面的常量表达式的值互不相同，否则会出现互相矛盾的现象。3、各个case和default的出现次序不影响执行结果。4、可以让多个case共用一组执行语句。5、switch语句允许嵌套使用。</p><p>The post <a href="https://www.linuxmi.com/c-language-branch-structure-2.html">C 语言之分支结构（下）</a> first appeared on <a href="https://www.linuxmi.com">Linux迷</a>.</p>]]></content:encoded>
					
					<wfw:commentRss>https://www.linuxmi.com/c-language-branch-structure-2.html/feed</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
	</channel>
</rss>
