我以为
int a1[5];
Run Code Online (Sandbox Code Playgroud)
和
int a2[6];
Run Code Online (Sandbox Code Playgroud)
是不同的类型。
但
void foo(int a[5]){};
void foo(int a[6]){};
Run Code Online (Sandbox Code Playgroud)
不会编译,说它们是 foo 的重复定义(即foo(int *a)
)
我对此感到非常惊讶。我看到 C++ 标准中不允许 VLA 的原因之一是它们破坏了类型系统。
我也惊讶地发现 c 也在做同样的事情。
void foo(int a[4]){
printf("sz=%ld", sizeof(a));
}
Run Code Online (Sandbox Code Playgroud)
报告指针大小。我期望它报告4*sizeof(int)
(并且只接受类型变量int[4]
作为调用参数)
我正在考虑一下C编程语言,并开始想知道如何inline
与递归交互.我做了这个测试程序来找出答案.
static inline void f(void) {
f();
}
int main(void) {
f();
return 0;
}
Run Code Online (Sandbox Code Playgroud)
我使用编译程序gcc
并且根本没有警告
$ c99 -Wall -pedantic main.c -o a
Run Code Online (Sandbox Code Playgroud)
我的问题是
关于混合
inline
递归的C标准有什么用?
对我来说,不应该允许它是合乎逻辑的.
编辑:原始的单词选择令人困惑.术语"象征性"比原始术语("神秘")要好得多.
在关于我以前的C++问题的讨论中,我被告知指针是
这并没有健全的权利!如果没有任何符号,并且指针是其表示,那么我可以执行以下操作.我可以吗?
#include <stdio.h>
#include <string.h>
int main() {
int a[1] = { 0 }, *pa1 = &a[0] + 1, b = 1, *pb = &b;
if (memcmp (&pa1, &pb, sizeof pa1) == 0) {
printf ("pa1 == pb\n");
*pa1 = 2;
}
else {
printf ("pa1 != pb\n");
pa1 = &a[0]; // ensure well defined behaviour in printf
}
printf ("b = %d *pa1 = %d\n", …
Run Code Online (Sandbox Code Playgroud) 这是我在"我不理解C和C++中的指针"集合中的一个新问题.
如果我将具有相同值的两个指针的位混合(指向相同的存储器地址),那恰好具有完全相同的位表示,当一个是可解除引用且一个是结束时,标准说应该发生什么?
#include <stdio.h>
#include <string.h>
#include <assert.h>
// required: a == b
// returns a copy of both a and b into dest
// (half of the bytes of either pointers)
int *copy2to1 (int *a, int *b) {
// check input:
// not only the pointers must be equal
assert (a == b);
// also the representation must match exactly
int *dest;
size_t s = sizeof(dest);
assert(memcmp(&a, &b, s) == 0);
// copy a and b into dest:
// …
Run Code Online (Sandbox Code Playgroud) 如果我这样写:
i = i++, i, i++;
Run Code Online (Sandbox Code Playgroud)
它是C语言中未定义的行为.
但是,如果我这样写:
return i++, i, i++; // Is it UB?
Run Code Online (Sandbox Code Playgroud)
是不确定的行为?
例:
#include <stdio.h>
int f(int i)
{
return i++, i, i++; // Is it UB?
}
int main() {
int i = 1;
i = i++, i, i++;
i = f(i);
printf("%d\n",i);
return 0;
}
Run Code Online (Sandbox Code Playgroud) 与例如 C++ 的可变参数模板相比,CPP(C/C++ 预处理器;为简单起见,我将在本问题中将其视为一种单独的语言)中的可变参数宏非常有限。本质上,可变参数宏只是带有参数的宏,其参数允许包含逗号。这没有提供计算参数、一个接一个操作参数等的直接方法。这些事情是可能的,但需要精心设计、令人困惑且编译缓慢的技巧,例如本问题中描述的技巧。唯一可以直接处理的事情VA_ARGS
就是将它们传递给可变参数函数。
我的问题是,他们为什么要这样设计?在像 CPP 这样的任何纯函数式语言中,列表的标准方法是 cons 样式的模式匹配:处理列表的第一个参数并递归其余部分,并为空列表设置基本情况。标准委员会成员应该非常熟悉这种方法。
为什么 CPP 的可变参数宏没有采用这样的方法?可变参数宏是否只是一种包装可变参数函数的方法,这样就不需要对参数列表进行操作?是否存在一些潜在的问题使得允许可变参数宏递归变得不切实际?或者...?
注意:我不是在寻找“因为人们不应该想要可变参数宏”形式的答案/评论。boost.preprocessor 之类的东西的存在表明,理性的人希望以非平凡的方式使用预处理器。也不寻求关于为什么其他设计是一个好/坏主意的个人意见。我试图找出当时的实际推理。
我正在寻找一种无需定义计数器即可多次执行某些操作的语法。
例如这样:
do(10)
{
//do something
}
Run Code Online (Sandbox Code Playgroud)
其他语言有这个。是C ++的不足吗?
首先,感谢您的回答和建议。我认为在某些应用场景中,例如
我认为没有其他正常要求。多次执行一些OP的操作如此频繁,并且有理由使其更加简洁。
(为标题笨拙而道歉;我不知道如何更简洁地概括这个问题。如果有人有更好的主意,请随时进行编辑!)
我想编写一个自由函数,该函数可以基于类的成员函数的返回值自动确定其参数的类型。使用decltype
,这部分很容易。
我还希望有一个编译时断言来验证关于该参数类型的假设,这就是我提出的解决方案的地方。
考虑以下MCVE:
#include <type_traits>
#include <array>
#include <iostream>
class Foo
{
public:
std::array<int, 10> Get();
};
void PrintFoos(const decltype(Foo().Get())& param)
{
static_assert(param.size() == 10, "wrong size");
for (const auto& i : param)
{
std::cout << i << "\n";
}
}
Run Code Online (Sandbox Code Playgroud)
GCC可以很好地编译以上代码,但不会发出警告。
另一方面,lang声抓住:
error: static_assert expression is not an integral constant expression
static_assert(param.size() == 10, "wrong size");
^~~~~~~~~~~~~~~~~~
Run Code Online (Sandbox Code Playgroud)
MSVC也是如此:
(13): error C2131: expression did not evaluate to a constant
(13): note: failure was caused by …
Run Code Online (Sandbox Code Playgroud) 是((char *)NULL - (char *)NULL)
UB吗?
海事组织的答案在这里不是微不足道的。有什么想法吗?
Godbolt 实验链接https://godbolt.org/z/zgVGk9
我不是在问添加一些空指针的东西(就像在提议的欺骗中一样),而只是关于一种特殊情况。
在 Rust 中,元组可以使用点(例如:)进行索引x.0
,而数组可以使用方括号(例如:)进行索引x[0]
。乍一看,这在我看来似乎会使重构现有代码变得更加困难,而没有任何实际目的。但是,我可能只是错过了一些东西。Rust 的创建者是否曾对此发表评论并告诉我们他们为什么选择以这种方式构建语言?