C进阶8goto和void分析

Posted bryson

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了C进阶8goto和void分析相关的知识,希望对你有一定的参考价值。

Summary

1) 一般工程开发中需要禁用goto语句,不同的编译器对goto语句的错误处理可能不同。

2)在C语言中,如果函数没写返回值,则默认返回值类型是int;如果函数没有写参数列表,则函数接受任意数量的参数
因此,如果函数没有返回值,必须显式声明返回值类型为void;如果函数没有参数,则必须声明参数列表为void。

3)void是一种基础类型,但不是基础数据类型,所以无法用来定义变量(C语言没规定void是多大内存空间的别名)。

4)对于标准C语言规范,不允许sizeof(void)这种写法,如bcc编译器;对于扩展C语言,可能允许sizeof(void)这种写法,如gcc编译器,输出为1。

5)void*指针的主要作用是:用于接收任意类型的指针。在C语言中,void*type*可以相互转换;在C++中,void*可以作为左值接收任意类型的指针,作为右值时,必须进行强制类型转换

goto和void

1、goto

goto语句带有很浓厚的汇编语言特性,能够跳转到指定的语句,如同汇编语言的跳转指令。
在工程实践中,一般都禁用“goto”。goto会破坏程序的结构,带来意想不到的错误

// 代码示例:以下代码输出什么?

int main()
{
goto End;
    int i = 0;
End:
    printf("i = %d\\n", i);
    return 0;
}
  • gcc编译器:编译错误error,提示i变量的初始化被跳过了。
  • vs编译器:编译警告warning,提示i未初始化,但是编出了可执行程序。运行的结果是随机值,意料之外的错误!

2、void

2.1 void修饰返回值和参数

在C语言中:

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

注意, C语言中:

  • 如果函数没写返回值,默认的返回值类型是int
  • 如果函数没有声明参数列表,默认接受任意多参数

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

2.2 是否存在void类型的变量?

结论:不存在void类型的变量

void是一种基础类型,但不是基础数据类型;C语言中没有定义void究竟是多大内存的别名,所以也无法定义对应的变量。

int main()
{
    void var;        // error
    void arr[5];     // error

    return 0;
}

小贴士:

  • ANSI C:标准C语言规范,如bcc编译器
  • 扩展C:在ANSI C的基础上进行了扩展,如gcc编译器

    // void类型有大小么?
    
    int main()
    {
      prinft("%d\\n", sizeof(void));
      return 0;
    }
  • gcc编译器,Demo可以编过,输出为1
  • bcc编译器,编译错误,提示void是不允许的类型。

2.3 void类型的指针

  • 在C语言中,对指针类型的检查不那么严格,所以void类型的指针可以和任意数据类型的指针进行相互转换

    // test.c
    int main()
    {
      int* p = nullptr;
    
      void* pv = p;         // ok
      
      char* pc = pv;        // ok
      return 0;
    }
  • 在C++语言中,对类型进行了增强,同事也兼容了C语言中的写法。void可以作为左值接受任意类型的指针,但是,void作为右值时,就必须进行强制类型转换

    // test.cpp
    
    int main()
    {
      void* pv = nullptr;        // 初始化是个好习惯
      
      int* pi = pv;          // error, invalid conversion from void* to int*
      int* pi = (int*)pv;    // ok, due to cast
    
      return 0;
    }

总结:void*指针的主要作用是,用于接收任意类型的指针
示例Demo:将数组所占内存全部置0

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

本文总结自“狄泰软件学院”唐佐林老师《C语言进阶课程》。
如有错漏之处,恳请指正。

以上是关于C进阶8goto和void分析的主要内容,如果未能解决你的问题,请参考以下文章

我的C语言学习进阶之旅解决 Visual Studio 2019 报错:错误 C4996 ‘fscanf‘: This function or variable may be unsafe.(代码片段

C语言进阶指针的进阶

我的C/C++语言学习进阶之旅解决使用algorithm库里面的sort函数的时候,编译报错:未能使函数模板“unknown-type std::less<void>::operator ()(代码片

我的C/C++语言学习进阶之旅解决使用algorithm库里面的sort函数的时候,编译报错:未能使函数模板“unknown-type std::less<void>::operator ()(代码片

C语言进阶数据的存储

嵌入式进阶必看!7个硬核的 C 语言要点