1、数据类型的本质,固定大小内存块的别名:如64位系统 int类型占8个字节,本质上int表示内存块为8个字节的集合。
int a; //表示申请了一块占8个字节的内存,用a表示,但并不占用实际的内存,只有真正使用的时候才会占用物理内存。
变量的本质是一段连续内存空间的别名,是一个门牌号,通过变量来操作内存,对内存可读可写,通过变量往内存中读写数据。
2、数据类型转换:强制转换和自动转换
程序员显式进行的转换称为强制类型转换:
- (float) a; //把a转换为实型
- (int)(x+y); //把x+y的结果转换为整型
- (float) 100; //将一个常量转换为实型
自动转换的规则:
- float PI=3.14159;
- int r=5;
- double s2;
- s1 = r*r*PI; //s1=5
- s2 = r*r*PI; //s2=78.539753
① void的字面意思是“无类型”,void *则为“无类型指针”,void *可以指向任何数据类型的指针。
② void修饰的函数返回值和参数,表示是无,如果函数没有返回值,应该将函数声明为void类型,如果函数没有参数,应该将函数括号中用void来明确表示。
③ void指针的含义,C语言规定,只有同种类型的指针才能进行赋值,void* 作为左值的时候,可以接收任何类型的指针,void* 作为右值的时候,需要进行强制类型转换。
④ 不存在void类型的变量,在C语言中,没有定义void应该分配多大的内存。
4、数组类型:本质就是申请一组相同数据类型大小的内存块切是连续的数组长度计算:
可以使用sizeof求数据类型的大小。
一维数组: sizeof(数组名) / sizeof(数组类型);
二维数组: 列数:sizeof(二维数组名[0]) / sizeof(类型) 行数: sizeof(二维数组名) / sizeof(而数组名[0])
数组名代表数组首元素的地址
数组首元素的地址,&代表整个数组的地址。
数组指针和指针数组
指针数组:首先它是一个数组,数组的元素都是指针,数组占多少个字节由数组本身决定。它是“储存指针的数组”的简称。
数组指针:首先它是一个指针,它指向一个数组。在64 位系统下永远是占48个字节,至于它指向的数组占多少字节,不知道。它是“指向数组的指针”的简称。
下面到底哪个是数组指针,哪个是指针数组呢:
A)
int *p1[10];
B)
int (*p2)[10];
这里需要明白一个符号之间的优先级问题。
“[]”的优先级比“*”要高。p1 先与“[]”结合,构成一个数组的定义,数组名为p1,int *修饰的是数组的内容,即数组的每个元素。那现在我们清楚,这是一个数组,其包含10 个指向int 类型数据的指针,即指针数组。至于p2 就更好理解了,在这里“()”的优先级比“[]”高,“*”号和p2 构成一个指针的定义,指针变量名为p2,int 修饰的是数组的内容,即数组的每个元素。数组在这里并没有名字,是个匿名数组。那现在我们清楚p2 是一个指针,它指向一个包含10 个int 类型数据的数组,即数组指针。我们可以借助下面的图加深理解:
通过变量修改内存的方法有两中,一种是直接进行修改内存,另外一种是间接修改内存。
如果想要间接修改内存中的值,应该拿到这个内存的地址,然后强制转换成为对应类型的指针的地址,然后在通过*来操作这块内存。
64位环境下各个类型的大小:
size_t : 8 bytes
void * : 8 bytes
char : 1 bytes
short: 2 bytes
int : 4 bytes
long : 8 bytes
long long : 8 bytes
float: 4 bytes
double : 8 bytes
long double: 16 bytes
ssize_t: 8 bytes
off_t : 8bytes