【发布时间】:2009-06-03 20:00:28
【问题描述】:
作为一个想提高基础编程技能的人,我选择学习C++而不是C。这不禁让我问:我留在C中的一些基础技能可能不是通过学习C++获得的吗?
【问题讨论】:
-
这应该是一个社区维基,因为这个问题没有单一的“正确”答案。
-
@lothar:我认为这不一定是 CW。不过,它有点在边界线上,所以应该没问题。
作为一个想提高基础编程技能的人,我选择学习C++而不是C。这不禁让我问:我留在C中的一些基础技能可能不是通过学习C++获得的吗?
【问题讨论】:
如果你只使用过像 C++ 这样的面向对象编程语言,那么练习一点 C 语言是值得的。我发现许多 OO 程序员倾向于像拐杖一样使用对象,不知道该怎么做一旦你把它们带走。 C 将使您清楚地了解为什么 OO 编程首先出现,并帮助您了解它何时有用,何时它只是矫枉过正。
同样,您将了解不依赖库为您做事的感觉。通过注意 C++ 开发人员将哪些功能转变为库,您可以更好地了解在时机成熟时如何抽象自己的代码。感觉就像您需要在每种情况下抽象所有内容会很糟糕。
也就是说,您不必学习 C。如果您了解 C++,您可以拖着自己完成大多数项目。但是,通过查看低级语言,您将改进您的编程风格,即使是在高级语言中也是如此。
【讨论】:
我不认为你可以在 C 中学习任何技能,但不是 C++,但我绝对建议还是先学习 C。 没有人能把 C++ 放在他们的脑海里;它可能是有史以来最复杂的非深奥语言。另一方面,C 非常简单。将 C 放入您的脑海中相对容易。 C 肯定会比 C++ 更快地帮助您习惯指针和手动内存管理等内容。 C++ 将帮助您理解 OO。
另外,当我说学习 C 时,可以使用 C++ 编译器,如果您愿意,也可以使用 iostreams 之类的东西,但首先尝试将自己限制为主要使用 C 功能。如果你全力以赴,学习所有奇怪的 C++ 特性,如模板、RAII、异常、引用等,你会彻底糊涂。
【讨论】:
比较以下代码示例(抱歉,我的 C++ 有点生疏)。
C++:
int x;
std::cin >> x;
C:
int x;
scanf("%d", &x);
那么,你在上面看到了什么?在 C++ 中,一个值被插入到一个变量中。这很酷,但它教会了我们什么?在 C 中,我们注意到一些事情。 x 前面有一个有趣的 & ,这意味着它的地址正在被传递。这一定意味着 scanf 函数实际上需要知道内存 x 在哪里。不仅如此,它还需要一个格式字符串,所以它一定不知道你给它的地址是什么以及它获取信息的格式是什么?
C 可以让您发现有关计算机和操作系统实际工作的所有这些奇妙的事情,如果您愿意努力的话。我觉得这很酷。
【讨论】:
肯定有一件事:内存管理。以如下代码为例:
struct foo {
int bar;
char **box;
};
struct foo * fooTab = (struct foo *) malloc( sizeof(foo) * 100 );
for(int i = 0; i<100; i++) {
fooTab[i].bar = i;
fooTab[i].box = (char **) malloc( sizeof(char *) * 10 );
for(int j = 0; j<10; j++) {
fooTab[i].box[j] = (char *) malloc( sizeof(char) * 10 );
memset(fooTab[i].box[j], 'x', 10);
}
}
使用 C++,您根本不会以这种方式处理内存分配。因此,这些技能可能未经训练。这肯定会导致例如调试技能较低。另一个缺点可能是:优化技能较低。
C++ 代码如下所示:
struct foo {
int bar;
static int idx;
vector< vector<char> > box;
foo() : bar(idx), box(10) {
idx++;
for ( auto it = box.begin(); it != box.end(); it++) {
it->resize(10,'x');
}
}
};
int foo::idx = 0;
foo fooTab[100];
正如您所见,使用 C++ 风格的代码根本无法学习原始内存管理。
编辑:“C++ 风格的代码”是指:RAII 构造函数/析构函数、STL 容器。无论如何,我可能夸大了,最好说:用 C++ 风格的代码学习原始内存管理要困难得多。
【讨论】:
我发现在尝试深入 C++ 之前学习 C 中的内存管理更好。
在 C 中,只有 malloc() 和 free()。您可以将周围的东西作为指针进行类型转换。这很简单:将 sizeof() 乘以所需的 # 个项目,适当地进行类型转换,然后使用指针算法在各处跳转。
在 C++ 中,您有各种 reinterpret_cast(相对于 dynamic_cast 等)类型的东西,这很重要,但只有当您意识到各种强制转换旨在陷阱多重继承中的陷阱时才有意义,并且其他如此可爱的 C++ 主义。理解(学习)为什么需要将“虚拟”一词放在执行内存管理等对象的析构函数上是一种痛苦。
仅此一个原因就是您应该学习 C 的原因。我还认为(起初)理解 printf() 与可能重载的“
【讨论】:
我不会说你错过了任何基本的。不过,请查看 Compatibility of C and C++ 了解一些非基本示例。
C++ 不支持 C99 的一些添加或与 C++ 功能冲突,例如可变参数宏、复合文字、可变长度数组和本机复数类型。 C99 中定义的 long long int 数据类型和限制限定符不包含在当前的 C++ 标准中,但一些编译器(例如 GNU Compiler Collection[3])将它们作为扩展提供。 long long 数据类型以及可变参数模板,可以实现可变参数宏的某些功能,将在下一个 C++ 标准 C++0x 中。另一方面,C99 通过合并 C++ 特性(例如 // cmets 以及混合声明和代码)减少了其他一些不兼容性。
【讨论】:
C 的简单性focuses the mind wonderfully。
在 C 语言中要学的东西越来越少,学生就有可能更好地学习这些东西。如果一个人从 C++ 开始,那么另一端就有可能一无所知。
【讨论】:
这实际上取决于您学习了 C++ 的哪个子集。例如,您可以在 C++ 中仅使用 iostreams 库;这将使您没有 C stdio 库的经验。我不确定我是否会将 stdio 称为 基本 技能,但它肯定是一个应该熟悉的经验领域。
或者手动处理 C 风格的以空字符结尾的字符串和 str*() 函数集可能被认为是一项基本技能。在危险的 API 函数面前练习避免缓冲区溢出绝对是值得的。
【讨论】:
这只是在黑暗中的一个镜头,但也许你在 C 中比在 C++ 中更多地使用函数指针,并且可能通过开始学习 C 来提高使用函数指针作为一项技能。当然所有这些好东西都在C++ 也是如此,但是一旦你掌握了类,可能很容易只关注它们而错过其他基本的东西。
例如,您可以使用简单的结构和函数指针在纯 C 中构建自己的继承和多态“系统”。这需要更具创造性的思维,我认为可以加深对“盒子里”发生的事情的理解。
如果您从 C++ 开始,您可能会错过 C++ 中的这些小细节,但您永远不会看到它们,因为编译器会为您完成。
只是一些想法。
【讨论】:
取决于您使用 C++ 的方式。我通常建议从高层次开始,使用 STL 容器和智能指针,这不会让你了解低层次的细节。如果你想学习这些,你可能应该直接跳入 C。
【讨论】:
扮演魔鬼的拥护者,因为我认为 C 是一个很好的起点......
就个人而言,我开始学习 C、算法、数据结构、内存分配、文件操作、图形例程......我将这些称为编程的基本粒子。
接下来我学习了 C++。为了过度简化,C++ 添加了面向对象的编程层——无论使用哪种语言,您都拥有相同的目标,但是为实现这些目标而构建的方法和构造是不同的:类、重载、多态性、封装等。 ..
我没有做出任何明智的决定,这只是我的编程课程的结构,结果证明它是一门很好的课程。
另一个简化... C 基本上是 C++ 的一个子集。通过避免使用 C++ 的语言特性,您可以用 C++“做 C”。从语言特征来看。图书馆是另一回事。如果不开始使用和构建库,我认为你不会超越仅仅编程 101,而且那里有足够的东西让你忙一辈子。
如果您的目标是最终学习 C++,那么从“C”开始可能是一个合乎逻辑的开始,该语言“更小” - 但“C”中有太多内容,您可能希望缩小关注范围。你正在对付一只更大的野兽,但如果你得到指导,我认为没有令人信服的理由不这样做,尽管我走了这条路。
【讨论】:
大多数 C 代码只需稍作改动即可编译为 C++ 代码。有关无法更改的极少数事情的示例,请参阅Why artificially limit your code to C?。不过,我认为这些都不能归类为基础。
【讨论】:
C 本质上是 C++ 的一个子集。其他一些答案强调存在差异,但基本上大多数 C 编译为 C++,只需稍作修改。
学习 C 的好处是它是一种更紧凑的语言,因此学习它的速度更快。 C 还要求您在相对较低的抽象级别上工作,这有助于理解计算机的实际工作方式。我个人是在汇编中长大的,然后从那里转向 C,我现在认为这是理解编译器如何将高抽象级别的构造映射到实际机器代码的明确优势。
在 C++ 中,您会发现自己很快就陷入了更高层次的抽象之中。这对生产力有好处,但对理解却不一定如此。
所以我的建议是:如果你有动力学习 C++,但首先专注于 C 常见的核心低级结构。然后才转向更高层次的东西,例如面向对象、模板、广泛的类库和以此类推。
【讨论】:
优化理论
主要是因为 C 编译器的 asm 输出通常更加可预测,并且通常与 C 有很好的相关性。这可以让您教/学习为什么通过显示生成的实际指令。
【讨论】:
你应该学习 C 中的数据结构。首先,它会迫使你真正理解指针,这将帮助你处理高级语言中的leaky abstractions。其次,它将使 OO 的好处显而易见。
【讨论】:
编码风格
我所说的编码风格不是指 {} 和空格,而是指您如何组织数据、类、文件等。
我开始学习 c++,它通常倾向于以某种方式创建类和组织事物。我可以在需要时编写 c 代码,但它绝不像其他人以 c 开头的 c 风格代码。
我的一个操作系统课程要求我们用 C 语言编写文件系统。我的搭档最初是一名 C 人,我对我们编写的代码的不同感到惊讶。我的显然是在尝试在 c 中使用 c++ 风格的编码。
这有点像当你第一次学习 perl 或 ruby 或其他东西时,你只是想编写相同的 c# 代码,除了翻译成新的语言而不是使用这些语言的功能。
虽然 C 是 C++ 的一个子集,但 C 程序和 C++ 程序如此不同以至于无法真正进行比较。
【讨论】:
是的,简单的结构化编程。
随着 OOP 无处不在,很容易忘记您可以仅使用模块和函数来构建完善的系统。 C 的模块系统很弱,但仍然...
这也是函数式编程的优点之一,在我的书中。许多函数式编程语言都有强大的模块系统。当您需要比简单函数提供的更多通用性时,总会有更高阶的函数。
【讨论】:
如果您想学习新技能并且您拥有良好的结构化编程 (SP) 基础知识,那么您应该选择 C++。学会以面向对象(OOP)的方式(定义对象、方法、继承等)来思考给定的问题,这有时是最困难的部分。几年前我和你的情况一样,我选择C++,因为学习新的范式,新的思维方式和设计软件,有时比代码本身更难,如果你不喜欢C++或者 OOP 你可以回到 C 和 SP,但至少你会有一些 OOP 技能。
【讨论】:
我会选择 C 来学习编程的低级原语。
对于 OOP,so 在 C++ 之前还有许多其他更容易学习的语言需要学习。这不是 1990 年,当时唯一的 OOP 语言是 Smalltalk 和 C++,而且只有 C++ 在学术界之外使用。从那以后,几乎所有发明的新编程语言都有对象,而且几乎都没有 C++ 复杂。
【讨论】: