1数组定义并少量初始化的误区最近我在看linux内核源码发现函数里面使用了大量数组变量其中有一些数组在定义的同时完成了初部分元素的少量始化处理这里以前我一直有一个误区那就是对只对显式元素进行初始化处理那种隐式的元素为垃圾值现在着重强调一下这种理解是错误的。如下代码enum s5p_tv_hdmi_err s5p_hdmi_init_spd_infoframe( enum s5p_hdmi_transmit trans_type, u8 *spd_header, u8 *spd_data) { u8 header[3] {0x83, 0x1, 25}; u8 vendor[8] {0,}; u8 product[17] {0,}; int checksum 0; int i; switch (trans_type) { case HDMI_DO_NOT_TANS: writel(SPD_TX_CON_NO_TRANS, g_hdmi_base S5P_SPD_CON); break; case HDMI_TRANS_ONCE: writel(SPD_TX_CON_TRANS_ONCE, g_hdmi_base S5P_SPD_CON); break; case HDMI_TRANS_EVERY_SYNC: writel(SPD_TX_CON_TRANS_EVERY_VSYNC, g_hdmi_base S5P_SPD_CON); break; default: pr_err(%s::invalid out_mode parameter(%d)\n, __func__, trans_type); return S5P_TV_HDMI_ERR_INVALID_PARAM; break; } ... }在函数开头位置定义了2个数组vendor和product都是用了{0, }的初始化用法。首先我们有时候看到{}内部初始化值后面跟着逗号“,”有时候又没有这两种写法编译器都是允许的并且完全等效。其次这样写的目的是2个数组中每一个元素都被写0而不是只有第一个元素0写0剩余其他元素为垃圾值因为存在栈上我以前那种理解方式是完全错误的。无论是早期编译器、还是比较现代的gcc/clang编译器至少从KR经典时代开始就这样规定了。我以前那种误理解方式是完全错误的将没有初始化和部分初始化给等效了。最后如果初始化值不为0例如int a[5] {7, } /* 逗号空格可以省略 */正确的理解是元素a[0] 7,剩余其他元素为0而不是每一个元素都是7也不是隐藏元素为垃圾值。总结数组定义并初始化时遇到“少量初始化”后剩余隐式元素会自动补0处理。2三目运算符? :的适用场景在看linux内核源码的时候里面有大量代码使用了三目运算而非使用if-else if-else条件判断语句我当时就有一个疑问为什么在这里使用三目运算而不使用更广泛的if-else if-else条件判断呢先看代码void s5p_hdmi_audio_set_acr(u32 sample_rate) { u32 value_n (sample_rate 32000) ? 4096 : (sample_rate 44100) ? 6272 : (sample_rate 88200) ? 12544 : (sample_rate 176400) ? 25088 : (sample_rate 48000) ? 6144 : (sample_rate 96000) ? 12288 : (sample_rate 192000) ? 24576 : 0; u32 cts (sample_rate 32000) ? 27000 : (sample_rate 44100) ? 30000 : (sample_rate 88200) ? 30000 : (sample_rate 176400) ? 30000 : (sample_rate 48000) ? 27000 : (sample_rate 96000) ? 27000 : (sample_rate 192000) ? 27000 : 0; HDMIPRINTK(sample rate %d\n, sample_rate); HDMIPRINTK(cts %d\n, cts); writel(value_n 0xff, g_hdmi_base S5P_ACR_N0); writel((value_n 8) 0xff, g_hdmi_base S5P_ACR_N1); writel((value_n 16) 0xff, g_hdmi_base S5P_ACR_N2); writel(cts 0xff, g_hdmi_base S5P_ACR_MCTS0); writel((cts 8) 0xff, g_hdmi_base S5P_ACR_MCTS1); writel((cts 16) 0xff, g_hdmi_base S5P_ACR_MCTS2); writel(cts 0xff, g_hdmi_base S5P_ACR_CTS0); writel((cts 8) 0xff, g_hdmi_base S5P_ACR_CTS1); writel((cts 16) 0xff, g_hdmi_base S5P_ACR_CTS2); writel(4, g_hdmi_base S5P_ACR_CON); }这里使用了2个三目运算实现多个分支判断从这个理解可以看出三目运算的代码段只有一行代码不能有多行正要写反也要写才能更好描述清楚例如4096, 6272, 12544...如果写成if-else if-else条件判断只有一行代码代码空白空间浪费太多。另外三目运算符经常用于这种赋值运算将判断的结果赋值给某个变量当然这种三目运算在赋值运算中的应用经常在return作为返回值返回如下代码。其实return语句也是进行一次隐式赋值操作只是这个赋值操作可以有接收方也可以没有返回值没有利用起来没有将返回值用于知道后续代码编写c语言编译器都是允许的。static inline const char *basename(const char *path) { const char *tail strrchr(path, /); return tail ? tail1 : path; }总结三目运算适合代码段只有一行代码的条件判断而且三目运算写代码能够减少代码空白区域浪费。代码段只有一行代码的情况优先使用三目运算替代普通if条件判断。三目运算经常用于赋值运算和return语句的代码。