相关疑难解决方法(0)

从C++迁移到C

在用C++编写了几年后,我最近在嵌入式领域的C中提供了一个编码工作.

抛开在嵌入式领域中忽略C++是对还是错的问题,C++中有一些特性/习惯用法我会错过很多.仅举几个:

  • 通用的,类型安全的数据结构(使用模板).
  • RAII.特别是在具有多个返回点的函数中,例如,不必记住在每个返回点上释放互斥锁.
  • 一般的析构函数.也就是说,你为MyClass写了一次,如果一个MyClass实例是MyOtherClass的成员,MyOtherClass就不必显式地取消初始化MyClass实例 - 它的自动调用它.
  • 命名空间.

从C++到C的经历是什么?
您找到的C替代品是您最喜欢的C++特性/习语吗?您是否发现了C++的C功能?

c c++

82
推荐指数
5
解决办法
6万
查看次数

转到标签后的变量声明

今天我发现了一件有趣的事情.我不知道在goto标签之后无法声明变量.

编译以下代码

#include <stdio.h>
int main() {
    int x = 5;
    goto JUMP;
    printf("x is : %d\n",x);
JUMP:
    int a = 0;  <=== giving me all sorts of error..
    printf("%d",a);
}
Run Code Online (Sandbox Code Playgroud)

给出错误

temp.c: In function ‘main’:
temp.c:7: error: expected expression before ‘int’
temp.c:8: error: ‘a’ undeclared (first use in this function)
temp.c:8: error: (Each undeclared identifier is reported only once
temp.c:8: error: for each function it appears in.)
Run Code Online (Sandbox Code Playgroud)

那背后的逻辑是什么?我听说无法在switch的case语句中创建变量.由于JUMP是goto语句的同一范围(主要功能的范围,在我的情况)里面,我相信,范围是不是一个问题在这里.但是,为什么我会收到此错误?

c goto variable-declaration

66
推荐指数
5
解决办法
3万
查看次数

不透明的C结构:它们应该如何声明?

我已经看到以下两种在C API中声明不透明类型的样式.使用一种风格而不是另一种风格有明显的优势吗?

选项1

// foo.h
typedef struct foo * fooRef;
void doStuff(fooRef f);

// foo.c
struct foo {
    int x;
    int y;
};
Run Code Online (Sandbox Code Playgroud)

选项2

// foo.h
typedef struct _foo foo;
void doStuff(foo *f);

// foo.c
struct _foo {
    int x;
    int y;
};
Run Code Online (Sandbox Code Playgroud)

c struct coding-style typedef opaque-pointers

46
推荐指数
2
解决办法
3万
查看次数

从C`goto`错误处理范例转换到C++异常处理范例

我是一名学习C++的C程序员.在C中,有一个常用的goto习惯用法来处理错误并从函数中干净地退出.我已经读过,在面向对象的程序中,通过try- catchblocks的异常处理是首选,但我在使用C++实现这个范例时遇到了麻烦.

以C中的以下函数为例,它使用了goto错误处理范例:

