【C语言进阶剖析】8、goto 和 void 分析

1、遭人遗弃的 goto

有一个项目经验:程序质量和 goto 的出现次数成反比。所以在程序中要尽量避免使用 goto

下面就通过一个实例分析一下 goto 的副作用

//8-1.c
#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(1)\n");
	func(1);
	printf("func(-1)\n");
	func(-1);
	printf("end...\n");
	return 0;
}

在这里插入图片描述

上面的程序如果 n 小于 0,程序直接goto STATUS,跳过 malloc,没有分配内存,p 为空指针,对 p[0] 赋值会导致程序崩溃。

2、void 的意义

2.1 void 作用

void 用于修饰函数返回值和参数。如果一个函数没有返回值,应该将其声明为 void;如果函数没有参数,应该将其声明为 void

小问题:函数没有返回值,直接不写返回值不就行了吗,函数没有参数,直接不写参数不就行了。
下面我们来尝试一下:

//8-2.c
#include<stdio.h>
f(){

}
int main(){
	int i = f(1,2,3);
	return 0;
}

在这里插入图片描述

对上面的结果:编译通过,运行通过,有一条警告,没有返回值默认为 int。
1、对于没有返回值类型的函数,默认返回值类型为 int
2、对于没有参数的函数,默认参数个数为任意个

所以,void 修饰函数返回值和参数是为了表示“无”,没有返回值类型,没有参数

C 语言没有定义 void 究竟是多大内存的别名,这个模子没有大小,所以在无法从内存中裁剪出 void 对应的变量。不存在 void 类型的变量,但是有 void 类型的指针。
比如:void var;void array[5] 是不合法的;void* p是合法的。

小贴士:C 语言规范包括两部分,1、ANSI C:标准 C 语言规范;2、扩展 C:在ANSI C基础上进行了扩充
不同公司在制作自己编译器的时候,对标准 C 语言规范做出了扩充看如下代码
#include<stdio.h>
int main(){
printf("%ld\n", sizeof(void));
return 0;
}
上面的代码在ANSI C编译器中无法通过编译,但是对于支持 GNU 标准的 gcc
编译器而言是合法的,打印结果为:1

2.2 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
pni = p;	// 	类型转换
p = pC;		// ok
pnc = p;	// 类型转换
//8-3.c
#include<stdio.h>
void MemSet(void* src, int length, unsigned char n){
	unsigned char* p = (unsigned char*)src;
	int i = 0;
	for (i = 0; i < length; i++){
		p[i] = n;
	}
}
int main(){
	int a[5];
	int i = 0;
	MemSet(a, sizeof(a), 0);
	for (i = 0; i < 5; i++){
		printf("%d\n", a[i]);
	}
	return 0;
}

在这里插入图片描述

对于上面的程序,函数的功能是把传入地址的每个字节的数值都变成 n, 为什么要把 src 定义为void* 类型的指针呢,因为传入的参数有多种类型,如int*, char*, double|* 等等,传入不同的指针类型,都可以操作。

3、小结

1、现代工程软件中禁用 goto 语句
2、void 是一种抽象的数据类型,不能用于定义变量
3、void 类型用于声明函数无参数,函数无返回值
4、可以定义void* 类型的指针,void* 类型的指针可以接受任意类型的指针值

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值