1).为什么声明extern int f(struct x *p); 报出了一个奇怪的警告信息“结构x 在参数列表中声明”?
与C 语言通常的作用范围规则大相径庭的是, 在原型中第一次声明(甚至提到) 的结构不能和同一源文件中的其它结构兼容, 它在原型的结束出就超出了作用范围。
要解决这个问题, 在同一源文件的原型之前放上这样的声明:
struct x;
它在文件范围内提供了一个不完整的结构x 的声明, 这样, 后续的用到结构x的声明至少能够确定它们引用的是同一个结构x。
2).我不明白为什么我不能象这样在初始化和数组维度中使用常量:
const int n = 5; int a[n];
const 限定词真正的含义是“只读的”; 用它限定的对象是运行时(同常) 不能被赋值的对象。因此用const 限定的对象的值并不完全是一个真正的常量。在这点上C 和C++ 不一样。如果你需要真正的运行时常量, 使用预定义宏#define(或enum)。
3).警告信息“warning: macro replacement within a string literal”是什么意思?
有些ANSI 前的编译器/预处理器把下面这样的宏
#define TRACE(var, fmt) printf("TRACE: var = fmt\n", var)
解释为
TRACE(i, %d);
这样的调用会被扩展为
printf("TRACE: i = %d\n", i);
换言之, 字符串常量内部也作了宏参数扩展。
K&R 和标准C 都没有定义这样的宏扩展。当你希望把宏参数转成字符串时,
你可以使用新的预处理操作符# 和字符串常量连接(ANSI 的另一个新功能):
#define TRACE(var, fmt) \
printf("TRACE: " #var " = " #fmt "\n", var)
4).a[3] = "abc"; 合法吗?它是什么意思?
尽管只在极其有限的环境下有用, 可它在ANSI C (可能也包括一些ANSI 之前的系统) 中是合法的。它声明了一个长度为3 的数组, 把它的三个字符初始化为’a’, ’b’ 和’c’, 但却没有通常的’\0’ 字符。因此该数组并不是一个真正的C 字符串从而不能用在strcpy,
printf %s 等当中。
多数时候, 你应该让编译器计算数组初始化的初始值个数, 在初始值“abc” 中,计算得长度当然应该是4。
5).memcpy() 和memmove() 有什么区别?
如果源和目的参数有重叠, memmove() 提供有保证的行为。而memcpy()则不能提供这样的保证, 因此可以实现得更加有效率。如果有疑问, 最好使用memmove()。
malloc(0) 有什么用?返回一个控指针还是指向0 字节的指针?
ANSI/ISO 标准声称它可能返回任意一种; 其行为由实现定义。
6).这样的代码有什么问题?char c; while((c = getchar()) != EOF)
...
第一, 保存getchar 的返回值的变量必须是int 型。getchar() 可能返回任何字
符值, 包括EOF。如果把getchar 的返回值截为char 型, 则正常的字符可能会被
错误的解释为EOF, 或者EOF 可能会被修改(尤其是char 型为无符号的时候), 从
而永不出现。
2.为什么这些代码
while(!feof(infp)) { fgets(buf, MAXLINE,infp); fputs(buf, outfp); } 把最后一行复制了两遍?
在C 语言中, 只有输入例程试图读并失败以后才能得到文件结束符。换言之,C 的I/O 和Pascal 的不一样。通常你只需要检查输入例程的返回值, 例如, fgets()在遇到文件结束符的时候返回NULL。实际上, 在任何情况下, 都完全没有必要使用feof()。
3.我如何在printf 的格式串中输出一个’%’?我试过\%, 但是不行。
只需要重复百分号: %%。
\%不行, 因为反斜杠\ 是编译器的转义字符, 而这里我们的问题最终是printf的转义字符。
4.我如何用printf 实现可变的域宽度?就是说, 我想在运行时确定宽
度而不是使用%8d?
printf("%*d", width, x) 就能达到你的要求。
7).scanf函数:
1.当我用“%d\n” 调用scanf 从键盘读取数字的时候, 好像要多输入一行函数才返回。
可能令人吃惊, \n在scanf 格式串中不表示等待换行符, 而是读取并放弃所有的空白字符。
2.我用scanf %d 读取一个数字, 然后再用gets() 读取字符串, 但是
编译器好像跳过了gets() 调用!
scanf %d 不处理结尾的换行符。如果输入的数字后边紧接着一个换行符, 则
换行符会被gets() 处理。
作为一个一般规则, 你不能混用scanf() 和gets(), 或任何其它的输入例程的调
用; scanf 对换行符的特殊处理几乎一定会带来问题。要么就用scanf() 处理所有的
输入, 要么干脆不用。
3..我发现如果坚持检查返回值以确保用户输入的是我期待的数值, 则
scanf() 的使用会安全很多, 但有的时候好像会陷入无限循环。
在scanf() 转换数字的时候, 它遇到的任何非数字字符都会终止转换并被保留
在输入流中。因此, 除非采用了其它的步骤, 那么未预料到的非数字输入会不断
“阻塞” scanf(): scanf() 永远都不能越过错误的非数字字符而处理后边的合法数字
字符。如果用户在数字格式的scanf 如%d 或%f 中输入字符‘x’, 那么提示后并用
同样的scanf() 调用重试的代码会立即遇到同一个’x’。
4.为什么大家都说不要使用scanf()?那我该用什么来代替呢?
scanf() 有很多问题。而且, 它的%s 格式有着和gets() 一样的问题,很难保证接收缓冲不溢出。更一般地讲, scanf() 的设计使用于相对结构化的, 格式整齐的输入。设计上,它的名称就是来自于“scan formatted”。如果你注意到, 它会告诉你成功或失败,但它只能提供失败的大略位置, 至于失败的原因, 就无从得知了。对scanf() 的错误恢复几乎是不可能的; 通常先用类似fgets() 的函数读入整行, 然后再用sscanf() 或其它技术解释。strtol(), strtok() 和atoi() 等函数通常有用;如果你真的要用任何scanf 的变体, 你要确保检查返回值, 以确定找到了期待的值。而使用%s 格式的时候, 一定要小心缓冲区溢出。
8).&i是常量表达式
全局变量只能用常量表达式初始化,如果定义int p = i;就错了,因为i不是常量表达式,然而用i的地址来初始化一个指针却没有错,因为i的地址是在编译链接时能确定的,而不需要到运行时才知道,&i是常量表达式。
分享到:
相关推荐
二维卷积运算之C语言实现二维卷积运算之C语言实现 二维卷积运算之C语言实现二维卷积运算之C语言实现
c语言课件第二章c语言课件第二章c语言课件第二章c语言课件第二章c语言课件第二章c语言课件第二章c语言课件第二章c语言课件第二章c语言课件第二章
四川省C语言二级考试四川省C语言二级考试四川省C语言二级考试四川省C语言二级考试四川省C语言二级考试四川省C语言二级考试四川省C语言二级考试四川省C语言二级考试四川省C语言二级考试四川省C语言二级考试四川省...
二级C语言题库二级C语言题库二二级C语言题库级C语言题库
C语言二级题库
主要给大家介绍了关于C语言中二维数组作为函数参数来传递的三种方法,文中通过示例代码介绍的非常详细,对大家学习或者使用C语言有一定的参考学习价值,需要的朋友们下面来一起学习学习吧
c语言第二节c语言第二节c语言第二节c语言第二节c语言第二节c语言第二节c语言第二节c语言第二节
c语言第二章节:基本数据类型。ppt内容丰富,适合个人学习
二级C语言二级C语言真题,TXT文件格式
C语言 第二章 程序的灵魂-算法,ppt,简洁易懂,是不错的教学用具。
C语言二级是Android客户端目前最全面的免费离线C语言二级考试参考书籍,主要内容包括: 1、C语言的结构 2、数据类型及其运算 3、基本语句 4、结构程序设计 5、循环结构程序设计 6、数组的定义和引用 7、函数、...
C语言二级是Android客户端目前最全面的免费离线C语言二级考试参考书籍,主要内容包括: 1、C语言的结构 2、数据类型及其运算 3、基本语句 4、结构程序设计 5、循环结构程序设计 6、数组的定义和引用 7、函数、指针、...
c语言(二级考试)
C语言二路归并排序算法, 写了个二路归并的归并排序小代码,直接贴上来
基础的C语言二级,对于想学习其他语言的同志们很是有帮助的,希望大家一起努力!
c语言 二级题 c语言 二级题c语言 二级题c语言 二级题c语言 二级题
c语言 一元二次源码 带我的注释啥啥啥 Design by Smith
二分查找 C语言语言源代码 用递归写的 C语言入门经典代码 值得收藏
二级c语言公共基础知识二级c语言公共基础知识二级c语言公共基础知识
用二C语言求二维数组鞍点,有文档和程序。。