C语言详细分析讲解关键字goto与void的作用

目录
  • 一、关于goto
  • 二、void 的意义
  • 三、小结

一、关于goto

  • 高手潜规则:禁用 goto
  • 项目经验:程序质量与 goto 的出现次数成反比
  • 最后的判决:将 goto 打入冷宫

下面看一段 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(1)\n");

    func(1);

    printf("func(-1)\n");

    func(-1);

    printf("end...\n");

    return 0;
}

下面为输出结果:

这段代码中当 func 的入口参数 n 的值小于 0 时,就会 goto 到STATUS 那里去执行代码,但是由于跳过了分配内存环节,就不能把 n 的值赋给 p[0],强行赋值就会发成段错误。

二、void 的意义

void 修饰函数返回值和参数

  • 如果函数没有返回值,那么应该将其声明为 void
  • 如果函数没有参数,应该声明其参数为 void

void 修饰函数返回值和参数是为了表示“无”

下面这段代码就表示 f 函数的输入参数没有限制。

不存在 void 变量

  • C语言没有定义 void 究竟是多大内存的别名
  • 没有 void 的标尺
  • 无法在内存中裁剪出 void 对应的变量

在下面的代码中,只有 void* 那条语句可以编译通过,因为 void* 指针是合法的。

小贴士

  • ANSI C:标准 C 语言的规范
  • 扩展C:在 ANSI C 的基础上进行了扩充

上面的代码在 ASNI C编译器中无法通过编译,但是对于支持 GNU 标准的 gcc 编译器而言是合法的。

void 指针的意义

  • C 语言规定只有相同类型的指针才可以相互赋值
  • void* 指针作为左值用于“接收”任意类型的指针
  • void* 指针作为右值使用时需要进行强制类型转换

下面看一段通过 void* 实现 MemSet 函数的代码:

#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;
}

下面为输出结果:

void* 定义的 src 表示可以接收任意类型的指针,所以数组 a 可以是任意类型。

三、小结

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

