关于首字符下划线及C/C++语言保留的名称
C和C++语言为实现保留了特定类别的名称,这意味着您无法在自己的代码中使用它们。部分名称被无条件保留,禁止用于变量名、参数名、类名、方法名、宏名等任何场景;另一些名称仅在特定上下文中被保留。
C++ 的命名规则详见 [lex.name] 章节。C语言的规则恰好与C++规则基本一致(参见第7.1.3节 “保留标识符”),这使得规则更易于记忆。
| 模式 | 条件 |
|---|---|
| 以两个下划线开头 | 保留 |
| 以下划线加大写字母开头 | 保留 |
| 以下划线加其他字符开头 | 全局作用域保留(含宏) |
| 包含两个连续下划线 | C++中保留(C中允许) |
需注意:若私有成员名称以大写字母开头,则常见的“成员名前缀下划线”约定将违反此规则。
class Widget
{
public:
Widget();
private:
int _size; // 有效
void _Toggle(); // 无效
};
C语言不支持命名空间,因此也需在全局命名空间中预留名称以备未来扩展。某些名称不能用于具有外部链接的符号。它们可用于类型名、枚举成员、局部变量以及声明为静态存储类的函数或全局变量,但不能用于 extern 函数或 extern 全局变量。
// 不允许:外部链接标识符
// 以 “str” 和小写字母开头
int strategy;
void strafe() { /* ... */ }
// 允许:内部链接标识符以
// “str” 和小写字母开头
static int strawberry;
static void stream_video() { /* ... */ }
此外,若包含对应头文件,这些名称可被函数样式宏覆盖。这意味着若需在无外部链接的场景使用保留名,必须先通过#undef取消定义或用括号包裹名称,以避免其被视为宏。
// 包含此头文件可能导致定义名为“strategy”的
// 函数样式宏。
#include <string.h>
// 必须用括号包裹以避免误判
// 作为函数样式宏。
static void (strategy)();
自C11起,符合下列正则表达式的标识符不得用于具有外部链接的符号(详见第7.31节“未来库发展方向”)。类型定义和宏也有保留名称,此处不再赘述。
| Pattern | Header |
|---|---|
cerfc?[fl]?, cexp2[fl]?,cexpm1[fl]?, clog1[0p][fl]?,clog2[fl]?, c[lt]gamma[fl]? |
complex.h |
is[a-z].*, to[a-z].* |
ctype.h, wctype.h |
atomic_[a-z].* |
stdatomic.h |
str[a-z].* |
stdlib.h, string.h |
mem[a-z].* |
string.h |
wcs[a-z].* |
string.h, wchar.h |
cnd_[a-z].*, mtx_[a-z].*,thrd_[a-z].*, tss_[a-z].* |
thread.h |
令人意外的是,C语言竟保留了strong、island和together这类标识符。
补充说明:Windows头文件历来未严格规避这些保留名称。我们正努力改进新头文件,但并非所有人都收到通知。
更新:新增特殊“内部双下划线”规则。
本文文字及图片出自 On leading underscores and names reserved by the C and C++ languages

