我无法理解以下atoi实现代码,特别是这一行: atof
代码:
k = (k << 3) + (k << 1) + (*p) - '0';
Run Code Online (Sandbox Code Playgroud)
有人可以向我解释一下吗?
另一个问题:atoi实施算法应该是什么?
C enum声明中是否需要最后一个逗号?
即是VAL3必要后的逗号?
enum { Val1, Val2, Val3, } someEnum;
Run Code Online (Sandbox Code Playgroud)
将其留入/取出是否有任何副作用
谢谢
是O(log(log(n)))实际上只是O(log(n))当谈到时间复杂度?
你是否同意这个函数g()的时间复杂度O(log(log(n)))?
int f(int n) {
if (n <= 1)
return 0;
return f(n/2) + 1;
}
int g(int n) {
int m = f(f(n));
int i;
int x = 0;
for (i = 0; i < m; i++) {
x += i * i;
}
return m;
}
Run Code Online (Sandbox Code Playgroud) 何时应该使用以下陈述之一?
typedef struct Foo {
int a;
} Bar;
Run Code Online (Sandbox Code Playgroud)
和
typedef struct {
int a;
} Bar;
Run Code Online (Sandbox Code Playgroud)
并使用它
Bar bar1 = { 5 };
Run Code Online (Sandbox Code Playgroud)
我理解第二个是匿名结构但不确定何时应该使用另一个结构.
该gets函数首先在C99中弃用,最后在C11中删除.然而,在C库中没有直接替代它.
fgets()不是替代品,因为它不会剥离最终版本'\n',这可能在文件末尾不存在.许多程序员也错了.
有一个单行代码可以删除换行符:buf[strcspn(buf, "\n")] = '\0';但它不重要,通常需要解释.它也可能效率低下.
这会适得其反.许多初学者仍然使用,gets()因为他们的老师是蹩脚的或他们的教程已经过时.
微软提出了gets_s()许多相关的函数,但它并没有默默地截断超长行,这种约束违规的行为并不简单.
BSD和GNU libc都getline在POSIX中标准化,通过realloc... 分配或重新分配缓冲区.
教初学者关于这个混乱的最佳方法是什么?
我早就知道C中有位字段,偶尔我会用它们来定义密集的结构:
typedef struct Message_s {
unsigned int flag : 1;
unsigned int channel : 4;
unsigned int signal : 11;
} Message;
Run Code Online (Sandbox Code Playgroud)
当我阅读开源代码时,我经常会发现位掩码和位移操作,以便在手工滚动的位域中存储和检索这些信息.这是如此常见,我不认为作者不知道位字段语法,所以我想知道是否有理由通过位掩码滚动位字段并转移自己的操作而不是依赖编译器生成用于获取和设置此类位字段的代码.
采取以下措施:
int a(void) {
puts("a");
return 0;
}
int b(void) {
puts("b");
return 1;
}
int c(void) {
puts("c");
return 2;
}
int d(void) {
puts("d");
return 3;
}
Run Code Online (Sandbox Code Playgroud)
以下行为会有可预测的行为吗?
int arr[4][4][4][4];
arr[a()][b()][c()][d()] = 1;
Run Code Online (Sandbox Code Playgroud)
是否保证按这个顺序打印:
int a(void) {
puts("a");
return 0;
}
int b(void) {
puts("b");
return 1;
}
int c(void) {
puts("c");
return 2;
}
int d(void) {
puts("d");
return 3;
}
Run Code Online (Sandbox Code Playgroud)
我知道以下结构是无效的:
int i;
i = i++;
Run Code Online (Sandbox Code Playgroud)
这是因为=是一个无序运算符,因此是否首先计算i或i++是未定义的。在另一个序列点之前访问和修改单个对象是未定义的行为。
换句话说,以下内容是否有效:
int i …Run Code Online (Sandbox Code Playgroud) c arrays multidimensional-array undefined-behavior order-of-execution
C23 在函数声明符中引入了新的语义:
\n\n\n6.7.6.3 函数声明符
\n[...]
\n13\xc2\xa0\xc2\xa0\xc2\xa0对于没有参数类型列表的函数声明符:效果就像是使用由关键字 组成的参数类型列表进行声明
\nvoid。函数声明符提供函数的原型。
这似乎意味着具有空参数列表的函数定义可以等效地用()or编写(void)。
然而,该函数似乎并不能保证这种main等价性:
\n\n5.1.2.2.1 程序启动
\n程序启动时调用的函数名为
\nmain。该实现没有声明该函数的原型。它的返回类型应为int且不带参数定义:Run Code Online (Sandbox Code Playgroud)\nint main(void) { /* ... */ }\n或带有两个参数(此处称为
\nargc和argv,但可以使用任何名称,因为它们对于声明它们的函数来说是本地的):Run Code Online (Sandbox Code Playgroud)\nint main(int argc, char *argv[]) { /* ... */ }\n或等效的或以某种其他实现定义的方式。
\n
这似乎并不能保证 是 的int main() { /* ... */ }有效定义main,或者等效定义是否涵盖此变体?
我很好奇C18标准中的一句话:
两个指针比较相等当且仅当它们都是空指针,都是指向同一个对象的指针(包括指向一个对象的指针和它开头的子对象)或函数,都是指向同一数组最后一个元素之后的指针对象,或者一个是指向一个数组对象末尾的指针,另一个是指向另一个数组对象开头的指针,该对象恰好紧跟地址空间中的第一个数组对象。§ 6.5.9 6
为什么数组后面的对象必须是另一个数组?不能简单地成为与数组基类型相同类型的对象(例如int紧跟在 之后的int[])?
难怪我试过这个代码:
#include <stdio.h>
struct test { int arr[10]; int i; };
int main() {
struct test t;
int *p, *q;
p = t.arr + 10;
q = &t.i;
if (p == q)
printf("Equal pointers.");
return 0;
}
Run Code Online (Sandbox Code Playgroud)
它产生相等的指针。这种行为是否根本没有保证,只是实现定义的巧合?