小编Phi*_*lip的帖子

在功能结束时跳转到清理时,GOTO被认为是无害的吗?

goto在几个SO讨论中已经对这个声明进行了长时间的讨论(见这个那个),我当然不想重振那些激烈的辩论.

相反,我想专注于gotos 的单个用例并讨论它的价值和可能的替代方案.

请考虑以下代码片段,这在(至少我自己的)FSM中很常见:

while (state = next_state()) {
        switch (state) {
                case foo:
                        /* handle foo, and finally: */
                        if (error) goto cleanup;
                        break;
                case bar:
                        /* handle bar, and finally: */
                        if (error) goto cleanup;
                        break;
                /* ...other cases... */
        }
}

return ok;

cleanup:
/* do some cleanup, i.e. free() local heap requests, adjust global state, and then: */
return error;
Run Code Online (Sandbox Code Playgroud)

在一个单独的函数中交换清理东西只是为了保存gotos似乎很尴尬.另一方面,我们已经被提出来谴责goto尽可能使用s.

我的问题:我的代码示例被认为是好风格吗?
如果没有,是否有可行的替代方案?

请坚持上述具体用法goto …

c coding-style goto

20
推荐指数
4
解决办法
3310
查看次数

按顺序读取内存:"signed char*"vs"unsigned char*"

人们经常需要一次一个字节地读取内存,就像在这个天真的memcpy()实现中一样:

void *memcpy(void *dest, const void *src, size_t n)
{
    char *from = (char *)src;
    char *to   = (char *)dest;

    while(n--) *to++ = *from++;

    return dest;
}
Run Code Online (Sandbox Code Playgroud)

但是,我有时会看到人们明确使用unsigned char *而不仅仅是char *.

当然,charunsigned char可能不相等.但这是否有所作为我是否使用char *,signed char *unsigned char *当按字节读取/写入内存?

更新:实际上,我完全清楚c=200可能有不同的值,具体取决于类型c.我在这里问的是为什么人们有时会使用unsigned char *而不是仅仅char *在阅读记忆时,例如为了存储uint32_t一个char[4].

c c++ coding-style char unsigned-char

17
推荐指数
2
解决办法
6199
查看次数

为什么malloc(0)的返回值是实现定义的?

ISO/IEC 9899:TC2(即C99标准),§7.20.3规定:

如果请求的空间大小为零,则行为是实现定义的:返回空指针,或者行为就像大小是非零值一样,但返回的指针不应用于访问对象.

换句话说,malloc(0)可以返回NULL或有效指针,我可能不会取消引用.

这种行为背后的理由是什么?
并且定义malloc(0)导致UB不是更容易吗?

c c++ malloc memory-management

16
推荐指数
3
解决办法
834
查看次数

我们应该使用poll()还是select()?

我充分意识到之间的主要差异poll()select():

  • select() 仅支持固定数量的文件描述符
  • select() 据说在更多系统上支持
  • poll() 允许对事件类型进行稍微细粒度的控制
  • poll() 实现在某些细节上可能不同

但是,它们都以大致相同的方式完成相同的任务.所以:

我们要用poll()还是select()


编辑:我可能会补充一点,我不感兴趣,epoll()因为可移植性是我关注的问题.此外,libev(ent)也不是一个选项,因为我问这个问题,因为我正在编写自己的替换库libev(ent).

c c++ networking posix network-programming

15
推荐指数
3
解决办法
9437
查看次数

为什么size_t当int足以满足数组的大小?

C标准保证int能够存储每个可能的数组大小.至少,这是我从阅读§6.5.2.1,第1小节(数组下标约束)中理解的内容:

其中一个表达式应具有类型''指向对象类型的指针'',另一个表达式应具有整数类型,结果具有类型''type''.

既然我们将ints用作数组下标,为什么我们应该用它size_t来确定数组的大小?

为什么strlen()回报size_t什么时候int就够了?

c int standards size-t

13
推荐指数
2
解决办法
6458
查看次数

为什么"typedef struct foo foo;" 认为有害吗?

C vs C++中的typedef和struct命名空间中,其中一条注释似乎意味着暴露某些注释struct foo优于使用typedef ...

typedef struct foo foo;
Run Code Online (Sandbox Code Playgroud)

...然后使用foo而不是struct foo整个API.

后一种变体有任何缺点吗?

c coding-style

12
推荐指数
3
解决办法
5225
查看次数

论未定义的行为

一般来说,UB被认为是必须避免的东西,目前的C标准本身列出了附录J中的不少例子.

但是,在某些情况下,除了牺牲可移植性之外,我认为开发UB没有任何害处.

考虑以下定义:

int a = INT_MAX + 1;
Run Code Online (Sandbox Code Playgroud)

评估此表达式会导致UB.但是,如果我的程序打算在32位CPU上运行,模块化算术代表二进制补码中的值,我倾向于相信我可以预测结果.

在我看来,UB有时只是C标准告诉我的方式:"我希望你知道你在做什么,因为我们无法保证会发生什么."

因此我的问题是:即使C标准认为它可以调用UB,或者"UB"真的要避免,无论情况如何,有时依赖依赖于机器的行为是否安全?

c undefined-behavior

11
推荐指数
2
解决办法
921
查看次数

为什么sizeof(void)== 1?

可能重复:
空白的大小是多少?

在§6.2.5.19中,先知让我们知道:

void类型包含一组空值

那么为什么sizeof(void)产生1,当0似乎就足够了?

c gcc

11
推荐指数
3
解决办法
2914
查看次数

好C头样式

我的C标头通常类似于以下样式,以避免多重包含:

#ifndef <FILENAME>_H
#define <FILENAME>_H

// define public data structures / prototypes, macros etc.

#endif  /* !<FILENAME>_H */
Run Code Online (Sandbox Code Playgroud)

但是,在他的C语言编程中,Rob Pike对头文件做了如下论证:

有一个小小的舞蹈涉及#ifdef到可以防止文件被读取两次,但它在实践中通常是错误的 - #ifdef它们在文件本身,而不是包含它的文件.结果往往是成千上万的不必要的代码行通过词法分析器,这是(在良好的编译器中)最昂贵的阶段.

一方面,派克是我唯一真正钦佩的程序员.另一方面,将多个#ifdefs放在多个源文件中而不是将其#ifdef放在单个头文件中会感到不必要的尴尬.

处理多重包含问题的最佳方法是什么?

c coding-style header-files

9
推荐指数
3
解决办法
1500
查看次数

8
推荐指数
1
解决办法
2432
查看次数