到此这篇关于C语言详细分析讲解关键字goto与void的作用的文章就介绍到这了,更多相关C语言goto与void内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • C语言goto语句简单使用详解

    简单介绍 C语言中提供了可以随意滥用的 goto语句和标记跳转的标号.从理论上 goto语句是没有必要的,实践中没有goto语句也可以很容易的写出代码.但是某些场合下goto语句还是用得着的,最常见的用法就是终止程序在某些深度嵌套的结构的处理过程,例如一次跳出两层或多层循环.这种情况使用break是达不到目的的.它只能从最内层循环退出到上一层的循环. 语法 C 语言中 goto 语句的语法: goto label; .. . label: statement; 示例对比 #include<std

  • 详解C语言的void*空指针

    目录 void的应用 空指针类型(void*) 总结 在C语言中,void称为无类型,相应的void*称为无类型指针或者空指针类型. void的应用 对函数返回值的限定. 例如void func(int);该函数没有返回值.对函数参数类型的限定. 例如int func(void);该函数没有参数,不允许接收参数. 空指针类型(void*) 空指针类型的变量void* pvoid;可以指向任意类型的数据,任何类型的指针也可以直接赋值给空指针类型的变量. #include <stdio.h> in

  • C语言详细分析讲解关键字goto与void的作用

    目录 一.关于goto 二.void 的意义 三.小结 一.关于goto 高手潜规则:禁用 goto 项目经验:程序质量与 goto 的出现次数成反比 最后的判决:将 goto 打入冷宫 下面看一段 goto 副作用分析的代码: #include <stdio.h> #include <malloc.h> void func(int n) { int* p = NULL; if( n < 0 ) { goto STATUS; } p = (int*)malloc(sizeof

  • C语言详细分析讲解关键字enum与sizeof及typedef的用法

    目录 一.枚举类型的使用方法 二.sizeof 关键字的用法 三.typedef 的意义 四.小结 一.枚举类型的使用方法 enum 是 C 语言中的一种自定义类型 enum 值是可以根据需要自定义的整型值 第一个定义的 enum 值默认为 0 默认情况下的 enum 值是在前一个定义值的基础上加 1 enum 类型的变量只能取定义时的离散值 enum 中定义的值是C语言中真正意义上的常量 在工程中 enum 多用于定义整型常量 下面看一段 enum 的使用代码吧: #include<stdio

  • C语言详细分析讲解关键字const与volatile的用法

    目录 一.const 只读变量 二.const 全局变量的分歧 三.const 的本质 四.const 修饰函数参数和返回值 五.volatile 解析 六.小结 一.const 只读变量 const 修饰的变量是只读的,本质还是变量 const 修饰的局部变量在栈上分配空间 const 修饰的全局变量在全局数据区分配空间 const 只在编译期有用,在运行期无用 const 修饰的变量不是真的常量,它只是告诉编译器该变量不能出现在赋值符号的左边. 二.const 全局变量的分歧 在现代C语言编

  • C语言详细分析讲解多文件的程序设计

    目录 一.多文件与编译器链接 二.多文件之间的相互访问 三.关于#include 四.头文件使用的一些原则 五.再论全局变量 六.注意事项 七.实验程序 八.小结 一.多文件与编译器链接 如下图所示,.o 为目标文件,链接器将不同的目标文件装配组合在一起形成一个可执行文件. 二.多文件之间的相互访问 每个文件可以定义功能接口(可被其它文件访问的函数或数据) 源文件:代码实现文件,后缀为.c 头文件:源文件的接口定义文件,后缀为.h 当需要使用其它文件提供的功能时,包含对应的头文件 语法: #in

  • C语言详细分析讲解流程控制语句用法

    目录 一.分支语句 1.if语句 2.switch语句 二.循环语句 1.for语句 2.break和continue语句 3.循环嵌套 4.while和do…while语句 一.分支语句 1.if语句 流程控制语句可以让程序中的语句不再从上到下逐条执行 分支是一种流程控制语句,可以把程序中某些语句忽略掉不去执行 if关键字可以用来编写分支语句,只有当表达式为真时,才会执行对应语句 如果多个分支的逻辑表达式之间存在互斥关系,则可以采用else关键字把他们合并成一个分支语句 一个分支语句中的多个逻

  • C语言详细分析讲解struct与union使用方法

    目录 一.struct 的小秘密 二.结构体与柔性数组 三.C语言中的 union 四.小结 一.struct 的小秘密 C语言中的 struct 可以看作变量的集合 struct 的问题:空结构体占用多大内存?下面编写程序看一下吧: #include <stdio.h> struct TS { }; int main() { struct TS t1; struct TS t2; printf("sizeof(struct TS) = %d\n", sizeof(stru

  • C语言详细分析讲解内存管理malloc realloc free calloc函数的使用

    目录 C语言内存管理 一.动态空间申请 二.动态空间的扩容 三.释放内存 C语言内存管理 malloc && realloc && free && calloc c语言中为了进行动态内存管理,<stdlib.h>中提供了几个函数帮助进行内存管理. 我们知道,C语言中是没有C++中的容器或者说是python中list,set这些高级的数据结构的,我们一旦申请了一段内存空间以后这一段空间就归你了,比如我们举个例子,我们申请一个数组 int nums[

  • Java超详细分析讲解final关键字的用法

    目录 基本介绍 final细节01 final细节02 基本介绍 final 可以修饰类.属性.方法和局部变量. 在某些情况下,程序员可能有以下需求,就会使用到final: Base Sub 类 1)当不希望类被继承时,可以用final修饰. 2)当不希望父类的某个方法被子类覆盖/重写(override)时,可以用final关键字 修饰.[案例演示:访问修饰符 final 返回类型方法名] 3)当不希望类的的某个属性的值被修改,可以用final修饰.[案例演示: public final dou

  • C++详细分析讲解函数参数的扩展

    目录 一.函数参数的默认值 二.函数占位参数 三.小结 一.函数参数的默认值 C++ 中可以在函数声明时为参数提供一个默认值 当函数调用时没有提供参数的值,则使用默认值 参数的默认值必须在函数声明中指定 下面看一段代码: #include <stdio.h> int mul(int x = 0); int main(int argc, char *argv[]) { printf("%d\n", mul()); printf("%d\n", mul(-1

  • Java超详细分析讲解哈希表

    目录 哈希表概念 哈希函数的构造 平均数取中法 折叠法 保留余数法 哈希冲突问题以及解决方法 开放地址法 再哈希函数法 公共溢出区法 链式地址法 哈希表的填充因子 代码实现 哈希函数 添加数据 删除数据 判断哈希表是否为空 遍历哈希表 获得哈希表已存键值对个数 哈希表概念 散列表,又称为哈希表(Hash table),采用散列技术将记录存储在一块连续的存储空间中. 在散列表中,我们通过某个函数f,使得存储位置 = f(关键字),这样我们可以不需要比较关键字就可获得需要的记录的存储位置. 散列技术

随机推荐