int a[] = {1,2,3,4};
//printf("%d\n", sizeof(arr));//16 sizeof求的是字节,一个int类型占四个字节。
//printf("%d\n", sizeof(arr + 0));//4 当前由于数组名参与了+0的运算,隐式转成了指针。
//printf("%d\n", sizeof(*arr));// 4 当前arr参与*运算,也隐式转成了指针int* ,针对int*解引用,结果是一个int
//printf("%d\n", sizeof(arr + 1));//4 当前由于数组名参与了+1的运算,隐式转成了指针。
//printf("%d\n", sizeof(arr[1]));//4 arr是数组,[1]取到下标为1的元素,是一个int
//printf("%d\n", sizeof(&arr));//4 &arr是一个数组指针,int(*)[4],只要是指针
//不管是什么指针,都是占四个字节.指针里面存放的都是地址。
//printf("%d\n", sizeof(*&arr));//16 &arr得到一个数组指针,int(*)[4],然后针对这个数组指针*操作,
//结果就得到了一个int [4]
//printf("%d\n", sizeof(&*arr));//4 当前arr是int [4],*a,其实就是先把a转成一个int*,
//然后*得到了一个int.然后又取地址,又得到了一个int*
//printf("%d\n", sizeof(&arr + 1));//4 &arr是一个数组指针,int(*)[4],再+1,仍然是int(*)[4]
//printf("%d\n", sizeof(&arr[0]));// 4 arr是一个int[4],arr[0]是int,再&就是int*
//printf("%d\n", sizeof(&arr[0] + 1));//4 arr是一个int[4],arr[0]是int,再&就是int*,再+1仍然是int*
只要在算指针的sizeof,都是4;
数组名,在很多情况下会隐式转成指针类型;(指向数组首元素的指针)
1.函数调用
2.参与运算(+-,*,==,<,>,>=......)
字符串和字符数组不一样,并不是等价关系。
字符串是一种特殊的字符数组,里面必须带\0;
如果没有带\0,就绝对不是字符串。
sizeof是在求一个变量在内存中占几个字节。
strlen是在求一个字符串的长度。(从传入字符串的起始位置开始,找\0)
sizeof与strlen是没有任何关系的!
unsigned
printf("%d\n",strlen(*arr));
在函数调用的时候,需要保证形参和实参是类型是匹配的。
char与const char*不匹配。按理说应该要编译出错,但是在C语言中存在隐式类型转换。就会在传参的时候尝试把char转成const char*.相当于把‘a’这个ASCIL当成了一个具体的地址了。(这个地址是非法地址,尝试读取这个地址,就容易出现未定义行为)。
int main(){
char arr[] = { 'a','b','c','d','e','f' };
//printf("%d\n", sizeof(arr));//6 没有\0
//printf("%d\n", sizeof(arr+0));//4 arr本来是char[6],但是进行了+0操作,就隐式转成了char*是一个指针
//printf("%d\n", sizeof(*arr));//1 arr是char[6],本来是一个数组,但是在*运算中也隐式转成了char*
//针对char*进行*解引用,结果就变成了char
//printf("%d\n", sizeof(arr[1]));//1 arr是char[6]进行[1]操作,就得到了char ‘b’
//printf("%d\n", sizeof(&arr));//4 arr本来是arr[6],进行&运算之后,就得到了char(*)[6] 是一个数组指针。
//printf("%d\n", sizeof(&arr+1));//4 arr本来是arr[6],进行&运算之后,就得到了char(*)[6] 再+1,
//仍然是char(*)[6]
//printf("%d\n", sizeof(&arr[0] + 1));//4 arr[0]得到字符‘a’,然后&,变成了char* char*+1,
//依然还是char*,是一个指针
//代码中永远不能依赖未定义行为。
//printf("%d\n", strlen(arr));//未定义行为,arr没有\0,进行strlen就会出现数组下标越界的情况。
//printf("%d\n", strlen(arr + 0)); //未定义行为
//printf("%d\n", strlen(*arr));//未定义行为 arr是char[6],*arr得到的是char,‘a’这个字符
//把‘a'的ASCIL的值对应的内存。
//printf("%d\n", strlen(arr[1]));//同上,这次访问的是‘b’的ASCIL的值对应的内存。
//printf("%d\n", strlen(&arr)); //未定义行为 得到的是char(*)[6],是一个数组指针。
//虽然和形参类型不同,但是大家都是指针,里面存的地址相同,这个时候也就相当于是从‘a’地址开始往后找\0
//printf("%d\n", strlen(&arr + 1));//未定义行为 得到的是char(*)[6],是一个数组指针,再+1,
//仍然还是数组指针,指针+1,地址就跳过一个元素。这一跳就把整个数组元素都给跳过了。
printf("%d\n", strlen(&arr[0] + 1));//
char(*)[6]和char(*)[7]是不同类型的。指针的类型是描述房间的大小。
int main(){
//“”本身已经是字符串了,本身里面已经有\0了。
//得到的arr应该是一个char[7].
char arr[] = "abcdef";
//printf("%d\n", sizeof(arr));//7
//printf("%d\n", sizeof(arr + 0));//4 相当于隐式转成了char*
//printf("%d\n", sizeof(*arr));// 1 *arr得到的是‘a’,char
//printf("%d\n", sizeof(arr[1]));//1 'b',char
//printf("%d\n", sizeof(&arr));// 4 arr得到的是 char[7],&得到char(*)[7]数组指针。
//printf("%d\n", sizeof(&arr + 1));//4 同上
//printf("%d\n", sizeof(&arr[0] + 1));//4 char[0]得到的是char,再&得到char*
int main(){
//“”本身已经是字符串了,本身里面已经有\0了。
//得到的arr应该是一个char[7].
char arr[] = "abcdef";
//printf("%d\n", strlen(arr));//6 计算strlen的时候不计算\0;
//printf("%d\n", strlen(arr + 0));//6
//printf("%d\n", strlen(*arr));//未定义行为,*arr得到的是‘a’,char,不是const char*
//printf("%d\n", strlen(arr[1]));//未定义行为,得到的是‘b’
//printf("%d\n", strlen(&arr));//6 得到的是数组指针,char(*)[7]和形参要求的const char*不同的。
//虽然类型不匹配,但是结果碰巧是对的。
//printf("%d\n", strlen(&arr + 1));
//printf("%d\n", strlen(&arr[0] + 1));//5 arr[0]得到字符‘a’,再&得到的了指向‘a’的指针。
//+1就得到了指向‘b’的指针,从'b'开始找\0
指针的[]相当于*解引用的简化写法
int main(){
char* p = "abcdef";
//printf("%d\n", sizeof(p));//4 char*类型
//printf("%d\n", sizeof(p + 1));//4 还是char*类型
//printf("%d\n", sizeof(*p));//1 是char类型
//printf("%d\n", sizeof(p[0]));//1 指针同样也支持[]操作,p[0]相当于*(p+0)
//指针的[]相当于*解引用的简化写法。
//printf("%d\n", sizeof(&p));//4 p是char*,&p之后的类型是char**;
//printf("%d\n", sizeof(&p + 1));//4 char**+1还是char**
//printf("%d\n", sizeof(&p[0] + 1));//4 p[0]得到char, &char得到的是char*
//printf("%d\n", strlen(*p));//未定义行为,*arr得到的是‘a’,char,不是const char*,
// 从'a'开始找\0,但是97是没有申请到地址,strlen需要的是char*类型。
// 原则上讲是不应该编译通过的,但是c语言对于类型的检查是不严格的。
// strlen就会尝试从‘a’的ASCIL这个地址开始找\0
/*char* p = "abcdef";*/
//printf("%d\n", strlen(p));//6 从a开始找\0
//printf("%d\n", strlen(p + 1));//5 从b开始找\0
//printf("%d\n", strlen(*p));//未定义行为,*arr得到的是‘a’,char,不是const char*,
// 从'a'开始找\0,但是97是没有申请到地址,strlen需要的是char*类型。
// 原则上讲是不应该编译通过的,但是c语言对于类型的检查是不严格的。
// strlen就会尝试从‘a’的ASCIL这个地址开始找\0
//printf("%d\n", strlen(p[0]));//也是属于未定义行为。
//printf("%d\n", strlen(&p));//未定义行为 char**类型
//printf("%d\n", strlen(&p + 1));//未定义行为 &p得到的是char**, 本身内部存的地址,是p变量本身的地址。
// 这个地址和\0无关,尝试去找,能不能找到这个\0是完全不知道的。
//printf("%d\n", strlen(&p[0] + 1));//5 p[0]得到的是char ‘a’,指向‘a’,再+1得到的是指向‘b’的指针。
二维数组本质上也是一个一维数组,每一个元素还是一个一维数组。
针对二维数组取下标(只有一个【0】),得到的是里面的一个元素,仍然是一个一维数组。
int a[3][4];
长度为3的一维数组,每个元素又是长度为4的一维数组。
a[0]=int [4]=>sizeof 16
*(a[0]+1)=>a[0][1];
//printf("%d\n", sizeof(a + 1));// 4 int[3][4],a+1就是数组名,在进行+1的时候,会隐式转成指针。
// 首元素是int[4]
//指向首元素的指针int(*)[4] 数组指针。
*(a+1)=a[1];
*a = *(a+0)=a[0];
char* const p; p为指向字符变量的指针,地址不变,地址内容可变
const char *p; p为指向字符变量的指针,地址可变,地址内容不变
char const *p 与const char *p等价。