为何不精通C? 01一些零碎的混淆知识
引言---
一直以来,我以为能在简历上写上“精通C语言”, 可是,朋友都劝阻说,还是写“熟悉or掌握”吧,要不然,会被问得很死的。我算是没认清现实吧,去网上找了些题,看了看,大体脉络掌握还行,但是细节部分,就很差劲了。我想起了段誉和慕容复的故事:“段誉仅精通六脉神剑,却稳胜以彼之道还施彼身的慕容复”。 C 语言既然作为我"Hello World!" 的引路人, 我很想说,我很想,精通你。
主要阅读材料: 《C专家编程》
主要记录我还未掌握,或者掌握不精的内容。
1, 合法的赋值形式, 类型的兼容
- 问题来源:
1 foo(const char** p){} 2 main(int argc, char** argv) 3 { 4 foo(argv); 5 }
这里,定义了foo函数,具有一个 const char** 类型的形参。main函数调用foo, 将 argv 作为实参传入, 若是编译,则会有一条警告信息:
line 4: warning: argument is incompatible with prototype
- 为什么会迷惑?
若实参是char*,形参为 const char*, 则不会报这个警告信息,因为,他们是兼容的。
- 理论上的解释
来自ANSI C标准的解释:
条件 1,两个操作数都是指向有限定符(const等)或无限定符的相容类型指针,
条件2, 左边指针所指向的类型必须具有右边指针所指向类型的全部限定符。
- 问题解决:
a, char* p; const char* cp; cp=c; : 这里,左操作数cp是具备 const限定符 的 char*; 右操作数是 char* , 左边集合为[const], 右边为[],左边包含右边所有,条件2合法;类型都为char*,条件1合法,所以通过。
b, char** p; const char** cp; cp = p; 这里,p 是一个指向 char* 的指针, cp是一个指向 const char* 的指针。 限定符都为[],条件2符合,但是,const char* != char* 条件1不合法,所以警告。
- 引出心得
虽然 const 是好东西,但是不深入了解,还是很难驾驭,慎重!另外,提出了原型prototype的概念,及“兼容”理念,需要深入探究。
2, const 我们所理解错的地方
关键字 const 并不把变量变成常量! const仅是说明了被它限定的东西,不可被赋值,即 read only!
int const* k, const int* p 和 int *const q 区别: 最简单的做法,从右往左看,是先出现*还是const
- 解释:
对于 k/p而言,先看到了*,所以我们知道k/p被声明成一个指针,它指向了一个被const限定int型变量。即指针可以赋新值,但是它所指之物不能被修改。
对于 q 而言,先看到了const, 则说明 q 具有const属性,然后看到了*,说明q是一个指针,接着是 int, 说明它指向int型变量,合起来就是:q是一个常量指针,指向int型变量。即指针不能赋值,但是其所指之物可以被修改。
- 进阶: 见 后续博客, 大概是将声明时引入。
3, strlen()函数返回的字符串长度不包含最末尾的'\0'。对于这个知识点比较了解,但是也是因为熟悉,在使用malloc时更加容易疏忽。
若是见到 malloc(strlen(str)); 那么,几乎可以肯定是错误的,它疏忽了最末尾的'\0', 应该 malloc(strlen(str)+1);
4, NUL != NULL
NUL:一个ACSII字符, 表示0的位模式。
NULL: 指向哪里也不是,一般是0;
5, break 从哪跳出,跳向哪里?
break可以使用在for, while, do-while, switch中,用于跳出离他最近的那层循环或者switch语句。它不会跳出if语句。