goto、void和sizeof分析
1. 遭人遗弃的goto
(1)高手潜规则:禁用goto
(2)项目经验:程序质量与goto出现的次数成反比
(3)最后的判决:将goto打入冷宫(1)循环语句的基本工作方式
【实例分析】goto副作用的分析
#include <stdio.h>
#include <malloc.h>
void func(int n)
{
int* p = NULL;
if( n < 0 )
{
goto STATUS;
}
p = (int*)malloc(sizeof(int) * n);//n<0时,将不被执行
STATUS:
p[0] = n; //n<0时,p内存未申请,出现错误
free(p);
}
int main()
{
printf("begin...\n");
printf("func(1)\n");
func(1);
printf("func(-1)\n");
func(-1);
printf("end...\n");
return 0;
}
2. void的意义
(1)void修饰函数返回值和参数——为了表示“无”
①如果函数没有返回值,那么应该将其声明为void
②如果函数没有参数,应该声明其参数为void
| 任意参数 | 无参(用void声明) |
#include<stdio.h>
f() //f()函数任意参数,返回值默认int型
{
}
int main()
{
int i=f(1,2,3)
return 0;
|
#include<stdio.h>
void f(void) //无参无返回值
{
}
int main()
{
int i=f(1,2,3) //error
f(); //ok
return 0;
}
|
(2)不存在void变量
①C语言没有定义void究意是多大内存的别名,没有void标尺,无法在内存中裁出大小
#include<stdio.h>
void main()
{
void var; //error,不可以是void型的变量
void array[5]; //error,同上
void* pv; //ok,void*的指针是可以的。
}
②小贴士:ANSI C:标准C语言的规范
扩展C: 在ANSI C的基础上进行了扩充
#include<stdio.h>
int main()
{
//在ANSI C编译器中无法通,支持GNU标准的gcc下为void大小为1,是合法的(C语言的灰色地带,有编译器厂商在出厂时设定的)
printf("sizeof(void)=%d\n",sizeof(void));
}
(3)void指针的意义
①C语言规定只有相同类型的指针才可以相互赋值
②void* 指针作为左值用于“接收”任意类型的指针
③void* 指针作为右值使用时需要进行强制类型转换
int* pI = (int*)malloc(sizeof(int)); char* pC = (char*)malloc(sizeof(char)); void* p = NULL; int* pni = NULL; char* pnc = NULL; p = pI; //ok,void*指针p可接收任何类型的指针 pni = p; //error,void*须强制类型转换,即pni =(int*)p; p = pC; //ok pnc = p; //error,应为pnc=(char*)p;
【编程实例】通过void*实现MemSet函数

#include <stdio.h> void MemSet(void* src, int length, unsigned char n) //void* src 这样定义可以接受任意类型的地址值 { unsigned char* p = (unsigned char*)src; int i = 0; for(i=0; i<length; i++) { p[i] = n; } } int main() { int a[5];//这里可以是任何其他类型,如char a[5];double a[5]等。 int i = 0; MemSet(a, sizeof(a), 0); for(i=0; i<5; i++) { printf("%d\n", a[i]); } return 0; }
3. sizeof关键字的用法
3.1 sizeof简介
(1)sizeof是编译器的内置指示符
(2)sizeof用于“计算” 类型或变量所占的内存大小
(3)sizeof的值在编译期就己经确定
3.2 为sizeof关键字正名——sizeof是C语言的内置关键字而不是函数
(1)在编译过程中所有的sizeof将被具体的数值所替换
(2)程序的执行过程与sizeof没有任何关系
int var =0;
int size = sizeof(var++); //在编译期,该行的size值就被计算出来了,并
//被替换为类似int size=4;这样的语句。即己经
//最终的代码己经没有var++的语句了。(注意,
//var++可看作是var = var+1;所以sizeof(var++)
//相当于计算最终的变量var的大小)。
printf("var = %d, size = %d\n",var,size); //输出0,4。而不是1,4;
int main() { int a; printf("%d\n", sizeof(a)); printf("%d\n", sizeof a); //sizeof 不是函数,为了统一因此一般都加括号,才有机会被误以为是函数 printf("%d\n", sizeof(char)); printf("%d\n", sizeof int);//编译器报错,因为标准里不允许除了unsigned和signed之外的修饰 return 0; }
【编程实验】sizeof的本质
#include <stdio.h> int f() { printf("I like programming!\n"); return 0; } int main() { int var = 0; int size = sizeof(var++); //该行在编译期被替换为int size =4; //所以运行时,不存在var++之类的代码了 printf("var = %d, size = %d\n", var, size); size = sizeof(f()); //该行在编译期被替换为size = sizeof(函数的返回值类型) =4; //即最终代码没有f()函数的调用,也就不会输出f()里面的printf printf("size = %d\n", size); return 0; }
4. 总结
(1)现代软件工程中禁用goto语句
(2)void是一种抽象的数据类型
(3)void类型不能用于定义变量
(4)void类型用于声明函数无参数或函数无返回值
(5)可以定义void*类型的指针,该指针可接受任意类型的指针值
(6)sizeof是编译器的内置指示符
(7)sizeof不参与程序的执行过程
浙公网安备 33010602011771号