摘要: 分析了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不是一个函数,而是一个关键字。
这篇帖子就总结到这里,如有不正确的地方还请指出,大家共同进步!