在用C++编写了几年后,我最近在嵌入式领域的C中提供了一个编码工作.
抛开在嵌入式领域中忽略C++是对还是错的问题,C++中有一些特性/习惯用法我会错过很多.仅举几个:
从C++到C的经历是什么?
您找到的C替代品是您最喜欢的C++特性/习语吗?您是否发现了C++的C功能?
今天我发现了一件有趣的事情.我不知道在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 API中声明不透明类型的样式.使用一种风格而不是另一种风格有明显的优势吗?
// foo.h
typedef struct foo * fooRef;
void doStuff(fooRef f);
// foo.c
struct foo {
int x;
int y;
};
Run Code Online (Sandbox Code Playgroud)
// 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++的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) 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 …
假设我非常防御地编写代码,并且总是从我调用的所有函数中检查返回类型.
所以我喜欢:
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.
我有一个程序,我需要打破一大堆嵌套for循环.到目前为止,大多数人告诉我这样做的方式是在我的代码中使用一个丑陋的goto.
现在,如果我创建一堆本地堆栈(我认为这就是它们被称为,如果不是,我的意思是只使用常规变量而不使用新命令)我的循环中的变量和我的程序命中一个if语句触发goto,我会遇到内存泄漏,因为我的程序不正确地退出许多循环并且没有清理局部变量?
我正在尝试通过编写一个简单的解析器/编译器来学习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 …
我正在使用一个似乎不存在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)
谢谢你的帮助.
处理可能按顺序发生的多个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中有效使用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) 我有一个运行时间很长的脚本,我想包装其中可能包含多达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语句返回结果?
我正在尝试根据一组规则制定一个程序来决定密码的有效性.
这是我有的:
#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 ×11
goto ×5
c++ ×3
coding-style ×2
allocation ×1
arrays ×1
embedded ×1
exception ×1
free ×1
malloc ×1
memory ×1
memory-leaks ×1
sql ×1
sql-server ×1
struct ×1
terminator ×1
typedef ×1