关键词:goto副作用分析、 void
的意义、void*
指针的意义
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);
STATUS:
p[0] = n;
free(p);
}
int main()
{
printf("Begin...\n");
printf("func(10)\n");
func(10);
printf("func(-10)\n");
func(-10);
printf("End...\n");
return 0;
}
输出结果:
Begin...
func(10)
func(-10)
段错误
总结:goto
语句的执行破化了程序的结构化特征。
2. void
的意义
-
void
修饰函数返回值和参数
如果函数没有返回值,应该将其声明为void
;
如果函数没有参数,应该将其声明为void
void
修饰函数返回值和参数是为了表示无
#include <stdio.h>
// 在C语言中,函数定义可以不写任何参数,也可以不写任何的返回值
// 当没有写参数的情况下,编译器认为函数可以接收任意个参数
// 当没有写返回值的情况下,编译器认为返回值为int类型
f()
{
}
int main()
{
int i = f(1, 2, 3, 4);
int j = f(2, 4, 5, 6, 6, 7);
return 0;
}
总结:C语言不是强类型语言
需要通过void
来声明函数的返回值为空,需要通过void
来声明函数的参数个数未0个(注意与C++的区别)。
#include <stdio.h>
void f(void)
{
}
int main()
{
f();
return 0;
}
3. 不存在void
变量
- C语言中没有定义
void
究竟是多大内存的别名,因此不能定义void
类型的变量 - 没有
void
的标尺,无法在内存中裁剪出void
对应的变量
#include <stdio.h>
int main()
{
void var; // error
void array[3]; // error
void* pv;
return 0;
}
总结:不能定义void
类型的变量,可以定义void*
类型的指针
小贴士:
ANSI C:标准C语言的规范
扩展C:在ANSI C的基础上进行了扩充(如VS编译器,gcc编译器)#include <stdio.h> int main() { printf("%d\n", sizeof(void)); return 0; }
上述代码在ANSI C编译器中无法编译通过,但是对于支持GNU标准的gcc编译器而言是合法的。
4. void*
指针的意义
- C语言规定只有相同类型的指针才可以相互赋值
-
void*
指针作为左值用于接收任意类型的指针 -
void*
指针作为右值使用时需要进行强制类型转换
5. void*
作用—指针类型间的转换
#include <stdio.h>
#include <malloc.h>
/*
* MemSet(void* src, int length, unsigned char n) : 设置某一段内存中的每个字节为固定字符
* 在函数传递过程中不需要关心数组类型,因此用void*类型
*/
void MemSet(void* src, int length, unsigned char n)
{
unsigned char* p = (unsigned char*)src;
for(int i=0; i<length; i++)
{
p[i] = n;
}
}
int main()
{
int a[5];
MemSet(a, sizeof(a), 0);
for(int i=0; i<5; i++)
{
printf("%d\n", a[i]);
}
return 0;
}
输出结果:
0
0
0
0
0
6. 小结
- 现代软件工程中禁用
goto
语句 -
void
是一种抽象的数据类型 -
void
类型不能用于定义变量 -
void
类型用于声明函数无参数 -
void
类型用于声明函数无返回值 - 可以定义
void*
类型的指针 -
void*
类型的指针可以接收任意类型的指针值 -
void*
类型的指针可以作为指针类型转换的中间类型
声明:此文章为本人在学习狄泰软件学院《C语言深度解析》所做的笔记,文章中包含狄泰软件资料内容一切版权归狄泰软件所有!