【C语言学习趣事】_32_平胸的尴尬,嫁不出去的姑娘
为什么写这篇文章呢? 为什么要弄这么个题目呢?
首先解释为什么用这个题目。这一切都要从那天在QQ群中的讨论说起,那天在群中,一个哥们问了一个关于(void)0 的问题。然后大家说到了
(void)0和(void*)0; 大家看看(void)0 和(void*)0 ,是不是一个像个平胸的小妹,一个像个丰韵的美女。
他问的的问题如下:
(void); //这个语句在C语句中可以执行吗?
我想了一下这个语句应该没有什么问题,在没有用(void)0,去影响内存对象的情况下,应该是可以的。下面是我在FC 14中进行测试的结果。
[volcanol@volcanol c]$ ls
a.out test.c
[volcanol@volcanol c]$ cat test.c
#include <stdio.h> int main(int argc,char** argv)
{
int test; test=; (void); getchar(); return ;
} [volcanol@volcanol c]$ gcc -Wall test.c
[volcanol@volcanol c]$
可以发现,编译过程没有警告和错误信息。
然后,我们就讨论是否可以将(void)0 赋值给其他的对象,于是我就修改了一下,将其改成赋值。
[volcanol@volcanol c]$ cat -n test.c
#include <stdio.h> int main(int argc,char** argv)
{
int test; test=(void); getchar(); return ;
}
编译输出信息:
[volcanol@volcanol c]$ gcc -Wall test.c
test.c: 在函数‘main’中:
test.c::: 错误:void 值未如预期地被忽略
可以看出,void类型不能通过隐式类型转换为int类型。
既然我们不能将void类型的值赋值,那么定义void类型的变量呢?
[volcanol@volcanol c]$ cat -n test.c
#include <stdio.h> int main(int argc,char** argv)
{
void test; test=(void); getchar(); return ;
}
编译器输出信息如下所示:
[volcanol@volcanol c]$ gcc -Wall test.c
test.c: 在函数‘main’中:
test.c::: 错误:变量或字段‘test’声明为 void
test.c::: 错误:void 值未如预期地被忽略
可以发现,不能将变量定义为void类型。
下面我们来讨论一下整个过程。
1、void类型
void表示为无类型,在 K&R C 里面有明确的说明。
因为不能在Linux下上传图片,所以就不上传图片里,可以到 K&R 第二版的 附录 A.6.7 查看相关的内容。
K&R C里面明确的指出: void类型对象的值不能以任何方式使用,也不能显式或者隐式的转换为非空类型。void类型表示
一个不存在的值,任何对象转换为void类型都将返回一个不存在的值,因此也就不能将void转换为其他非空类型。
2、void类型的作用
【1】声明函数不需要返回任何值
这个需要注意下面两个函数定义的差别:
getx(); //函数1 void getx(); //函数2
注意:函数1和函数2是两个不一样的函数。
【2】声明函数不需要传递任何
getx(); //函数1 getx(void); //函数2
注意:函数1和函数2 一样。
【3】返回void对象的表达式语句,作用和空语句一样。
(void)x; // 空对象表达式语句 ; //空语句
在编译的时候,编译优化后,这两个语句都不产生任何实际代码。
3、void* 类型
指向任何对象的指针都可以转换为void* 类型,而且在转换过程中不会丢失信息;一个被转换为void* 类型的指针可以转换为初始类型,
并且在转换的过程中不会丢失信息。
char *p="Hello world"; char *pVoid = (void*)p;
下面是我的测试代码:
[volcanol@volcanol c]$ cat -n test.c
#include <stdio.h> int main(int argc,char** argv)
{
char *p="Hello world"; char* pVoid=(void*)p; puts(pVoid); getchar(); return ;
} [volcanol@volcanol c]$ gcc -Wall test.c
[volcanol@volcanol c]$ ./a.out
Hello world
可以看到,这样的结果符合原本的定义。 分析代码中的第7行语句, 首先将p指针显式的转换为(void*); 然后再将空类型指针(void*)p隐式的转换为char*, 可以看到
这个过程没有丢失信息。
这里我们可以看到: 挺拔的void*可以任意的和别人交往,而平胸的void成了嫁不出去的姑娘。
4、关于void* 变量和常量
在C语言库中,预定义了一个常量:NULL; 通常是如下定义的:
#define NULL ((void*)0)
这个常量可以赋值给任意类型的指针。例如:
char* p=NULL;
这个语句在编译时不会出错,当然如果程序中不再对p进行再赋值,这个指针p通常也不能进行操作,例如此时不能用于puts(p);
这里还需要说一个特别的事情,就是关于0这个常量在C 语言中的应用,这个在获取结构体变量的成员offset地址非常有用。
[volcanol@volcanol c]$ cat -n test.c
#include <stdio.h> struct testType
{
int x;
char y;
struct testType *z;
}; int main(int argc,char** argv)
{ int x=((size_t)&((struct testType*))->y); printf("%d",x); getchar(); return ;
} [volcanol@volcanol c]$ gcc -Wall test.c
[volcanol@volcanol c]$ ./a.out
这里内存地址0,可以引用为任意指针类型,这个内存地址是不允许应用程序引用的,这也就是如果将一个指针赋值为NULL后不能引用的原因。
关于void* 变量,在网络上盛传一篇文章: http://wenku.baidu.com/view/22c4b8d86f1aff00bed51edc.html,
这篇文章中对void* 指针某些描述,实际上是用某个平台的某个编译的特殊情况来描述的,存在一些偏颇之处,例如文章中说
但这并不意味着,void *也可以无需强制类型转换地赋给其它类型的指针。因为“无类型”可以包容“有类型”,而“有类型”则不能包容“无类型”。道理很简单,
我们可以说“男人和女人都是人”,但不能说“人是男人”或者“人是女人”。下面的语句编译出错:
而且和多人还对里面的说法深信不疑, http://www.cnblogs.com/ComputerG/archive/2012/02/22/2363165.html
下面的这个链接对void* 指针的描述比较详细: http://learn.akae.cn/media/ch23s01.html
我们可以看下面的代码和执行情况:
[volcanol@volcanol c]$ cat -n test.c
#include <stdio.h> int main(int argc,char** argv)
{
char *p="Hello world"; void* pVoid=(void*)p; puts(pVoid); getchar(); return ;
} [volcanol@volcanol c]$ gcc -Wall test.c
[volcanol@volcanol c]$ ./a.out
Hello world
实际上: void* 指针也是一个指针,具有普通指针的某些特性,例如 sizeof(void *)具有和sizeof(char *)一样的大小,也就是说,void* 变量同样占用4个字节(32位系统),这个
内存位置,同样可以存储一个内存地址。而设置void*的一个目的就是无需进行显式地址转换就可以将void* 指针转换为其他任意指针, 因为最初的时候,是用char* 做这个功能的。
这样每一次进行转换的时候,都必须将char* 指针进行强制类型转换。
这个地方,就不再细说了,在C语言中,(void)0注定有平胸姑娘的尴尬,成了嫁不出去的姑娘。
文章的内容,均为一孔之见,如果有不同意见,欢迎拍砖。 另外,前两次有朋友说要我的电子书,这里我不太方便上传,如果您需要电子书,可以加我QQ,我的QQ在博客园
中的个人信息里面添了,加的时候请说明是要电子书的,我会根据您的需要给你传,要我上传,我的书太多(达50G之多,很多种类的,不只是计算机的,有需要的都可以索要)。
【C语言学习趣事】_32_平胸的尴尬,嫁不出去的姑娘的更多相关文章
- 【C语言学习趣事】_33_关于C语言和C++语言中的取余数(求模)的计算_有符号和无符号数的相互转换问题
最近再次复习C++语言,用的教材是<C++ Primer>这本教材, 看到第二章的时候,里面有个问题困扰了我. 于是想上网查查怎么回事, 结果看了很久都没有得到一个满意的答案. 书上有这么 ...
- GO语言学习(二)Windows 平台下 LiteIDE 的安装和使用
1. 安装 Go 语言并设置环境变量 参考GO语言学习(一) 2. MinGW 的下载和安装 Windows 下的 Go 调试还需要安装 MinGW. 2.1 下载安装工具的安装 最新版本下载安装工具 ...
- 20165316 技能学习心得与c语言学习
20165316 技能学习心得与c语言学习 一.技能学习经验 我会打乒乓球,在中国,我只能说我"会"打,至于"比大多数人更好"我不敢断言,因为我无时无刻不感受到 ...
- C语言学习 第八次作业总结
本次作业其实没有新的内容,主要就是复习上一次的一维数组的相关内容.冯老师布置了5道题目,其中涉及到一些比较简单的排序或者是查找的方法.因为数据很少,所以直接使用for循环遍历就可以了. 关于本次作业, ...
- C语言学习 第七次作业总结
C语言学习 第七次作业总结 数组可以分为数组和多下标数组(在传统的国内C语言书本中,将其称为二/多维数组). 数组名称 在之前的课程中,大家应该都有印象,对于int a这样的定义,会为变量 a 声明一 ...
- 技能收获与C语言学习
你有什么技能比大多人(超过90%以上)更好? 我会的东西很多,喜欢的东西太多,但是很遗憾广而不专,会而不精.学了很多东西我都是为了娱乐,因为以前我们那里过于强调学习,很多爱好也都被扼杀在摇篮里.我觉得 ...
- 一份关于Swift语言学习资源的整理文件
一份关于Swift语言学习资源的整理文件 周银辉 在这里下载 https://github.com/ipader/SwiftGuide
- go语言学习笔记
Go语言学习基本类型Bool 取值范围:true,false (不可以用数字代替)Int/uint 根据平台可能为32或64位int8/uint8 长度:1字节 取值范围-128~127/0~255b ...
- 20155206赵飞技能获取经验,C语言学习感想与对JAVA的学习目标
自己较强的技能获取经验. 1:实话实说我自己是没有哪个技能可以超过90%的人的,只有自认为做的还可以的一些事情,例如打篮球,office软件的应用,一百米跑.至于其他方面就是很平庸了. 2:经验主要有 ...
随机推荐
- 说说设计模式~策略模式(Strategy)
返回目录 策略模式定义了一系列的算法,并将每一个算法封装起来,而且使它们还可以相互替换.而对于客户端(UI)来说,可以通过IOC再配合工厂模块,实现动态策略的切换,策略模块通常于一个抽象策略对象(in ...
- Oracle Redo 以及 Archived日志简述
Oracle通过Redo Archived实现数据的归档 什么是Redo日志 Redo日志记录了数据的变更,用于在数据库出现故障后,进行数据恢复. 功能主要由三个组件实现:Redo Log Buffe ...
- Atitit 五种IO模型attilax总结 blocking和non-blocking synchronous IO和asynchronous I
Atitit 五种IO模型attilax总结 blocking和non-blocking synchronous IO和asynchronous I 1.1. .3 进程的阻塞1 1.2. 网络 ...
- GitHub & Bitbucket & GitLab & Coding 的对比分析
目前基于 Git 做版本控制的代码托管平台有很多种,比较流行的服务有 Github.Bitbucket. GitLab. Coding,他们各自有什么特点,个人使用者和开发团队又该如何选择? 在这篇文 ...
- WPF仿Win7便笺
最近用WPF写了个仿WIN7下面的便笺小工具,还算是比较华丽的,相似度99%以上吧,在集成了便笺原有的功能以外,当然也做了略微的修改,比如加了关于作者版本信息和修改了原有删除便笺的系统弹出框.软件开机 ...
- salesforce 零基础开发入门学习(九)Approval Process 介绍
在阅读此篇文章前,可以先参考阅读一个前辈总结的关于Approval Process的操作.以下为参考的链接: http://www.cnblogs.com/mingmingruyuedlut/p/37 ...
- TextView 显示内容时出现 ArrayIndexOutOfBoundsException 的解决方法(Android 4.1)
很久以前做的表情输入及显示,用的系统的SpannableString,完成后的代码在其他版本的Android手机上没有问题,但是在在4.1和4.1.1的手机上显示时,有概率出现程序崩溃的问题. 下面是 ...
- 让 “微软雅黑” 在IE6下完美显示
微软雅黑可以说是网页中最常见的字体了,但是往往在IE8+的浏览器上调试得很好,到了IE6则会变成默认的"宋体". 因为宋体字体宽度通常比雅黑的要宽,有时候会把页面都布局挤乱. 为了 ...
- android target unknown and state offline解决办法
没有错,将adb的版本升级一下就好了! 下载地址为:http://files.cnblogs.com/files/hujunzheng/adb1.0.32.zip
- spring源码分析之spring-core-io
1. 看一下源码整体结构: 抓住主要点Resource.ResourceLoader和ResourceEditor 其中Resource作用 Interface for a resource desc ...