> 令人惊讶的是,C语言竟会保留诸如strong、island和together这类标识符,但事实确是如此
好吧,我知道这只是博客文章里随口一提,但现在我不得不花大量精力去:
1. 查明这些标识符究竟在何处被保留,因为像https://pubs.opengroup.org/onlinepubs/9699919799/functions/V…似乎并未收录?
2. 尝试推测这些标识符的预期用途(比如
island,我猜可能是作用域:仅限同一岛屿上的其他标识符访问?天啊…)这是 POSIX 规范而非 C 语言标准。https://www.iso-9899.info/n1570.html#7.31 列出了为未来使用保留的库 API 名称;该文档第 7.1.3 节明确声明这些名称已被保留。
“island”一词本身并无特殊含义;关键在于所有以“is”开头且后接小写字母的名称均被保留(在外部链接及包含
<ctype.h>的文件全局作用域内),以便未来语言版本能沿袭isalpha、isdigit等模式添加更多标准库函数, 等函数,同时避免现行标准委员会预先猜测后续版本可能采用的命名模式,且不破坏现有代码(除非现有代码本就忽略这些规则——实践中此类情况相当普遍)。C语言自然是海盗最爱的语言。说不定哪天标准里真会出现“水”和“陆地”类型。届时可能需要
bool iswater()和bool island()函数!当你拿到岛屿结构体时,得确认它是否真是陆地,所以island(&possible_island)显然能帮上忙,也不会让代码读者困惑。哎,每个海盗的初恋都是C语言
你可能需要判断是否存在被水环绕的小陆地,因此需要
或者判断某个元素是否属于特定恐怖组织(或埃及女神):
若需判断某区域是否被特定恐怖组织(或埃及女神、后金属乐队)占领,可使用经典函数:
此时通常需构建内存屏障。
只需向编译器传递海盗旗即可
其实这叫作“arrgument”才对
当然,区域设置的不同会影响island()和iswater()的返回结果
我看到有人指出,这些标识符限制意味着有效的C编译器优化方案是将所有“x = to[a-z]+(y);”改为“if (!is[a-z]+(y)) x = to[a-z]+(y);”。当然,现实中编译器不会蠢到实现这种优化 🙂
这自然暗示了该优化的有效性:
x = toilet(y); -> if (!isilet(y)) x = toilet(y);
但前提是必须包含
<ctype.h>或<wctype.h>头文件。他们完全可以生成随机字符串,这样几乎不可能与现有名称冲突。而且其描述性绝不逊于C标准库中大多数现有名称。
需注意原帖未反映C23标准对此议题的最新进展:标准化机构似乎注意到无人真正关注str*、is*、to*和E*这类过度宽泛的保留机制,因此引入了“潜在保留标识符”的概念——目前我尚未能理解其具体含义。相关论文《我们认为保留的符号》[1]已纳入标准草案。
[1] https://www.open-std.org/jtc1/sc22/WG14/www/docs/n2625.pdf(希望这是正确版本)
本质上,该措辞允许他们建议实现对“潜在保留标识符”的未来可能无效用法发出警告,但对实际保留标识符的无效使用仍“无需诊断”。他们认为这能让他们毫无顾忌地进一步扩展本已过多的保留标识符。
没错,这意味着实现方会警告你代码可能在未来失效,但当真正失效时,警告就会消失。他们为何不能直接强制检测保留标识符的无效用法,我实在无法理解。
在您链接的页面中,可以看到
ctype.h保留了所有以is[a-z]和to[a-z]开头的前缀,而string.h保留了str[a-z]。这些规则源自C标准(在C99的7.26节“未来库方向”中),不过我认为该处并未使用“保留”一词。“保留”的定义出自第7.1.3节:
他指明了这些保留项的来源——C11标准第7.31节[1]。例如7.31.12条款:
> 以str开头且首字母为小写的函数名可添加至
<stdlib.h>头文件的声明中。或7.31.13条款:
> 以str、mem或wcs开头且接小写字母的函数名可添加至
<string.h>头文件声明中。因此根据标准规定,若代码包含string.h,使用“strong”或“memorize”这类名称可能与未来标准版本冲突。不过这种情况极其罕见。
[1] https://port70.net/~nsz/c/c11/n1570.html#7.31
这些字符串在正则表达式中被标记为保留字符,由特定头文件为未来扩展预留。“island”受ctype.h和wctype.h头文件约束,这些文件将所有以“is”开头的单词均设为保留字。
这种“规则非我所立”的情形,恰好能用一句俏皮话概括。
查阅C标准后发现,POSIX进一步为自身定义了C标识符规则。这包括类型名中的
_t!该规则在现实中几乎无人遵守,实在难以当真。所谓“强制”不过是未来标准版本可随意定义以_t结尾的新类型,且无需担心破坏现有代码。若你定义了专属的uint32_t类型,而新标准的uint32_t类型将其覆盖——那你(理论上)早该有所防备。
尾随的_t是保留字,我多年都对此毫不知情。直到某位面试者指出这点,才让我意识到这是我题目提示中的陷阱。他们因此加分,我也学到新知识。真好奇编译器或静态分析工具为何不更频繁地报错这类问题?
因为关注POSIX规范本就不在C编译器的职责范围内。
POSIX与C标准是两回事。例如当你针对Windows API编写代码时,POSIX就无关紧要了——你更需要警惕与Windows API头文件中类型名或常量定义的冲突,而这类冲突本就无处不在。
…况且:这条规则在现实中完全没有意义——要么你的类型名与包含头文件中的POSIX类型冲突(这种情况编译器本就会报错),要么不冲突,后者自然无碍。
还有一种情况需要补充到你列出的清单中:当你需要与POSIX系统交互时,名称冲突才可能发生。
也就是说,这些规则的主要意义在于:某些标准会规定“遵循这些规则,将使你更容易与该标准集成(如果你的计划包含此项)”。
显然,如果你根本不打算接入POSIX,这些规则对你毫无意义。同样地,不遵循规则也不会阻碍该方向,只是可能增加额外工作量。
> 况且:这条规则在现实中完全毫无意义
我认为其含义是:库作者不能将某类型命名为epoch_t,因为POSIX可能在下个版本引入epoch_t,届时某些代码可能突然无法编译。
没错,但其他“标准API”同样存在这类问题,且它们的变更频率远高于POSIX。
> 因为关注POSIX规范并非C编译器的职责。
当开发者编写符合POSIX规范的代码却被编译器拒绝时,这便成了编译器的责任。
ISO C标准本身不包含POSIX兼容性要求,因为ISO C编译器支持的平台远不止类UNIX系统。
确保C编译器符合POSIX规范是各平台供应商的责任。
全球主流编译器都面向POSIX平台开发,兼容性对它们至关重要。
但它们似乎只满足于满足ISO标准的要求。
明确一点:我们讨论的仍是同款GCC和Clang编译器,对吧?
对于typedef而言,_t后缀的设计如此符合人体工学,以至于我完全忽略了POSIX的这一部分规范——毕竟我的类型通常带有命名空间前缀,而POSIX本身永远不会与之发生冲突。
“Gotcha”这个词很好地概括了整个问题,我认为在实际代码中无需为此担忧。
实际上每个C库都需要这么做,通常会预留特定前缀。
这本质上是在声明:“若使用此API/库,需做好心理准备:未来版本可能引入符合这些模式的额外符号,且当前版本可能定义未文档化的符合这些模式的符号”。开发者可选择避免定义冲突符号。
另一种方案是库随意添加新符号,而客户端代码无法主动预防冲突。
没错,_t作为类型后缀对程序员极具吸引力。我曾提醒过人们技术上不应这么做——通常只会得到完全的漠视
喜欢这种语气
Windows 2000引入了应用程序清单概念,可执行文件通过小型XML文件存储应用程序特定设置,而非写入注册表。
该机制还支持免注册COM组件。
时至今日,许多微软团队仍未领会这一理念。
我不确定他们是否为前者提供了足够的工具支持。但后者显然缺乏完善的文档说明。
或许他们确实做过——当年MSDN还算条理清晰且内容相对完整(通过光盘或下载渠道发布时),可惜那时我太年轻没能好好利用。如今这些知识宝库大多消失殆尽,外部链接也无法解析。
当然有文档记录,否则我这个非微软员工怎么可能知晓?
当前文档位置如下:
https://learn.microsoft.com/en-us/windows/win32/sbscs/creati…
https://learn.microsoft.com/en-us/windows/win32/sbscs/manife…
https://learn.microsoft.com/en-us/windows/win32/sbscs/isolat…
https://learn.microsoft.com/en-us/windows/win32/sbscs/author…(参见最后几条关于避免使用注册表的最佳实践建议)
问题一如既往地出在缺乏相关知识普及,以及人们不愿改变工作方式。
不过有一点我需要更正:时隔多年才注意到,该功能实际上是Windows XP和Server 2003才引入的,并非Windows 2000。
我不断看到微软开发的新工具将设置存储在用户目录或文档文件夹的点文件中,而非AppData目录。
很可能是受过UNIX训练的新实习生未经充分工作审查所致。
至少根据近期趋势,这是我的推测。
题外话,这正是Python在我眼中显得丑陋的原因——强制使用双下划线表示等号等操作极其刺眼。
我虽逐渐认可其作为语言的价值,但视觉上永远无法接受这种与其他语言的冲突。
看SIMD代码时我也有同样感受。
> const __m256i in = _mm256_loadu_si256((const __m256i*)ptr);
这正是我宁愿为SIMD代码编写内联汇编甚至外部汇编,也不愿使用内置函数的原因。前者可读性强得多。
你应该用typedef定义类型,而不是这样写。
这就像抱怨代码里到处要用_Bool——明明可以包含stdbool头文件…
而根据mem[a-z].*模式,memo似乎是C11中禁止使用的变量名之一
我明白这是权衡取舍,但我更倾向于希望编程语言强制要求使用
this或self表示成员/属性。C++
foo和bar是局部变量还是某个实例的成员?
vs
Python
100%清晰。无需命名约定。
提出此议题是因为:若语言强制要求使用
self或this,则成员采用_foo命名约定便毫无必要。话虽如此,我明白将独立函数重构为类方法或许更容易——毕竟无需大幅修改代码——但我很好奇这种做法究竟能带来多少净收益。
从语言设计角度看,这同样表明(对C++的简单修改)
比(我认为)
更具可读性。
不如干脆始终显式写出隐含的“this”参数。这样所有方法都会像普通函数一样呈现,既能简化语言语法和标准规范,使其更简洁一致,又不牺牲任何功能性。
你可能会喜欢“推断this”提案:http://wg21.link/P0847
(请滚动至“建议语法”部分)
这可以双向实现吗?
我赞同函数不应特殊化的观点,因此
本质上只是
的语法糖,且第一个参数可传入任何符合条件的值。
但遵循“语法糖无害”原则时
这不就是语法糖形式的
…或者类似的写法吗?
书写符合C++惯例的代码时,最终往往还是会用到impl->foo这类写法。
Pimpl模式某种程度上是编译器工作机制的产物,但它通常能成为结构化代码的巧妙方案。
这要视具体情况而定。我今天用了PImpl,但这实属罕见例外。在可内联的小类与抽象基类之间,存在多种实现方式。但这正是C++的魅力所在:解决问题的方式永远不止一种!
我在上一份工作中接触过C++,现在又和搭档在副业项目中使用。最让我抓狂的就是那些不使用
this的人。深有同感。
尤其在C中,遵守下划线命名规则至关重要——因为标准库大量采用纯头文件设计,意味着大量内联代码会暴露在标识符冲突风险中。例如若你将
foo定义为123,而某个内联函数中有局部变量名为“foo”,就会引发问题。正因如此,在多数实现中查看标准C头文件时,所有标识符(包括局部变量)都倾向于采用_Like __this命名模式。标准库还可能需要定义自身的内部宏(因存在大量重复语法),这些宏同样遵循此命名规范。因此若忽视这些保留名,程序或许能编译通过,但即使实现中微小的更新(例如某个冷门标准函数新增局部变量)也可能导致崩溃,更不用说C++标准的新版本了。
我曾试图解读所有围绕保留标识符的规则,结果发现意外地棘手。
https://gist.github.com/chjj/d0c1218e473bbb6d8f9e2224c583e2d…
“C语言竟会保留strong、island、together这类标识符,这或许令人惊讶,但事实确是如此。”
是的,我猜想多数C程序员并不熟悉这些规则。是否有办法让GCC或LLVM对此发出警告?
clang最近新增了
-Wreserved-identifier选项,我记得是在v14或v15版本。具体名称可能略有出入,但确实存在。不确定GCC是否支持GCC的这个漏洞存在已有11年之久:https://gcc.gnu.org/bugzilla/show_bug.cgi?id=51437
强有力的证据表明这些规则实际上无关紧要,可以忽略不计。
当然!我写C语言已有40年,却不知道“total”这类无害标识符竟是保留字。
我的意思是,实际上,如果Windows都做不好,编译器就算开始强制执行这些规则,至少也会提供“忽略此项”的选项。虽然Raymond Chen了解Windows并能对此发表见解,但我敢打赌Linux内核也存在大量违规情况,本质上是一样的——无论哪个C标准委员会说什么,未来的C编译器都不会让这些规则失效。
更准确的说法是“自行承担风险忽略它们”
问题不在于GCC/Clang,而在于开发者
若你在代码中定义了strfoom,而C标准委员会后来决定将其加入string.h,你就面临名称冲突的风险
问题不在开发者,而在于禁止使用[a-z].*、str[a-z].*等模式。谁会对编程语言做出这种事?
保留这些名称是个愚蠢的决定,它通过任意禁止许多与预期功能毫无关联的常用词汇,破坏了语言的可用性。即便你不直接导出这类名称,你的库名或公司名(作为所有导出名称的前缀)也可能恰巧以这些常用组合开头,因此现在你不得不避开某些库名或公司名。
若这种限制始于C11标准,我更感困惑——1970年代语言尚处萌芽期且资源受限尚可理解,但2011年仍如此设计完全不合逻辑。
但愿这仅限于C11标准,绝不会出现在C++中。
根本问题在于C语言缺乏命名空间,导致命名冲突不可避免且难以处理
C语言甚至无需命名空间就能解决这个问题,只需为标准库函数和类型添加stdc_前缀即可(参见C23标准库的stdbit.h,希望这不会是个特例)。
完善的命名空间支持导入功能,这样就不必每次都添加命名空间前缀。
没错,但我们不能直接移植C命名空间,因为这需要符号名称修饰机制。C语言可以采用“命名空间前缀”方案,例如’usingprefix stdc_’,这样既无需修改符号格式,又能实现C命名空间的大部分功能。
对于 memcpy 或 strcmp 这样基础的操作,这种写法很快就会变得非常丑陋。
C23 技术上必须支持属性命名空间。值得关注的是这些特性是否会被纳入核心语言。
为引入新标识符,他们还应保留哪些命名空间?否则新函数将不得不采用*__std_c__strfoo()*这类冗长形式。
可采取以下方案:
– 采用比“is”、‘to’、“str”更冷门的字母组合——这些词首在自然语言中过于常见。况且当需要添加无法用这些前缀命名的新功能时,这些前缀本身有何实际意义?
– 采用双下划线开头(根据文章所述该前缀已被保留)
-采用stdc_作为前缀
或通过链接器引入__newfunction机制,同时新增可选头文件定义短名。这正是C99中_Bool/bool(该处采用typedef)的解决方案,据我所知运行良好。
宏方案的弊端在于,当包含该头文件时,静态符号和结构体成员等也会被禁用。对于bool而言尚可接受,因其本就是可选关键词且头文件为新增内容;但若对所有函数及现有头文件都采用此方案,则可能破坏更多代码。
诸如“isalpha”、“tolower”和“strlen”这类函数诞生于C语言标准化之前,开发者只能基于现有资源进行适配。
我真心讨厌所有语言中带前缀下划线的命名方式。
stc_这类前缀才是正确选择。
坦白说,若C标准委员会能为新加入的标准库函数添加前缀(如C23 stdbit.h中的stdc_popcount、stdc_bit_width等),会合理得多。
> 更准确的说法是“忽视风险自负”
我认为编译器更新导致现有代码因“错误”变量名而失效,本质上属于编译器缺陷——即便该代码确实违反规范。如今才启用四十年前预留的关键字,规范制定已然为时过晚。
事实上他们引入新名称时一直很谨慎,避免破坏现有代码。例如最终引入bool类型时,特意命名为_Bool以避免与非标准bool类型冲突。开发者需要包含
<stdbool.h>才能获得友好的“bool”名称。_Complex的命名逻辑与此类似。
按此逻辑推演,C标准库将永远无法新增任何函数(或宏、结构体等)。
在合理范围内确实如此。比如若他们新增“island”函数导致我的地理软件崩溃,这显然是规范问题而非我的过错——尽管技术上我确实违反了规范。我甚至认为任何“is.*”函数在当前阶段都已错过规范修订时机。
> 我甚至认为任何“is.*”函数在当前阶段都已错过规范修订时机。
我希望看到isualpha()、isudigit()、isuncter()、isuspace()、isugraph()等函数,以及isucombining()。它们将补充iswxxx()系列,但需满足:(a) 接受
带符号Unicode整数(C2x标准定义为至少32位宽)参数,(b) 实现区域设置无关性。此外,clang-tidy 还提供了
bugprone-reserved-identifierhttps://clang.llvm.org/extra/clang-tidy/checks/bugprone/rese…该检查仅针对以下情况:以下划线开头的保留名。
> 此检查(目前)不涵盖其他保留名,例如与语言关键字相同的宏名,以及语言标准特有的保留名(如C++的“僵尸名”和C语言未来库方向)。
它会对以下代码发出警告:
该定义有时需置于#include前,以便调用线程安全的现代化库函数。
写了三十多年C语言,这是我第一次听说。不知自己无意中违反过多少次这类规则。
昨晚我(用C++)就因此吃过亏,完全不知道有这回事。这帖子来得真及时!
很想听听更多相关细节!
我在Dave’s Garage的YouTube节目里常听到Dave谈论Raymond,感觉这位真是传奇人物。
没错,Raymond是传奇,深入挖掘他的博客存档绝对值得。
(不过Dave的讲解风格实在令人不适,被过分高估了。)
真的,彻底避开下划线吧——它们糟透了。就算知道有排除规则的人,也搞不清具体规则。一旦用错,编译器给的错误信息根本看不懂。所以别用——谁会用这种东西?
我从未见过类名开头带下划线的情况。见过尾随下划线和老式的m_前缀,但纯粹的_从未有过。
C11新增的保留前缀让我颇感意外。现在我也在思考是否存在clang/gcc选项能对此类情况发出警告——虽然当前代码库中不存在问题(能编译运行),但我实在不愿发布公共API后又因C29之类的冲突而被迫重构。
前缀下划线能区分字段
_name与成员函数name,Python也有类似机制。若不采用这种方式,难道不是更混乱吗?m_真的更优吗?(诚恳提问)正如你回复的评论所提:使用尾随下划线。确实:由于前缀下划线已被保留,且保留该符号有合理依据,若你坚持拒绝使用尾随修饰符,m_ 确实优于 _。
我不会为此大做文章,但将变量作用域置于开头更符合我的逻辑。毕竟 foo.、foo-> 和 foo[] 都是放在开头的。
前缀下划线仅在后续字母为大写时保留。况且C++代码中普遍存在强制字段首字母小写的编码规范。
某些编码规范采用大小写区分(如成员变量’name’与获取器’Name()’)——不过我个人更倾向蛇形命名法_case。
我们公司采用`m_`命名法,我逐渐体会到其价值。这种写法极大提升了代码可读性——凡是`m_`前缀的变量必属类成员字段,其余则为函数参数、局部变量或特殊前缀(如`k`表示静态常量)。
考虑到我们阅读代码的时间远多于编写代码,在符号名称中添加这类“用法提示”能大幅减轻认知负担,效果远超预期。
我认为使用m_或s_作为前缀并非坏事,但标识符存储类型的视觉提示(颜色、粗体、斜体等)应由IDE提供。
自ANSI C起,某些下划线已在用户代码特定场景中被保留——根本无需使用它们。尾随下划线虽可行,但何必费心?它们既难读又难输入。
尾随下划线是我解决关键字冲突的首选方案。比起随意拼写或使用关键词同义词(斜眼瞥向
klazz),这种规则更具一致性且易于记忆。完全无法理解——为何要用关键词作为名称?而且评论最后部分完全不合逻辑。
若在C++中实现持久化或反射系统,’Class* clazz’其实不算罕见。
或许你在开发游戏,角色拥有…职业?
下划线究竟有何特别之处使其具备可区分性?
所以C语言确实预先保留了某些关键词?比如island、strong、together…
不知这种做法在某些情况下是否奏效?或者换个问法:若现在设计新编程语言,你会考虑预先保留关键词吗?
我是编程语言设计师。
我正在设计一种语言,确实会预留关键词——因为需要兼容C语言的ABI接口。但我也让这些关键词更容易规避。
以下是我的保留词列表:
* 以 `y_` 开头的任何词。
* 以 `yc_` 开头的词。
* 以 `YC_` 开头的词。
* 包含三个及以上连续下划线的词。
* 编辑补充:所有以下划线开头的词。这是因为我的语言必要时可转译为C语言。
第一类用于标准库中的类型和项(语言名为Yao,故
y具有特殊含义)。第二、三类分别用于C ABI(故yc)及历史兼容性。特别是YC_用于C宏。最后一个用于名称“修饰”。之所以加引号,是因为本语言的标准名称修饰机制(所有实现中保持一致)并非真正修饰名称,而是采用拼接方式:包名之间用五个下划线连接,包与包内元素之间用四个下划线连接,元素与其后缀之间用三个下划线连接。(对于重载函数,程序员需为每个重载定义专属后缀。该后缀即构成其在C ABI中的名称差异。)
我希望这些规则不会过于繁琐。保留前缀的使用频率不高,且未见有人连续使用多个下划线——尽管我额外允许使用一个下划线,以防万一。
遗憾的是POSIX未采用类似的保留规范,例如为命名空间添加psx_后缀。但考虑到POSIX的初衷是将成熟的*NIX规范纳入标准,以避免引发重大冲突,这种做法或许更易获得共识。
我认为‘y_’规则过于严苛。编写数值计算代码时(如游戏或物理模拟),常需声明大量变量如y_1或y_ans。
这规则看似严苛,但需澄清:这些规范仅适用于C语言ABI。
在纯Yao环境中声明此类变量实际上不会冲突。访问C符号函数和类型的机制是专门设计的,其差异性正是为此目的而存在。
啊,若仅限于C ABI就合理多了。不过我仍可能看到有人在编写数值算法时将 y_* 用作参数之一,尽管概率要小得多。
确实如此,因此我需要进一步澄清。
限制并非针对 `y[c]_`,而是针对 `y[c]___`。
这是因为
y是标准库的包名,而标准库名称始终通过3个或更多下划线与其余部分分隔。实际上,限制在于C语言名称中连续出现3个或更多下划线的情况,因此包名不能是
y、yc或YC。对于造成的困惑我深表歉意。最初发帖时因赶时间且使用移动设备操作。
新编程语言通常支持命名空间机制,可避免此类问题。
至于收益,新版C标准通常会引入符合这些命名模式的新函数和宏,同时确保遵守保留名规则的客户端代码不受影响。
若在新语言中保留某个名称,理应将其定义为错误使用。
我毫不犹豫会将island、strong或together用作变量名,尽管它们技术上属于“保留”词。或许应避免使用“strong”,该词正处于被列为保留字的边缘。但应避免使用“isnull”、“strsplit”或“toint”这类变量名。不过“isNull”、“strSplit”和“toInt”仍可接受。
我认为预先保留关键词的理念是好的,但不应轻易干扰常用词汇。其核心在于未来添加新关键词时,不会破坏当前使用该关键词的代码。
ES5曾有“未来保留词”列表,包括class、const、export、import和let。
ES5的案例颇具趣味性,因为该“未来保留字”列表中的多数词汇,实为ES4“失落版本”的保留字清单。该清单还包含至今未被采用的有趣特性,如private、public、abstract、package、byte、int、volatile、synchronized等。
值得一提的是,尽管“private”早已被保留为关键字,但TC-39在几年前为类添加私有字段时,最终选择了“哈希名称”而非“private”关键字。
而非:
这段争论颇有意思。
Java将goto和const设为保留关键字。来源:https://docs.oracle.com/javase/tutorial/java/nutsandbolts/_k…
C语言最初将
entry设为保留词(源自Fortran 77,该语言允许函数拥有多个入口点)。这是预先保留特定前缀的做法。“is”用于任何返回真/假的函数(导致与“island”、“israel”、“isaac”冲突)。“str”用于任何字符串函数(导致与“strong”、‘strepthroat’、“strange”冲突)。
他未指出名称中出现双下划线的位置是任意位置,而不仅限于开头。
此外,在实现头文件中(即使是非标准头文件),允许使用以下形式:开头下划线后接大写字母或其他保留名称。这种做法之所以被视为不良习惯,仅因其他编译器(如Clang)可能在未来读取这些头文件时,会为其赋予自定义含义。
据我所知,C++中仅保留名称中任意位置的双下划线组合,而C语言仅保留以双下划线开头的名称。诚然,使用此类标识符可能不会出问题,但你几乎永远无法确保绝对安全。
微软可以绝对、彻底、无可辩驳地确信,在其自身实现中使用实现保留名称是安全的。值得注意的是,某些头文件不属于实现范畴,因为它们并非随MSVS附带。但这属于包装问题,标准规范并未涵盖。
此外,此处仅讨论C++。微软从未重视C语言,任何在C中保留的名称在C++中同样保留。
赞
若雷蒙德·陈在微软的唯一职责就是写博客,那他的薪水绝对物有所值。他的博客始终保持着极高的水准,持续更新多年,如此高频产出令我产生冒名顶替症候群——实在难以想象他如何还能兼顾本职工作。
但愿微软能多些雷蒙德·陈这样的员工,少些…那些做出“预装糖果粉碎传奇”、“再次破坏开始菜单”决策的人。Windows内核本具优雅精髓,可惜堆砌其上的高层架构实在糟糕透顶。
NT是个设计精妙的操作系统。真好奇微软内部还有多少人真正理解它。听说苹果现在都难觅能做内核开发的工程师。
我在苹果从事视频系统开发时,因多次将他们的内核与Linux作负面比较而被绩效考核扣分。我敢肯定他们至今仍用着狗屎般的I/O调度器,不过我好久没用Mac了。
我怀疑问题不在于工程师能力不足,而在于苹果的部门壁垒导致现有工程师既不能尝试改进,甚至不能讨论此事。
> 因在绩效评估中贬低其内核而受批评…工程师们甚至不被允许尝试或讨论此事
我怀疑问题可能不在于你比较了内核,而在于你表达比较的方式。比如这段话让我觉得你可能用对抗性语气表达了观点:
> 狗屎般的IO调度器
或许你日常交流更得体些,我不得而知。但此处的措辞确实令人存疑。
你似乎从一句措辞过度推演,但事实是:苹果内核虽堪用,除dtrace支持外,其他方面绝非顶尖水平。
所以抱歉我的尖刻言辞冒犯了你,但证据表明被苹果忽视的绝非我一人。
有些人似乎没意识到,问题往往出在表达方式而非表达内容本身
你对一个相当温和的问题(假设对方是个人情绪而非沟通问题)的回应方式,恰恰印证了这种观点的合理性。
我认为这绝非温和——他们几乎在暗示我是职场混蛋,只因多年后对某个形容词不满。
措辞或许委婉,但实质陈述充满冒犯性、自以为是且虚伪做作。
你根本没冒犯我。
这就是所谓“因果报应谬误”。
https://en.wikipedia.org/wiki/Just-world_hypothesis
更像是故事的一面 🙂
https://www.collinsdictionary.com/us/dictionary/english/some…
公平地说,所有轶事都只是故事的一面 🙂
这很有意思,有没有基准测试能证明Mac调度程序的劣势?(当然不能让你违反保密协议)
如今我们不再使用寻道速度慢的机械硬盘,这点差异已不那么重要了。
对于Final Cut/iMovie这类包含大量视频/音频/杂项轨道的软件,由于缺乏调校手段,读取本应线性的数据流时,愚蠢的寻道操作很容易就让硬盘饱和。
据我所知Dave Cutler仍在职,但已调离Windows团队——先去了Xbox部门,后来可能转入云计算领域?
现存知名人物大多已转入Azure或开发部门(据我所知该部门现也归属Azure)。
这很可能是所有桌面框架之间爆发GUI内战的根源。
“被调离”强烈暗示并非其主动选择。卡特勒在Xbox团队攻克了若干尖端的虚拟化难题,并将相关技术专长带入Azure。
此类案例比比皆是,但早已一去不复返的是——当年负责Azure网络模块的工程师还能自由参与Windows开发的时代。部门壁垒本无不可,但当它们演变成象牙塔时便令人痛心。可悲的是,这种现代管理模式如今已蔓延至几乎所有企业。
这本书刚出版时我就拥有了,作为资深Unix背景者,它实在精彩绝伦。
《深入Windows NT》(微软出版社)
https://a.co/d/1lxwnQt
你似乎没理解微软的处境。
首先,《糖果粉碎传奇》从未预装在系统中。预装的只是微软商店的购买链接,用户只需点击两次即可移除。
其次,预装该链接使全球Windows系统的恶意软件感染率显著降低。
微软有责任保护需要帮助的用户。找到一个折中方案——让其他用户最多只需多点两下——已经相当不错了。
《糖果粉碎传奇》链接如何降低恶意软件感染率?
顺带一提,这个链接在我笔记本上反复出现(但奇怪的是台式机没有)。
> 第二,预装该链接使全球Windows系统恶意软件感染率显著下降。
为什么?因为用户会盗版游戏?还是说人们本来就会下载病毒游戏?
若想建立僵尸网络,把恶意软件捆绑在低端游戏里,再免费上传可执行文件到网上,这确实是个不错的开端
依据何在?为什么不捆绑《堡垒之夜》和《英雄联盟》?
没有这堆东西,很多人就没事可做了,奖金理由清单上就没法写了。
他总能完美平衡趣味性、基础性和精准度。感谢这些文章,每次都是下意识就点开 🙂
微软每年都要搞砸他博客的所有链接,所以旧文章链接永远无法正常访问。讽刺的是,这个讨论向后兼容性的博客却总在更换网址
90年代他还在Usenet论坛解答Windows编程问题。
雷蒙德·陈堪称Windows开发领域的元老。
对我而言查尔斯·佩佐尔德才是标杆:
http://www.charlespetzold.com/pw5/
还有迈克尔·卡普兰,他同样拥有极具深度的博客“Sorting it all out”,深入探讨Windows本地化、文本编码、键盘布局等议题。事实上,雷蒙德·陈曾专门推荐过他在这些领域的见解:
https://devblogs.microsoft.com/oldnewthing/20041217-00/?p=36…
遗憾的是,微软最终并未善待他[1]。雪上加霜的是,他的博客被彻底清空。虽然存在部分存档,但尚未发现完整保留图片的版本——这往往导致博文内容难以理解,实在可惜。
[1] https://vsubhash.wordpress.com/2017/04/17/rip-michael-j-kapl…
他与Russinovich——在后者加入微软之前。
“之前” 🙂
嗯,我想正职工作才是博客如此出色的原因吧。
而且每当我有疑问时,感觉他总能给出答案。无论问题多么具体。