我知道所有C编译器实现背后都有一个标准,所以应该没有隐藏的功能.尽管如此,我确信所有C开发人员都有他们一直使用的隐藏/秘密技巧.
我正在尝试打印类似off_t和size_t.什么是正确的占位符printf() 是可移植的?
或者是否有完全不同的方式来打印这些变量?
例:
#define FOO(...) printf(__VA_ARGS__)
#define BAR(fmt, ...) printf(fmt, __VA_ARGS__)
FOO("this works fine");
BAR("this breaks!");
Run Code Online (Sandbox Code Playgroud)
BAR()根据C99标准,上述用途确实不正确,因为它将扩展到:
printf("this breaks!",);
Run Code Online (Sandbox Code Playgroud)
请注意尾随逗号 - 不可行.
一些编译器(例如:Visual Studio 2010)将悄然摆脱那个尾随的逗号.其他编译器(例如:GCC)支持放在##前面__VA_ARGS__,如下所示:
#define BAR(fmt, ...) printf(fmt, ##__VA_ARGS__)
Run Code Online (Sandbox Code Playgroud)
但有没有符合标准的方法来获得这种行为?也许使用多个宏?
现在,该##版本似乎得到了相当好的支持(至少在我的平台上),但我真的更喜欢使用符合标准的解决方案.
先发制人:我知道我可以写一个小功能.我正在尝试使用宏来做到这一点.
编辑:以下是我想要使用BAR()的一个例子(虽然简单):
#define BAR(fmt, ...) printf(fmt "\n", ##__VA_ARGS__)
BAR("here is a log message");
BAR("here is a log message with a param: %d", 42);
Run Code Online (Sandbox Code Playgroud)
这会自动为我的BAR()日志记录语句添加换行符,假设fmt它始终是双引号C字符串.它不会将换行符打印为单独的printf(),如果日志记录是行缓冲的并且异步来自多个源,则这是有利的.
我正在按照本教程关于指针如何工作.
让我引用相关段落:
Run Code Online (Sandbox Code Playgroud)int i = 5, j = 6, k = 7; int *ip1 = &i, *ip2 = &j;现在我们可以设置
Run Code Online (Sandbox Code Playgroud)int **ipp = &ip1;并
ipp指向ip1哪些点i.*ippisip1,and**ippisi,or 5.我们可以用我们熟悉的盒子和箭头符号来说明这种情况,如下所示:
如果那时我们说
Run Code Online (Sandbox Code Playgroud)*ipp = ip2;我们已经改变了指向
ipp(即ip1)的指针以包含一个副本ip2,因此it(ip1)现在指向j:
我的问题是:为什么在第二张图片中ipp仍然指向ip1但不是ip2?
C11 标准似乎暗示不应优化带有常量控制表达式的迭代语句。我从这个答案中得到了我的建议,它特别引用了标准草案中的第 6.8.5 节:
其控制表达式不是常量表达式的迭代语句......可能会被实现假定为终止。
在该答案中,它提到while(1) ;不应进行优化之类的循环。
那么……为什么 Clang/LLVM 优化了下面的循环(用 编译cc -O2 -std=c11 test.c -o test)?
#include <stdio.h>
static void die() {
while(1)
;
}
int main() {
printf("begin\n");
die();
printf("unreachable\n");
}
Run Code Online (Sandbox Code Playgroud)
在我的机器上,这会打印出begin,然后在非法指令(ud2放置在 之后的陷阱die())上崩溃。在 Godbolt 上,我们可以看到调用puts.
让 Clang 输出无限循环是一项非常困难的任务-O2- 虽然我可以反复测试一个volatile变量,但这涉及到我不想要的内存读取。如果我做这样的事情:
#include <stdio.h>
static void die() {
while(1)
;
}
int main() {
printf("begin\n");
volatile int x …Run Code Online (Sandbox Code Playgroud) 编译器如何填充值char array[100] = {0};?它背后的魔力是什么?
我想知道内部编译器如何初始化.
在C/C++中是否有办法找到当前执行程序的位置(完整路径)?
(问题argv[0]在于它没有给出完整的路径.)
我的问题是关于我在主题中提到的那条线,我可以在生产代码中的许多地方看到.
整体代码如下所示:
if (0) {
// Empty braces
} else if (some_fn_call()) {
// actual code
} else if (some_other_fn_call()) {
// another actual code
...
} else {
// default case
}
Run Code Online (Sandbox Code Playgroud)
其他分支与我的问题无关.我想知道放在if (0)这里的含义是什么.大括号是空的,所以我认为它不应该评论一些代码块.它会强制编译器进行一些优化还是意图不同?
我试图在SO和互联网上搜索这个明确的案例,但没有成功.关于JavaScript有类似的问题,但不是C.还有另一个问题,当在`if`条件中分配零时会发生什么?,但它讨论了对变量的零赋值,而不是'if(0)'用法本身.
如何将一小段文本写入.txt文件?我一直在谷歌搜索超过3-4个小时,但无法找到如何做到这一点.
fwrite(); 有这么多论点,我不知道如何使用它.
当您只想为文件写一个名字和几个数字时,最简单的功能是什么.txt?
编辑:添加了一段我的代码.
char name;
int number;
FILE *f;
f = fopen("contacts.pcl", "a");
printf("\nNew contact name: ");
scanf("%s", &name);
printf("New contact number: ");
scanf("%i", &number);
fprintf(f, "%c\n[ %d ]\n\n", name, number);
fclose(f);
Run Code Online (Sandbox Code Playgroud) c ×10
c++ ×2
linux ×2
c99 ×1
clang ×1
if-statement ×1
path ×1
pointers ×1
portability ×1
unix ×1