你必须知道的495个C语言问题整理二

来源:互联网 发布:php中文分词算法 编辑:程序博客网 时间:2024/04/29 12:27

1.在调用malloc() 的时候, 错误“不能把void * 转换为int *”是什么意思?

说明你用的是C++ 编译器而不是C 编译器。

2. 我用一行这样的代码分配一个巨大的数组, 用于数字运算: double*array =malloc(300 * 300 * sizeof( double )); malloc() 并没有返回null,但是程序运行得有些奇怪, 好像改写了某些内存, 或者malloc() 并没有分配我申请的那么多内存, 云云。

注意300 * 300 是90,000, 这在你乘上sizeof(double)以前就已经不能放入16位的int 中了。如果你需要分配这样大的内存空间, 你可得小心为妙。如果在你的机器上size t(malloc() 接受的类型) 是32位, 而int 为16 位, 你可以写300 * (300* sizeof(double))来避免这个问题。(参见问题3.11)。否则, 你必须把你的数据结构分解为更小的块, 或者使用32 位的机器或编译器,或者使用某种非标准的内存分配函数。

3. 为什么在调用free() 之后指针没有变空?使用(赋值, 比较)释放之后的指针有多么不安全?

当你调用free() 的时候, 传入指针指向的内存被释放, 但调用函数的指针值可能保持不变, 因为C的按值传参语义意味着被调函数永远不会永久改变参数的值。在使用free函数之后,一定记得后面加一句将p赋为空的语句。

4. 我有个程序分配了大量的内存, 然后又释放了。但是从操作系统看,内存的占用率却并没有回去。

多数malloc/free 的实现并不把释放的内存返回操作系统,而是留着供同一程序的后续malloc() 使用。

5. free() 怎么知道有多少字节需要释放?

malloc/free 的实现会在分配的时候记下每一块的大小,所以在释放的时候就不必再考虑了。

6. 我认为我的编译器有问题: 我注意到sizeof(’a’) 是2 而不是1(即,不是sizeof(char))。

可能有些令人吃惊, C语言中的字符常数是int 型, 因此sizeof(’a’)是sizeof(int),这是另一个与C++ 不同的地方。

7. #if 预处理指令只处理整数。sizeof 操作符不可以用于#if预编译指令中。预编译在编译过程的早期进行, 此时尚未对类型名称进行分析。

8. 我不明白为什么我不能象这样在初始化和数组维度中使用常量:

const int n = 5; int a[n];

const 限定词真正的含义是“只读的”; 用它限定的对象是运行时(同常)不能被赋值的对象。因此用const 限定的对象的值并不完全是一个真正的常量。在这点上C 和C++ 不一样。如果你需要真正的运行时常量,使用预定义宏#define(或enum)。

9. “const char *p” 和“char * const p” 有何区别?

“const char *p” (也可以写成“char const *p”)声明了一个指向字符常量的指针, 因此不能改变它所指向的字符; “char * const p” 声明一个指向(可变) 字符的指针常量,就是说, 你不能修改指针。

10. 为什么我不能向接受const char ** 的函数传入char **?

你可以向接受const-T 的指针的地方传入T 的指针(任何类型T 都适用)。但是,这个允许在带修饰的指针类型上轻微不匹配的规则(明显的例外) 却不能递归应用, 而只能用于最上层。

如果你必须赋值或传递除了在最上层还有修饰符不匹配的指针, 你必须明确使用类型转换(本例中,使用(const char **)), 不过, 通常需要使用这样的转换意味着还有转换所不能修复的深层次问题。

11. 我觉得把main() 声明为void 不会失败, 因为我调用了exit()而不是return, 况且我的操作系统也忽略了程序的退出/返回状态。

这跟main() 函数返回与否, 或者是否使用返回状态都没有关系; 问题是如果main()声明得不对, 它的调用者(运行期初始代码) 可能甚至都不能正确调用它。你的操作系统可能会忽略退出状态, 而void main()在你那里也可能可行, 但这不可移植而且不正确。

12. 从main() 中, exit(status) 和返回同样的status 真的等价吗?

是也不是。标准声称它们等价。但是如果在退出的时候需要使用main() 的局部数据, 那么从main()return 恐怕就不行了; 参见问题16.4。少数非常古老不符合标准的系统可能对其中的某种形式有问题。最后, 在main()函数的递归调用时,二者显然不能等价。

13. memcpy() 和memmove() 有什么区别?

如果源和目的参数有重叠, memmove()提供有保证的行为。而memcpy()则不能提供这样的保证, 因此可以实现得更加有效率。如果有疑问,最好使用memmove()。

14. 这样的代码有什么问题?char c; while((c = getchar()) !=EOF)

第一, 保存getchar 的返回值的变量必须是int 型。getchar() 可能返回任何字符值,包括EOF。如果把getchar 的返回值截为char 型, 则正常的字符可能会被错误的解释为EOF, 或者EOF可能会被修改(尤其是char 型为无符号的时候), 从而永不出现。

15. 为什么这些代码while(!feof(infp)) { fgets(buf,MAXLINE,infp); fputs(buf, outfp);} 把最后一行复制了两遍?

在C 语言中, 只有输入例程试图读并失败以后才能得到文件结束符。换言之,C 的I/O 和Pascal的不一样。通常你只需要检查输入例程的返回值, 例如, fgets()在遇到文件结束符的时候返回NULL。实际上, 在任何情况下,都完全没有必要使用feof()。

16. 我如何用printf 实现可变的域宽度?就是说, 我想在运行时确定宽度而不是使用�?

printf("%*d", width, x) 就能达到你的要求。

17. 怎样在scanf() 格式串中指定可变的宽度?

不能: scanf() 格式串中的星号表示禁止赋值。你可以使用ANSI的字符串化和字符连接完成同样的事情, 或者你可以在运行时创建scanf 格式串。

18. 当我用“%d\n” 调用scanf 从键盘读取数字的时候,好像要多输入一行函数才返回。

可能令人吃惊, nn 在scanf 格式串中不表示等待换行符,而是读取并放弃所有的空白字符。

0 0
原创粉丝点击