来自 C17 草案 (6.3.2.3 \xc2\xb63):
\n\n\n值为 0 的整型常量表达式,或此类转换为类型的表达式
\nvoid *,称为空指针常量。67)如果将空指针常量转换为指针类型,则生成的指针(称为空指针)保证与任何对象或函数的指针比较不相等。67)该宏
\nNULL在(和其他标头)中定义<stddef.h>为空指针常量 [...]。
由此可见,以下是空指针常量:0, 0UL, (void *)0, (void *)0UL, NULL。
进一步得出以下是空指针:(int *)0, (int *)0UL, (int *)(void *)0, (int *)(void *)0UL, (int *)NULL。有趣的是,这些都不是“空指针常量”;看这里。
以下空指针常量是空指针(因为void *是指针类型,并且0和0UL是空指针常量):(void *)0 …
来自 C17 标准草案(6.3.2.1 \xc2\xb64;脚注已删除):
\n\n\n函数指示符是具有函数类型的表达式。除非它是运算
\nsizeof符或一元&运算符的操作数,否则类型为“函数返回类型”的函数指示符将转换为类型为“指向函数返回类型的指针”的表达式。
sizeof f(对于函数指示符f)是不符合标准的。_Alignof运算符。typeof操作员。结果(这里:f是函数指示符;fp是函数指针):
&f(显式)或f(短)。(&f)(args)或者f(args)fp(args)或者(*fp)(args)这里,
\n(&f)(args)/fp(args)与技术上操作函数指针的函数调用一致,并且f(args)/(*fp)(args)与函数调用对函数(而不是指向函数的指针)进行操作的天真的假设是一致的。从标准中尚不清楚strncmp(来自string.h)
int strncmp(const char *s1, const char *s2, size_t n);
Run Code Online (Sandbox Code Playgroud)
n如果其第三个参数是则应返回0。
根据C17标准草案,7.24.4.4:
该
strncmp函数比较不超过n字符(不比较空字符后面的字符)[...]。
该
strncmp函数返回一个大于、等于或小于零的整数,相应地,因为 指向的 [...] 数组s1大于、等于或小于 指向的 [...] 数组s2。
应该strncmp(s1, s2, 0)返回什么?或者标准对strncmp最后一个论点的情况保持沉默0?
我的直觉告诉我,0作为返回值最有意义:
0是最“对称”的答案(负或正返回值意味着不对称并且与未进行比较不一致)。0与假设的模型一致0,直到发现差异、n进行比较或到达字符串末尾。但上述推理是哲学性的。
似乎该标准在技术上并未声明有关此情况的任何内容。我认为如果这样会更好
0) 或对于它的价值,glibc给我0(没有警告或错误)一堆简单的测试用例,例如strncmp("abc", "def", 0)使用以下编译器标志:
-Wall -Wextra -std=c90 -pedantic
-Wall -Wextra -std=c17 …Run Code Online (Sandbox Code Playgroud) 关于已接受答案的一些评论位于本问题帖子的底部。
\n根据C标准(C17草案,6.10.3.2\xc2\xb62):
\n\n\n\n
#[the]和运算符的求值顺序##未指定。
我正在寻找一个示例,其中此评估顺序很重要,并且没有其他未定义行为的实例并且没有错误。
\n在花了一些时间处理这个问题之后,我怀疑以下方法可能有效:
\n#define PRECEDENCETEST(a, b, c) # a ## b\n\nPRECEDENCETEST(c, , d)\nRun Code Online (Sandbox Code Playgroud)\n(请注意,预处理器可以按如下方式运行:cpp或gcc -E(GCC),cl /E (MSVC);请参阅下面的可编译虚拟示例。另请注意,空宏参数仅自 C99 起才合法。)
我的问题:根据 C 标准,这实际上可以作为一个相对评估顺序#和产生合法输出的示例吗?##正如我在本文底部所解释的那样,如果我理解正确的话,答案可能取决于标准是否允许在之后使用令牌#与最初指定的令牌不同。
如果答案是“是(因为......)”,那么我们就找到了一个例子!如果答案是“不,你的例子不起作用(因为......)”,那么我稍后会想办法征求更好的例子。
\n(请注意,该标准不要求编译器对#和具有绝对相对评估顺序##运算符具有绝对相对的求值顺序。顺序可以是:从左到右、从右到左、遵循某些其他逻辑或完全随机。)
较旧的 GCC 文档(似乎最高版本为 6.5)指出:
\n\n
##该标准没有指定 \xe2\x80\x98 \xe2\x80\x99 运算符链的计算顺序,也没有#指定 \xe2\x80\x98 \xe2\x80\x99 …
c operator-precedence language-lawyer c-preprocessor token-pasting-operator
这是一个关于变量命名(或一般标识符的命名)的问题。
\n中心语(右分支)语言往往有后名词修饰语,而中心语(左分支)语言往往有前名词修饰语。修饰语包括形容词、副词、所有格代词和指示词。这是一个例子(英文翻译:“大声的音乐”):
\n一旦我们把例子拉长,我们就会发现,实际上,语言在这方面是非常不一致的,英语就是一个很好的例子。另外,根据我个人的经验,单词越短,它出现在左侧的可能性就越大(出于心理语言学解析的原因:您可以通过这种方式更早地辨别树结构)。但是,在命名由许多单词组成的长变量时,在这方面保持一致不是有好处吗?
\n这里有些例子:
\nredblackTree_leftSubtree_color(混合;自然英语)vs treeRedblack_subtreeLeft_color(一致右分支)\xe2\x80\x93 注意我如何没有将“subtree”更改为“treesub”(将其视为不可更改的词汇化块)old_bTree_order(混合;自然英语)与bTree_old_order(一致右分支)\xe2\x80\x93 在这种情况下,我没有将“bTree”更改为“treeB”myStrings_set_size(混合;自然英语)与stringsMy_set_size(一致右分支)len_median_sortedListCopy(混合;自然英语)与listSortedCopy_median_length(一致右分支)arrayIndexOutofboundsException[ ArrayIndexOutOfBoundsExceptionJava 中](混合;自然英语)vs exceptionArrayIndexOutofbounds(一致右分支)我个人非常喜欢非常严格的右分支命名。这样,我们总是从高级/抽象/一般概念到低级/具体/专业概念,即从大整体到小组成部分。不用说,这违背了英语中的自然语言用法。
\n顺便请注意,严格左分支命名的情况是,通常可以从最具体的元素猜测类型。例如,order_old_bTree几乎可以肯定是一个整数。此外,最左边的元素与当前的缩进级别很好地对齐。
关于由许多组件组成的变量/标识符的分支顺序是否有任何最佳实践或指南?
\n我浏览了非英语国家的人用英语编码的 108 个答案吗?,但我找不到任何一个解决这个方面的问题。
\n我在相应的维基百科文章中可以找到的唯一相关内容是OF 语言的 PRIME-MODIFIER-CLASS 单词方案(除了维基百科所说的之外,我对此一无所知)。
\n此站点上至少存在 2 个相关但编程语言\xe2\x80\x93 特定的问题:
\n我尝试使用正则表达式来查找由重复的双字母形成的最大长度序列,例如AABBstring 中的xAAABBBBy。
正如官方文档中所述:
、
'*'、'+'和'?'量词都是贪婪的;它们匹配尽可能多的文本。
当我使用量词时{n,},我得到一个完整的子字符串,但+仅返回部分:
import re
print(re.findall("((AA|BB){3,})", "xAAABBBBy"))
# [('AABBBB', 'BB')]
print(re.findall("((AA|BB)+)", "xAAABBBBy"))
# [('AA', 'AA'), ('BBBB', 'BB')]
Run Code Online (Sandbox Code Playgroud)
为什么{n,}比 更贪婪+?
在 C 中,默认情况下,变量和函数都在文件范围内具有外部链接。为什么extern仅变量需要关键字,而其他地方定义的函数不需要关键字?请注意,这个问题有两个方面。鉴于文件范围内的声明默认为外部链接:
extern或没有的区别?或者说,为什么客观上不需要这样的区分?extern?或者说,客观上为什么需要这样的区分?作为一个最小的示例,让我们使用以下两个源文件(tu代表“翻译单元”)。
tu1.c:
extern int i = 123;
Run Code Online (Sandbox Code Playgroud)
tu2.c:
#include <stdio.h>
extern int i;
int main(void) {
//extern int i;
++i;
printf("%d\n", i);
return 0;
}
Run Code Online (Sandbox Code Playgroud)
我们可以用 GCC 编译它们,如下所示:
gcc -c tu1.c
gcc -c tu2.c
gcc -o myprogram tu1.o tu2.o
Run Code Online (Sandbox Code Playgroud)
'i' initialized and declared 'extern'(GCC对第一个命令发出警告,因为它错误地认为extern“应该保留用于非定义声明”。我们可以安全地忽略它。)
让我们比较一下编译器对于略有不同的源代码版本的行为:
extern int i;在文件范围内tu2.c(对上述代码没有更改):ismyprogram124extern int i;in main …注意:我的问题的原始版本与编译器无关,并假设 GCC(我用来进行实验)的行为完全正确,并且匹配输入序列的非空前缀不会导致匹配失败或输入失败。事实证明(参见:C17 草案,7.21.6.2 \xc2\xb610),答案更有可能在编译器/库错误中找到,而不是在匹配的前缀的定义和正确处理的复杂性中找到。然而,为了保留问题的原始精神,我只是保守地对其进行了编辑(因此,最初的假设仍然在这篇文章的后半部分中体现出来)。
\n考虑到这一点,这篇文章所涉及的问题的一个方面仍然没有解决,即:在%4c示例(底部)中是否适合CD写入q[].
根据标准(C17 草案,6.4.4.2 \xc2\xb61),2E0(2.0) 和.5(0.5) 是有效的浮动常量,而2E和.不是。
然而,对于 GCC,scanf解析2E为 2.0,但它不会解析.为任何内容:
#include <stdio.h>\n\nint main(void) {\n float fl;\n char c;\n\n printf("Please enter a floating-point number: ");\n if (scanf("%f", &fl) == 1)\n printf("<%.2f>\\n", fl);\n if (scanf("%c", &c) == 1)\n printf("[%c]\\n", c);\n\n …Run Code Online (Sandbox Code Playgroud) 为什么按照标准不允许a++ = b;,而c[i++] = d;允许呢?
(显然,a++ = b;这是一种不好的风格,但这是一个关于仔细阅读 C 语言标准的问题。)
这是强制性的最小示例:
#include <stdio.h>
int main(void)
{
int a = 10;
int b = 20;
int i = 1;
int c[] = {30, 40};
int d = 50;
a++ = b; // error
c[i++] = d;
printf("%d\n", a); // [21]
printf("%d\n", b); // 20
printf("%d\n", i); // 2
printf("%d\n", c[0]); // 30
printf("%d\n", c[1]); // 50
printf("%d\n", d); // 50
return 0;
}
Run Code Online (Sandbox Code Playgroud)
-std=c90当使用或进行编译时,GCC …
c ×7
c-strings ×1
compiler-bug ×1
extern ×1
lvalue ×1
null-pointer ×1
python ×1
regex ×1
regex-greedy ×1
scanf ×1
strncmp ×1