C语言中容易被忽略的细节(第四篇)
2014-12-16 09:51
281 查看
转载时自己也能回顾一遍,所以还是有必要转载的。
第一篇链接:C语言中容易被忽略的细节(第一篇)
第二篇链接:C语言中容易被忽略的细节(第二篇)
第三篇链接:C语言中容易被忽略的细节(第三篇)
1、void*类型的指针不能参与算术运算,只能进行赋值、比较和sizeof操作的原因?
指针的算术运算还要包含指针所指对象的字节数信息。
2、不能把“&”单独用于一个非变量的东西。不能对字面常量使用“&”来取其地址,因为字面常量保存在符号表中,没有地址概念。数组名是一个指针常量,不能修改数组名的值。例如以下语句1与语句2是等价的:
[cpp] view
plaincopy
int a[10]; //语句1
int *const a; //语句2
int b[3][4]; //语句1
int (*const b)[4]; //语句2
int c[3][4][5]; //语句1
int (*const c)[4][5]; //语句2
3、return 0与exit(0)的几点区别
(1)exit结束正在运行的整个程序,只要调用exit就结束,它将参数返回给OS,把控制权交给操作系统;return退出当前函数,返回函数值,把控制权交给调用函数;
(2)exit是系统调用级别,它表示一个进程的结束;return是语言级别的,它表示调用堆栈的返回。
(3)main函数结束时也会隐式地调用exit函数,它将删除进程使用的内存空间,同时把错误信息返回给父进程。
(4)main函数返回一个整型值与该值调用exit是等价的。
4、static修饰符是一个能够减少命名冲突的有用工具。例如:static int a;将a的作用域限制在一个源文件内,对于其他源文件,a是不可见的。可以在多个源文件中定义同名的变量a,只要所有的变量a都被定义为static,或者仅仅只有其中一个变量不是static。static修饰符也适用于函数。
5、C语言允许程序员写操作前控制产生的输出数据量,这种控制能力是通过库函数setbuf实现的。例如:setbuf(stdout, buf);语句将通知输入/输出库,所有写入到stdout的输出都使用buf作为输出缓冲区,直到buf缓冲区被填满或程序员直接调用fflush,buf缓冲区的内容才实际写入到stdout中。缓冲区的大小由系统头文件<stdio.h>中的BUFSIZ定义。《C陷阱与缺陷》中有一个例子:
[cpp] view
plaincopy
#include <stdio.h>
int main(void)
{
char c;
char buf[BUFSIZ];
setbuf(stdout, buf);
while ((c = getchar()) != EOF)
putchar(c);
return 0;
}
以上程序是错误的。buf缓冲区最后一次被清空是在main函数结束之后,作为程序交回控制给操作系统之前C运行时库所必须进行清理工作的一部分。在此之前buf字符数组已经被释放了。修改的方法有3种:
(1)定义缓冲数组为静态数组static char buf[BUFSIZ];
(2)将缓冲数组拿到main函数外;
(3)动态分配缓冲区,程序中并不主动释放分配的缓冲区。setbuf(stdout, malloc(BUFSIZ));
备注:
(1)由于缓冲区是动态分配的,所以main函数结束时并不会释放该缓冲区,这样C运行时库进行清理工作时就不会发生缓冲区已释放的情况。
(2)如果malloc调用失败,返回NULL指针,此时标准输出不需要进行缓冲。
(3)对于由写操作打开的文件,调用fflush将导致输出缓冲区的内容被实际地写入该文件。
6、为什么向函数传递多维数组时候不需要说明第一维长度而必须说明其他维长度?
(1)数组元素在内存中按照“行优先”规则存储,需要列数确定一行有多少元素;
(2)编译器在计算元素地址时不需要数组第一维的长度,但需要所有其他维的长度信息;
(3)C/C++不对数组进行越界访问检查,对编译器来说不需要知道第一维的长度。
7、C语言将多维数组转换为数组指针。以下4种表达方式是等价的:
[cpp] view
plaincopy
a[i][j];
*(a[i] + j);
(*(a + i))[j];
*(*(a + i) + j);
8、在语义上,下标操作符返回的是一个元素的引用。例如语句1和语句2是等价的:
[cpp] view
plaincopy
//语句1
a[3] = 100;
//语句2
int &ri = a[3];
ri = 100;
9、不能使用一个元素类型的指针来接收动态创建的多维数组的返回地址,因为一个多维数组在语义上并不等价于一个指向其元素类型的指针,它等价于一个“指向数组的指针”。例如以下用法是正确的:
[cpp] view
plaincopy
char *q = new char[5];
delete []q;
char (*p)[4] = new char[5][4];
delete []p;
10、(1)标号(lable)是具有函数作用域的唯一一种标识符。无论标号定义在函数哪行,函数内嵌套多深,它都能在函数体内任何一个地方访问到。标号一般用在goto语句中,如果goto语句没有使用到该标号,那么该标号将被忽略。(2)当局部变量与某一个全局变量同名时,在函数内部将遮蔽该全局变量。此时在函数内部可通过一元作用域解析运算符来引用全局变量,如::a。
转载自:http://blog.csdn.net/mengwang024/article/details/40734969
第一篇链接:C语言中容易被忽略的细节(第一篇)
第二篇链接:C语言中容易被忽略的细节(第二篇)
第三篇链接:C语言中容易被忽略的细节(第三篇)
1、void*类型的指针不能参与算术运算,只能进行赋值、比较和sizeof操作的原因?
指针的算术运算还要包含指针所指对象的字节数信息。
2、不能把“&”单独用于一个非变量的东西。不能对字面常量使用“&”来取其地址,因为字面常量保存在符号表中,没有地址概念。数组名是一个指针常量,不能修改数组名的值。例如以下语句1与语句2是等价的:
[cpp] view
plaincopy
int a[10]; //语句1
int *const a; //语句2
int b[3][4]; //语句1
int (*const b)[4]; //语句2
int c[3][4][5]; //语句1
int (*const c)[4][5]; //语句2
3、return 0与exit(0)的几点区别
(1)exit结束正在运行的整个程序,只要调用exit就结束,它将参数返回给OS,把控制权交给操作系统;return退出当前函数,返回函数值,把控制权交给调用函数;
(2)exit是系统调用级别,它表示一个进程的结束;return是语言级别的,它表示调用堆栈的返回。
(3)main函数结束时也会隐式地调用exit函数,它将删除进程使用的内存空间,同时把错误信息返回给父进程。
(4)main函数返回一个整型值与该值调用exit是等价的。
4、static修饰符是一个能够减少命名冲突的有用工具。例如:static int a;将a的作用域限制在一个源文件内,对于其他源文件,a是不可见的。可以在多个源文件中定义同名的变量a,只要所有的变量a都被定义为static,或者仅仅只有其中一个变量不是static。static修饰符也适用于函数。
5、C语言允许程序员写操作前控制产生的输出数据量,这种控制能力是通过库函数setbuf实现的。例如:setbuf(stdout, buf);语句将通知输入/输出库,所有写入到stdout的输出都使用buf作为输出缓冲区,直到buf缓冲区被填满或程序员直接调用fflush,buf缓冲区的内容才实际写入到stdout中。缓冲区的大小由系统头文件<stdio.h>中的BUFSIZ定义。《C陷阱与缺陷》中有一个例子:
[cpp] view
plaincopy
#include <stdio.h>
int main(void)
{
char c;
char buf[BUFSIZ];
setbuf(stdout, buf);
while ((c = getchar()) != EOF)
putchar(c);
return 0;
}
以上程序是错误的。buf缓冲区最后一次被清空是在main函数结束之后,作为程序交回控制给操作系统之前C运行时库所必须进行清理工作的一部分。在此之前buf字符数组已经被释放了。修改的方法有3种:
(1)定义缓冲数组为静态数组static char buf[BUFSIZ];
(2)将缓冲数组拿到main函数外;
(3)动态分配缓冲区,程序中并不主动释放分配的缓冲区。setbuf(stdout, malloc(BUFSIZ));
备注:
(1)由于缓冲区是动态分配的,所以main函数结束时并不会释放该缓冲区,这样C运行时库进行清理工作时就不会发生缓冲区已释放的情况。
(2)如果malloc调用失败,返回NULL指针,此时标准输出不需要进行缓冲。
(3)对于由写操作打开的文件,调用fflush将导致输出缓冲区的内容被实际地写入该文件。
6、为什么向函数传递多维数组时候不需要说明第一维长度而必须说明其他维长度?
(1)数组元素在内存中按照“行优先”规则存储,需要列数确定一行有多少元素;
(2)编译器在计算元素地址时不需要数组第一维的长度,但需要所有其他维的长度信息;
(3)C/C++不对数组进行越界访问检查,对编译器来说不需要知道第一维的长度。
7、C语言将多维数组转换为数组指针。以下4种表达方式是等价的:
[cpp] view
plaincopy
a[i][j];
*(a[i] + j);
(*(a + i))[j];
*(*(a + i) + j);
8、在语义上,下标操作符返回的是一个元素的引用。例如语句1和语句2是等价的:
[cpp] view
plaincopy
//语句1
a[3] = 100;
//语句2
int &ri = a[3];
ri = 100;
9、不能使用一个元素类型的指针来接收动态创建的多维数组的返回地址,因为一个多维数组在语义上并不等价于一个指向其元素类型的指针,它等价于一个“指向数组的指针”。例如以下用法是正确的:
[cpp] view
plaincopy
char *q = new char[5];
delete []q;
char (*p)[4] = new char[5][4];
delete []p;
10、(1)标号(lable)是具有函数作用域的唯一一种标识符。无论标号定义在函数哪行,函数内嵌套多深,它都能在函数体内任何一个地方访问到。标号一般用在goto语句中,如果goto语句没有使用到该标号,那么该标号将被忽略。(2)当局部变量与某一个全局变量同名时,在函数内部将遮蔽该全局变量。此时在函数内部可通过一元作用域解析运算符来引用全局变量,如::a。
转载自:http://blog.csdn.net/mengwang024/article/details/40734969
相关文章推荐
- C语言---那些容易被忽略的细节
- C语言中容易被忽略的细节(第二篇)
- C语言中容易被忽略的细节(第三篇)
- C语言中容易被忽略的细节(第一篇)
- 容易被忽略的细节:config文件的使用
- C++ 容易忽略的细节
- Linux学习中容易忽略的细节(一)
- HTML5容易忽略的细节
- 【C/C++】C语言中一些容易被人忽略的东西 之一 【内存的分配与释放】
- 自定义View容易忽略的细节
- 学习Java,容易被你忽略的小细节(3)
- 使用Dedecms中七个容易忽略的安全细节介绍
- Linux容易忘记或忽略的基础细节(一)
- 容易被忽略的用法--c语言中用include时可以指定被包含文件的路径
- aspx超时问题容易忽略的细节
- C语言新手比较容易忽略的东西
- Windows 在处理 dll 的一些容易被人忽略的细节
- 【C/C++】C语言中一些容易被人忽略的东西 之五 【预编译中的未知数】
- c语言容易忽略的点