在内存空间中,
1. 单位大小的数据 叫 数值 . 比如 int a; char b; ...
2. 由这些单位数据组合起来的内存, 称作 空间. 比如: 各种数组char/int a[10]; 结构体... 空间以数组为例.又分为:
2.1 字符空间
2.2 非字符空间
对于 数值 做参数有两种方法:
值传递: 只是拷贝数据副本, 不会对原有数据进行篡改. (保护数据)
地址传递:. 传递数值的地址, 目的在于对原有的数据进行修改 . (灵活使用)
对于 空间 来说, 设计参数的时候,只用地址传递. 因为值传递的副本拷贝是非常缓慢而且浪费内存空间的操作 .
再次提一下 字符空间 和 非字符空间 的区别.
内存分为字符空间和非字符空间 .
字符空间 只有一种情况,那就是 由 char 组成,能转换成字符的内存空间.
唯一表达: char buf[10] --> char *buf
非字符空间 纯粹只是记录由0 1 组成的数据,由 char int float ...
最特殊的就char 大小的数组.
假设有一个char大小的非字符空间用来保存buf,所以定义成 char buf[10] ,,,但是,这不是和 字符空间的表达形式冲突了
所以定义非字符空间 中 char 的表达形式:
unsigned char buf[10]
字符空间与非字符空间小结:
数据定义 | 形参设计 | |
字符空间(唯一) | char buf [10] | char *buf |
非字符空间 | unsigned char buf[10]; int buf[10]; ... | unsigned char *buf; int *buf;... -->(void *) |
空间传递:
1. 下级函数只是读取空间的内容,并不修改空间里面的数据:
const char *buf 传达的是对数据进行一种保护,数据由上层传递到下层函数只是只读,并不修改 .
2. 子函数反向修改上层空间里面的内容
2.1 字符空间
2.2 非字符空间
func(char *p){
while(*p != 0){
*p = xx;
yy = *p;
p++;
}
}
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
int strlen( const char *str ){ //不希望改变传进来的空间,所以加上const
int len;
//1. 错误处理
if( str == NULL ){
return -1;
}
//2.操作
while( *str != 0 ){
len++;
str++;
}
return len;
}
void func( unsigned char *p, int len){ //首地址和 长度共同限制
int i;
for(i = 0; i<len; i++){
//xxxxx
}
}
但是这样子存在数据匹配的问题,(略)
所以,我们在想有没有一种表达形式来表示所有非字符空间呢,于是引进了 空指针 void *
于是:
字符空间 形参特征式 char *buf
非字符空间 形参特征式 void *buf
[ 看见 char *buf 就想到这是字符空间,带结束符
看见 void *buf 就想起这是非字符空间,靠数量规定结束符 ]
void func (void *p){ //强转 unsigned char *tmp = (unsigned char *)p; //使用 tmp[1] = xx; *(tmp+1) = xx; }
最后 int *p 和 void *p的区别:
因为我们在传递一个单一数值的时候有值传递和地址传递
int a 的地址传递的形参就是 int *a;
但是空指针的前身 非字符空间里面也有一种指针 int *buf
所以,在参数设计的时候,
对于
unsigned char *a; int *a; float *a ...等等,表达的是非字符串的 单一数据 的地址传递
而它们升级后的空间传递 均用 void * 来中转.