unsigned foobar(void){
    FILE *fp = fopen("blah.txt", "r");
    if(!fp){
        goto exit_fopen;
    }

    /* the blackbox function performs various
     * operations on, and otherwise modifies,
     * the state of external data structures */
    if(blackbox()){
        goto exit_blackbox;
    }

    const size_t NUM_DATUM = 42;
    unsigned long *data = malloc(NUM_DATUM*sizeof(*data));
    if(!data){
        goto exit_data;
    }

    for(size_t i = 0; i < NUM_DATUM; i++){
        char buffer[256] = "";
        if(!fgets(buffer, sizeof(buffer), fp)){
            goto exit_read;
        }

        data[i] = …
Run Code Online (Sandbox Code Playgroud)

c c++ error-handling exception-handling exception

24
推荐指数
4
解决办法
3201
查看次数

在功能结束时跳转到清理时,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
查看次数

如何在C中的每次错误检查后避免长链的免费(或删除)?

假设我非常防御地编写代码,并且总是从我调用的所有函数中检查返回类型.

所以我喜欢:

char* function() {
    char* mem = get_memory(100);  // first allocation
    if (!mem) return NULL;

    struct binder* b = get_binder('regular binder');  // second allocation
    if (!b) {
        free(mem);
        return NULL;
    }

    struct file* f = mk_file();  // third allocation
    if (!f) {
        free(mem);
        free_binder(b);
        return NULL;
    }

    // ...
}
Run Code Online (Sandbox Code Playgroud)

注意free()事情失控的速度有多快.如果某些功能失败,我必须先释放每一个分配.代码很快变得丑陋,我所做的就是复制粘贴一切.我成为了一个复制/粘贴程序员,更糟糕的是,如果有人在其间添加一个声明,他必须修改下面的所有代码来调用free()他的添加.

经验丰富的C程序员如何解决这个问题?我无法解决任何问题.

谢谢,Boda Cydo.

c memory free allocation

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

使用goto会导致内存泄漏吗?

我有一个程序,我需要打破一大堆嵌套for循环.到目前为止,大多数人告诉我这样做的方式是在我的代码中使用一个丑陋的goto.

现在,如果我创建一堆本地堆栈(我认为这就是它们被称为,如果不是,我的意思是只使用常规变量而不使用新命令)我的循环中的变量和我的程序命中一个if语句触发goto,我会遇到内存泄漏,因为我的程序不正确地退出许多循环并且没有清理局部变量?

c++ memory-leaks goto

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

有没有更好的方法来进行C风格的错误处理?

我正在尝试通过编写一个简单的解析器/编译器来学习C语言.到目前为止,它是一个非常有启发性的经验,但是来自C#的强大背景我调整了一些问题 - 特别是缺乏例外.

现在我已经阅读了Cleaner,更优雅,更难以识别,我同意该文章中的每一个字; 在我的C#代码中,我尽可能避免抛出异常,但是现在我面临着一个我无法抛出异常的世界,我的错误处理完全淹没了我的代码的干净且易于阅读的逻辑.

目前我正在编写需要在出现问题时快速失败的代码,并且它也可能深度嵌套 - 我已经确定了错误处理模式,其中"Get"函数在错误上返回NULL,而其他函数返回-1失败了.在这两种情况下,调用失败的函数NS_SetError()以及所有调用函数需要做的就是清理并立即返回失败.

我的问题是,if (Action() < 0) return -1;我所拥有的语句数量正在逐渐增加 - 它非常重复,完全掩盖了基础逻辑.我最终创建了一个简单的宏来尝试改善这种情况,例如:

#define NOT_ERROR(X)    if ((X) < 0) return -1

int NS_Expression(void)
{
    NOT_ERROR(NS_Term());
    NOT_ERROR(Emit("MOVE D0, D1\n"));

    if (strcmp(current->str, "+") == 0)
    {
        NOT_ERROR(NS_Add());
    }
    else if (strcmp(current->str, "-") == 0)
    {
        NOT_ERROR(NS_Subtract());
    }
    else
    {
        NS_SetError("Expected: operator");
        return -1;
    }
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

每个函数NS_Term,NS_Add并在错误的情况下NS_Subtract执行NS_SetError()并返回-1 …

c error-handling

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

C转到不同的功能

我正在使用一个似乎不存在exit()调用的嵌入式系统.

我有一个函数调用malloc而不是让程序在失败时崩溃我宁愿退出一点优雅.

我最初的想法是使用goto,但标签似乎有一个非常有限的范围(我不确定,我从来没有使用它们"从不使用GOTO !! 1 !!").

我想知道是否有可能转到另一个函数的一部分,或者是否有任何其他创造性的方法从任意函数退出C程序.

void main() {
  //stuff
  a();

  exit:
     return;
}

void a() {
   //stuff

   //if malloc failed
   goto exit;
}
Run Code Online (Sandbox Code Playgroud)

谢谢你的帮助.

c embedded goto

5
推荐指数
1
解决办法
6378
查看次数

推荐的方法在C中的单个函数中处理多个malloc错误

处理可能按顺序发生的多个malloc错误的推荐方法是什么,如下面的代码所示?

bool myFunc(int x, int y)
{
    int *pBufX = null;
    int *pBufY = null;

    if((x <= 0) || (y <= 0))
    {
        return false;
    }

    pBufX = (int*)malloc(sizeof(int) * x);
    if(pBufX == null)
    {
        return false; 
    }

    pBufY = (int*)malloc(sizeof(int) * y);
    if(pBufY == null)
    {
        free(pBufX) //free the previously allocated pBufX 
        return false; 
    }

    //do something useful

    free(pBufX);
    free(pBufY);

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

这种方法的问题在于,如果malloc的数量很高,您可能会忘记释放一些并导致内存泄漏.此外,如果在发生错误时需要输出某种日志,则代码会变得很长.

我已经看到了用goto处理这些代码的代码,你可以在一个地方清除所有的mallocs,只有一次.代码不长,但我不喜欢使用gotos.

有没有比这两种方法更好的方法?

也许问题在于设计首先.在设计函数时,最小化多个mallocs是否有经验法则?

编辑:我已经看到并使用过另一种方式.您不保留使用goto,而是保留程序的状态,并仅在状态为OK时继续.类似于goto但不使用goto.但是这增加了可能使代码运行速度变慢的if语句数.

bool myFunc(int x, int y)
{
    int *pBufX = null;
    int …
Run Code Online (Sandbox Code Playgroud)

c malloc error-handling

5
推荐指数
1
解决办法
289
查看次数

良好的做法 - 很多事情要做的功能终止 - goto替代

可能重复:
在C中有效使用goto进行错误管理?

最近我遇到过这样的C代码:

if( !condition1){
    goto failure;
}

some_stuff_that_needs_manual_undoing();

if( !condition2){
    goto failure;
}

// And many more lines such as the ones above
return 0;

failure:
// Do a lot of stuff here, free, file closing and so on
return -1;
Run Code Online (Sandbox Code Playgroud)

总结一下情况:

我有一个很长的函数,连续做几件事(让我们说打开一个文件,然后根据文件内容分配内存,然后连接do数据库等等).当然我想正确地释放资源,但是有很多地方可能会导致功能过早结束(而且所有这些都需要清理).

问题:如何正确地做到这一点?

虽然goto 似乎不是那么糟糕的做法,但它似乎也不是一个好的解决方案.

我虽然遵循:

使用可以完成工作的宏,例如:

#define CLEANUP if( memory != NULL)free(memory); \
                if( fp != NULL) fclose(fp);\
                // ...

if( !condition1){
    CLEANUP
    return -1;
}

if( !condition2){
    CLEANUP
    return -2;
} …
Run Code Online (Sandbox Code Playgroud)

c goto

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

在SQL事务中的SQL中使用GOTO和标签

我有一个运行时间很长的脚本,我想包装其中可能包含多达100多个事务的事务

我想实现一些错误处理和代码重用。我正在考虑使用标签和GOTO语句。

BEGIN TRY
BEGIN TRANSACTION abc
    --DO SOMETHING
    COMMIT TRANSACTION abc;
END TRY
BEGIN CATCH
    GOTO ERROR_OUT
END CATCH

ERROR_OUT:  
       SELECT ERROR_MESSAGE() [ErrorMessage];  
       ROLLBACK;    
Run Code Online (Sandbox Code Playgroud)

使用许多事务时是否应该这样做?

在我强制执行错误的简单测试中,我注意到ERROR_MESSGE()SELECT语句未返回结果。

有没有办法在使用标签时使select语句返回结果?

sql sql-server

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

C中字符数组中的字符串终止符

我正在尝试根据一组规则制定一个程序来决定密码的有效性.

这是我有的:

#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <string.h>
#include <math.h>

int main()
{
  int uppercase = 0;
  int length = 0;
  int numbers = 0;
  int others = 0;
  char password[13];
  char yesOrNo;
  printf("Your password must be 8-12 characters long.\n"
         "It must contain at least one symbol, uppercase letter, and number.\n\n");
 COMEBACK:
  printf("Please enter your password:");
  scanf(" %s", &password);
  while (password != 'NULL') { // Tried 0 here, tried '\0', but to no avail.
    if (isalpha(password)) {
      length …
Run Code Online (Sandbox Code Playgroud)

c arrays terminator

-1
推荐指数
1
解决办法
2223
查看次数