c语言学习笔记(2)goto,void,extern和sizeof分析

摘要: 分析了goto的副作用,void的意义,void的指针类型的意义和用法,实现了memset,总结了extern的意义和使用方法,最后分析了sizeof的意义和用法。


一、为什么不用goto

    因为goto有可能跳过我们程序中需要执行的部分,破坏了结构化程序顺序执行的思路,在现代c当中已经越来越少的使用goto,而且最好剔除掉。可以看下面一段程序:

<span style="font-size:24px;">#include <stdio.h>
 
void func(int n)
{
   int* p = NULL;
 
   if(  n < 0 )
    {
       goto STATUS;
    }
 
   
    p= malloc(sizeof(int) * n);
   
STATUS:
   p[0] = n;   
}
 
int main()
{ 
   f(1);
   f(-1);
   
   return 0;
}</span>

    在这个函数里面,当n=-1的时候,在p还未分配内存空间的时间,就直接跳转到了status,这样导致我们在给一个空指针赋值,会报错。goto会在大一点的程序里,程序员不经意的会跳过很多应有的操作,所以越好的程序员尽量不要使用goto。


二、void的意义

    void其实是用来修饰函数的返回值和参数,如果一个函数没有返回值,那么久修饰为void,如果函数没有参数,那么就声明其参数为void,void的作用仅仅是为了表示“无”

    c语言当中是不存在void变量的,c语言并没有定义void是多大内存的别名。虽然有时候使用sizeof(void),可以打印出1个字节,但是这并不代表void就是一个字节,使用g++进行编译的时候,就会报错。


二、void指针类型的意义

    c语言规定,只有相同类型的指针才能相互赋值,void* 用于左值可以接受任何类型的指针,void*用于右值赋值给其他指针时,需要强制转换类型。


三、void* 指针的使用

    使用void*指针实现一个自己的memset函数,对不同类型的内存进行清零或填充我们给定的值。函数如下:

<span style="font-size:24px;">#include <stdio.h>
 
void* my_memset(void* p,char v,int size)
{
     void* ret = p;
     char* dest = (char*)p;
     int i=0;
     
     for(i=0;i<size;i++)
     {
        dest[i]= v;
        }
       
     return ret;
    }
   
int main(void)
{
    inta[5] = {1,2,3,4,5};
    inti=0;
   
    for(i=0;i<5;i++)
    {
       printf("%d\n",a[i]);
       }
      
       my_memset(a,0,sizeof(a));
      
    for(i=0;i<5;i++)
    {
       printf("%d\n",a[i]);
       }  
      
      
    }</span>


    首先我们定义自己的memset函数,为void*类型,这里要传进去三个参数,分别是要初始化的内存的首地址,要填充的值和填充区域的大小,我们要想写一个能够初始化任意类型内存的函数,那么第一个参数使用了void*,它就可以接受任意类型的内存了.参数进来后,把初始化的内存的地址赋给ret,这里ret也是void*类型的,作为这个函数的返回值。但是我们为了验证左传值和右传值,在for循环里使用了dest,这是一个char*类型的指针,p在赋给它的时候,需要强制类型转换,下面便是对内存一次进行填充数据。

    主函数里面,对一个数组进行初始化与赋值,1,2,3,4,5,然后使用编写的my_memset对其进行清零,可以看到传进来的参数很方便,my_memset(a,0,sizeof(a));假如我们要初始化的是int类型的,unsigned char型的,一样可以使用。

编译运行之后的结果如下:

 

四、extern的意义

    extern用于声明外部定义的变量和函数,同时它也可以用于通知编译器,使用c的方式编译。某些c++编译器,会按照自己的规则去编译函数和变量,如果使用extern描述,那么就会通知编译器,请使用C的方式去编译。


五、extern使用分析

    extern声明外部变量和函数的用法前面已经总结了,这里总结的是通知编译器使用c的方式编译的方法。编写测试函数如下:

<span style="font-size:18px;">  
</span><span style="font-size:24px;">#include <stdio.h>
extern "C"
{
   int add(int a, int b)
    {
       return a + b;
    }
}
 
int main()
{ 
      int c = 0;
      c = add(2,3);
      printf("%d\n",c);
   return 0;
}</span>

    这里编写完成之后,我们使用gcc进行编译会报错,因为c里面是没有这个写法的,在c++和别的变种里面才有这种声明语句,可以使用g++编译,并且运行,得到的过程和结果如下:


六、sizeof的意义及用法

    其实sizeof是编译器内置的一个关键字和操作符,并不是一个函数!sizeof用来“计算”相应实体所占的内存大小,sizeof的值在编译期就已经确定了。sizeof后面在接变量的时候,可以不用括号,其余例如类型和函数,都需要括号。下面这个例子:

<span style="font-size:24px;">#include <stdio.h>
int main()
{ 
   int a;
   
   printf("%d\n", sizeof(a));
   printf("%d\n", sizeof a);
   printf("%d\n", sizeof(int));
   
   return 0;
}</span>

最终打印出来的值都是4,第二个打印处充分说明sizeof不是一个函数,而是一个关键字。

    这篇帖子就总结到这里,如有不正确的地方还请指出,大家共同进步!

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值