今天我教了几个朋友如何使用C structs.其中一个问你是否可以struct从一个函数返回一个函数,我回答说:"不!你会返回指向动态malloc编辑struct的指针."
来自主要使用C++的人,我期望无法struct按值返回s.在C++中,您可以operator =为对象重载并完全理解为具有按值返回对象的函数.但是,在C中,你没有那个选项,所以它让我思考编译器实际上在做什么.考虑以下:
struct MyObj{
double x, y;
};
struct MyObj foo(){
struct MyObj a;
a.x = 10;
a.y = 10;
return a;
}
int main () {
struct MyObj a;
a = foo(); // This DOES work
struct b = a; // This does not work
return 0;
}
Run Code Online (Sandbox Code Playgroud)
我理解为什么struct b = a;不能工作 - 你不能operator =为你的数据类型重载.它是如何a = foo();编译罚款?这是否意味着什么struct b = …
[这是一个受到其他地方最近讨论的启发的问题,我会用它来提供答案.]
我想知道数组"衰减"指针的奇怪C现象,例如当用作函数参数时.这似乎是不安全的.用它明确地传递长度也是不方便的.我可以通过其他类型的聚合 - 结构 - 完全符合价值; 结构不会腐烂.
这个设计决定背后的理由是什么?它如何与语言集成?为什么结构有区别?
我知道在C中我可以做到以下几点.
int test[5] = {1, 2, 3, 4, 5};
Run Code Online (Sandbox Code Playgroud)
现在,这在声明数组时才合法.但是我想知道为什么以后这样做不合法?但是后来在该计划中,执行以下操作是不合法的.
test[5] = {10, 20, 30, 40, 50};
Run Code Online (Sandbox Code Playgroud)
或类似的东西.为什么是这样?我知道这不合法,我不是在抱怨,但有人可以给我一个更技术性的解释,说明为什么我不能这样做?(即不要只说C规范不允许它或类似的东西)
我假设它必须对内存在数组的堆栈上分配的时间做一些事情,所以在那一点C可以自动填充我的值,但那么为什么它不能在以后呢?
多谢你们
如果我声明两个数组 - arr1并且arr2- 例如,int每个类型大小为10,并初始化第一个数组,并且我希望创建一个arr1in 的副本arr2; 为什么我不能给出指示arr2 = arr1呢?
我知道可以分配两种相同类型的结构.为什么不是阵列的情况?
在关于C的介绍性书籍中,经常声称指针或多或少是数组.充其量只是一个巨大的简化吗?
存在是 C中的数组类型,它可以表现从指针完全不同的,例如:
#include <stdio.h>
int main(int argc, char *argv[]){
int a[10] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
int *b = a;
printf("sizeof(a) = %lu\n", sizeof(a));
printf("sizeof(b) = %lu\n", sizeof(b));
return 0;
}
Run Code Online (Sandbox Code Playgroud)
给出输出
sizeof(a) = 40
sizeof(b) = 8
Run Code Online (Sandbox Code Playgroud)
或者作为另一个例子a = b会产生编译错误(GCC:"赋值给带数组类型的表达式").
当然,指针和数组之间存在密切关系,在某种意义上,数组变量本身的内容是第一个数组元素的内存地址,例如int a[10] = {777, 1, 2, 3, 4, 5, 6, 7, 8, 9}; printf("a = %ul\n", a);打印包含777的地址.
现在,一方面,如果你在结构中"隐藏"数组,只需使用=运算符就可以轻松复制大量数据(数组,如果忽略包装结构)(这甚至也很快):
#include …Run Code Online (Sandbox Code Playgroud) 所以,我的理解是下面的代码:
somestruct_t a = {0};
somestruct_t b;
b = a;
Run Code Online (Sandbox Code Playgroud)
如果可能的话,总是优于:
somestruct_t a;
somestruct_t b;
memset(&a, 0, sizeof(a));
memcpy(&b, &a, sizeof(a));
Run Code Online (Sandbox Code Playgroud)
顶级构造几乎总是可能的......这引出了我的问题:由于顶级代码都表现良好,并且对我来说显然对于学习该语言的人来说更直观,为什么memset和memcpy模式在 C 和 中如此令人惊讶地普遍存在甚至是非 OO C++ 代码?事实上,我几十年来从事的每个项目都更喜欢底部图案。
我假设有一些历史原因,例如非常旧的编译器不支持它或类似的东西,但我非常想知道具体原因。
我知道一般历史问题是题外话,但这是关于一个非常具体的不良做法,我想更好地理解。
编辑我并不是想断言 memcpy 和 memset 一般来说是不好的。我正在谈论单个结构的赋值或初始化的非常具体的使用模式。
该代码不起作用:
int main() {
int arr1[10];
int arr2[10];
arr2 = arr1;
return 0;
}
Run Code Online (Sandbox Code Playgroud)
但这有效:
struct foo {
int arr[10];
};
int main() {
struct foo f1;
struct foo f2;
f2 = f1;
return 0;
}
Run Code Online (Sandbox Code Playgroud)
但是在我看来,它们做同样的事情:只需将一个数组复制到另一个数组。
我在问:是否可以在数组定义后执行多个赋值?我用不同的语法进行了不同的测试,但没有成功。
这是我的源代码:
#include <stdio.h>
typedef int coords[3];
int main(int argc, char **argv)
{
coords x = {1, 2, 3}; // it works
x = {1, 2, 3}; // it doesn't work. Compiler gives the 'error: expected expression before ‘{’ token'
// x = (int[3]) {1, 2, 3}; // it doesn't work. Compiler gives the 'error: assignment to expression with array type'
// x = (coords[3]) {1, 2, 3};// it doesn't work. Compiler gives the 'error: assignment to expression with array …Run Code Online (Sandbox Code Playgroud)