我已经看到了很多这方面的问题,但是如果没有具体的代码,我会以不同的方式提出问题.有没有一种方法可以轻松确定导致类型不完整的原因?在我的情况下,我正在使用别人的代码,我完全确定我没有正确的标题,但是(因为计算机比人类的眼球更快更好地完成这个东西)有没有办法让编译器说出来,"嘿,你认为你在第34行有X型,但实际上已经失踪了." 错误本身仅在您分配时显示,这不是很有帮助.
我想将一个相同的结构复制到另一个结构中,然后将其用作第一个结构的比较.问题是,当我这样做时,我的编译器给了我一个警告!我应该以其他方式做到这一点还是我做错了:
在标题文件中:
extern struct RTCclk
{
uint8_t second;
uint8_t minute;
uint8_t hour;
uint8_t mday;
uint8_t month;
uint8_t year;
}
RTCclk;
Run Code Online (Sandbox Code Playgroud)
在C文件中:
struct RTCclk RTCclk;
struct RTCclk RTCclkBuffert;
void FunctionDO(void)
{
... // Some Code
/* Copy first struct values into the second one */
memcpy(&RTCclk, &RTCclkBuffert, sizeof RTCclk);
}
Run Code Online (Sandbox Code Playgroud) 我最近遇到了一个同事的代码,看起来像这样:
typedef struct A {
int x;
}A;
typedef struct B {
A a;
int d;
}B;
void fn(){
B *b;
((A*)b)->x = 10;
}
Run Code Online (Sandbox Code Playgroud)
他的解释是,因为它struct A是第一个成员struct B,所以b->x会b->a.x提供更好的可读性.
这是有道理的,但这被认为是好的做法吗?这会跨平台工作吗?目前这在GCC上运行良好.
static struct ctl_table ip_ct_sysctl_table[] = {
{
.procname = "ip_conntrack_max",
.maxlen = sizeof(int),
.mode = 0644,
.proc_handler = proc_dointvec,
},
// ...
{
.procname = "ip_conntrack_log_invalid",
.maxlen = sizeof(unsigned int),
.mode = 0644,
.proc_handler = proc_dointvec_minmax,
.extra1 = &log_invalid_proto_min,
.extra2 = &log_invalid_proto_max,
},
{ }
};
Run Code Online (Sandbox Code Playgroud)
这里的结构数组以{ }. 添加的目的是什么?
顺便说一句,在这段代码上方有另一个structs 数组,但最后没有空大括号。
什么时候应该在结构数组的末尾使用空大括号?
我刚刚开始工作的另一个代码库,开发人员在复制/比较/设置时始终使用结构的第一个元素的地址,而不是结构本身.这是一个简单的例子.
首先是结构类型:
typedef struct {
int a;
int b;
} foo_t;
Run Code Online (Sandbox Code Playgroud)
然后有一个函数可以复制这样的结构:
void bar(foo_t *inp)
{
foo_t l;
...
memcpy(&l.a, &inp->a, sizeof(foo_t));
...
}
Run Code Online (Sandbox Code Playgroud)
我不会以memcpy这种方式写一个调用,我开始怀疑原始开发人员根本没有完全掌握C中的指针和结构.但是,现在我已经在两个不相关的代码库中看到了这个,没有普通开发人员所以我开始怀疑自己.
为什么要使用这种风格?
这是声明不可变结构的正确方法吗?
public struct Pair
{
public readonly int x;
public readonly int y;
// Constructor and stuff
}
Run Code Online (Sandbox Code Playgroud)
我想不出为什么这会遇到问题,但我只想问一下.
在这个例子中,我使用了int.如果我使用了一个类,但该类也是不可变的,就像这样呢?这应该也可以正常工作,对吧?
public struct Pair
{
public readonly (immutableClass) x;
public readonly (immutableClass) y;
// Constructor and stuff
}
Run Code Online (Sandbox Code Playgroud)
(旁白:据我所知,使用性能更加普及,并允许改变,但这种结构的目的是从字面上只存储两个值我在永恒的问题只是有兴趣在这里.)
我已经找到了结构的最重要的指导方针,但我能找到的只是课程.
起初我以为我不必检查传递的对象是否为null,因为结构是值类型而不能为null.但是现在我开始想起它,就像平等签名一样
public bool Equals(object obj)
Run Code Online (Sandbox Code Playgroud)
似乎没有什么能阻止我的struct的用户尝试将它与任意引用类型进行比较.
我的第二点涉及在我比较我的结构中的私有字段之前我想(我想)必须做的转换.我该如何将对象强制转换为struct的类型?C#的as关键字似乎只适用于引用类型.
有些人不知道可以通过C中的值传递和返回结构.我的问题是关于编译器在C中返回结构时制作不必要的副本.诸如GCC之类的C编译器是使用返回值优化(RVO)优化还是仅仅是C++概念?我读过的关于RVO和copy elision的所有内容都与C++有关.
让我们考虑一个例子.我目前正在用C 实现一个双重数据类型(或者更确切地说是float-float,因为我觉得它很容易进行单元测试).请考虑以下代码.
typedef struct {
float hi;
float lo;
} doublefloat;
doublefloat quick_two_sum(float a, float b) {
float s = a + b;
float e = b - (s - a);
return (doublefloat){s, e};
}
Run Code Online (Sandbox Code Playgroud)
编译器是否会复制doublefloat我返回的值,还是可以省略临时副本?
在C中命名的返回值优化(NRVO)怎么样?我有另一个功能
doublefloat df64_add(doublefloat a, doublefloat b) {
doublefloat s, t;
s = two_sum(a.hi, b.hi);
t = two_sum(a.lo, b.lo);
s.lo += t.hi;
s = quick_two_sum(s.hi, s.lo);
s.lo += t.lo;
s = quick_two_sum(s.hi, s.lo);
return s; …Run Code Online (Sandbox Code Playgroud) OK,这是没有严重的后果,但它被窃听我一会:有没有为区分的理由->和.运营商?
当然,当前的规则是.作用于结构,并->作用于指向结构(或联合)的指针.但这是它在实践中的运作方式.让我们s成为包含元素的结构x,让它ps成为指向同一形式的结构的指针.
如果你写
s->x
Run Code Online (Sandbox Code Playgroud)
编译器会以这种方式吐出警告
你的意思是sx请重新输入并重新编译.
如果你写
ps.x
Run Code Online (Sandbox Code Playgroud)
编译器会以这种方式吐出警告
你的意思是ps-> x.请重新输入并重新编译.
因为编译器知道两者的类型s并且ps在编译时,它具有解释正确运算符所需的所有信息.我怀疑这不像其他警告(如缺少分号),因为没有关于正确修复的含糊不清.
所以这是对C1x标准委员会的一个假设性提议(由于ISO处于保守状态,因此永远不会被考虑):
给定表达式lhs.rhs,如果lhs是结构或联合类型,则表达式应引用名为rhs的lhs元素.如果lhs是指向结构或-union的类型,则应将其解释为(*lhs).rhs.
这肯定会拯救我们所有的时间,并且让人们更容易学习C [并且我已经教过足够的C来说明学习者发现->事情要么令人困惑或烦恼.]
甚至有先例,C做了一些类似的事情.例如,对于实现的原因,函数声明总是被转换为指针到功能,所以f(x,y)和(*f)(x,y)将两者的工作,无论是否f被宣布为一个函数或函数指针.
所以,我的问题是:这个提案有什么问题?你能想到的例子,其中会有致命之间的歧义ps.x和s.x,或者为什么保持强制区别,否则有用吗?
struct ×10
c ×7
c# ×2
arrays ×1
c++ ×1
copy ×1
copy-elision ×1
dereference ×1
equals ×1
go ×1
immutability ×1
linux-kernel ×1
microchip ×1
overriding ×1
string ×1
typedef ×1