目录
一、数组和指针
1、指针和数组的关系
下面是一个数组int a[2][3]:
(a),(a+1)的指向如图所示:即(a),(a+1)指向的是int [3],也就是说他们是行地址
所以对于int *p ,要使的指针能够指向数组,可以使用如下方式:
p = *a; 这里的*a就是列地址)
p = &a[0][0]; (*a == &a[0][0])
p = *(a+0); (*(a+0) == *a == &a[0][0])
//通过这三种方式使得指针指向数组a,之后变可以向后移动指针来获得数组内容,即可以理解二维数组a是一个一维数组p[6]。
例如使用 :
a[2][3] = {{1,2,3},{2,3,4}};
int *p = *a;
int i = 0;
for(i = 0; i < 6; i++){
printf("%d",p[i]);
}
二、数组指针和指针数组
1、数组指针
除了使用上述的方式,可以使用数组指针来指向a。即用行地址来指向a。
数组指针的定义为: 数据类型 (*指针 [index])= value 相当于 数据类型[index] *p = value.
所以可以使用(注意p是变量,a相当于常量,所以不能给a赋值,在其他方面p相当于a使用)
int (*p)[3] = a;来指向a;
下面是数组指针的两个例子:
例1:
//连接前面的代码
int (*p)[3] = a;
int j = 0;
for(i = 0; i < 2; i++){
for(j = 0; j < 3; j++){
printf("%d",*(*(p+i)+j));
}
}
例2:
int main()
{
char s[6][5] = {{"ll"}, {"jj"}, {"fk"},{"lsdf"}, {"fjsl"},{"sdjf"}};
char (*ptr)[5] = s;
int i ;
for(i = 0; i < 6; i++){
printf("%s\n", ptr[i]);
}
}
2、指针数组
例如:char *ptr[6],下面是他的使用
int main()
{
char s[6][5] = {{"lddd"}, {"jj"}, {"fk"},{"lsdf"}, {"fjsl"},{"sdjf"}};
char *ptr[6];
int i;
for(i = 0; i < 6; i++){
ptr[i] = s[i];
}
for(i = 0; i < 6; i++){
printf("%s\n", ptr[i]);
}
}
三、char *p 和char q[]的区别:
1.区别一
所以在使用sizeof的时候需要注意sizeof(p) 和sizeof(q)的结果不同,sizeof(p) 的值是char *指针大小,64位机为8,而sizeof(q)就是字符串大小(包括‘\0')。
我认为要明白这两个的区别还是需要自己在电脑上实验一下,例如这样
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main()
{
char *p = {"kdfj"};
char q[7] = {"jjdkj"};
printf("%ld %ld %ld\n", sizeof(p), sizeof(*p), strlen(p));
printf("%ld %ld %ld\n", sizeof(q), sizeof(*q), strlen(q));
return 0;
}
你将看到如下结果:
在写这个例子的时候,我在想sizeof 和strlen 函数在计算字符串大小时候的使用,一个众所周知的区别是是否计算 '\0' ,然后我进行了下面的测试:
printf("%ld %ld\n", sizeof("dls"), strlen("dls"));
我在前面的测试中用过sizeof 和 strlen 计算字符串大小,但是为什么还要这样做呢?
就是为了体会一下sizeof 在计算这四种情况的区别:
char p[4] = {"ld"}, sizeof(p) = 4; 他就该是四,因为你请求的指针常量大小就是4,
不是 够 就加 '\0'. 他本质是个常量,你不能用p[0] = a,来改变他的值。
char p[4] = {"lll"}, sizof(p) = 4;
char p[4] = {"dlsl"}, sizeof(p) = 4; 这里没有计算 '\0' 因为他没有。
"dls" , sizeof("dls"); sizeof ("dls") = 4;
第三种情况,我有个疑问,到底这样做否会有问题呢?因为他没有 ’\0' 结束,所以我进行了如下的测试:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main()
{
char *p = {"kdfj"};
char q[7] = {"jjdkj"};
// printf("%ld %ld %ld\n", sizeof(p), sizeof(*p), strlen(p));
// printf("%ld %ld %ld\n", sizeof(q), sizeof(*q), strlen(q));
// printf("%ld %ld\n", sizeof("dls"), strlen("dls"));
char l[4] = {"llfd"};
int i;
for(i = 0; i < 6; i++){
if(l[i] != '\0')
printf("l[%d]: %c\n", i, l[i]);
// else{
// break;
// }
}
char t[4] = {"ld"};
for(i = 0; i < 6; i++){
if(t[i] != '\0')
printf("t[%d]: %c\n", i, t[i]);
// else
// {
// break;
// }
}
return 0;
}
对的你没有看错,我越界访问了,我就是想这么做,来看看他有什么问题:
可以看到 t[4] 他有 '\0' 因为t[2] t[3]没有输出。而 l[4] 的问题就很明显,他没有 '\0', 如果打开 else语句,你可以看到如下的输出:
对的没错, 我想表达的就是不要这样用 l[4] = {"lsld"}; 还是有个 '\0' 好。
2.区别二
要记住,对于 char *p = {”ls"}, {”ls"}是一个常量,常量的值是不可以改变的,但是指针变量指向是可以改变的,但是这样p[0] = 'a'会报错,因为你在修改那个常量。
对于 char q[4] = {"fd"}; 你就可以这样改 q[0] = 'b';
为此 我进行了如下的测试:
int main()
{
char *t = {"dkk"};
char *p = {"kdfj"};
char q[7] = {"jjdkj"};
printf("*p= %s\n", p);
printf("*q = %s\n", q);
//p[0] = 'a'; //报错 试图修改常量的值
p = t;
q[0] = 'b'; //这个就可以, q 是指针常量,对,q自己是常量,
//那么他指向的空间不能改变,但是内容可以改变
//q = t; //报错, 表达式必须是可修改的左值, q是常量当然不可修改
printf("*p= %s\n", p);
printf("*q = %s\n", q);
}
结果如下:
好了这个时候我又有了这样的疑问:
1 .怎么char *p = {"kdfj"}中,{"kdfj"}不可修改
2,但是char q[7] = {"jjdkj"}中,{"jjdkj"}可以修改呢?
以前我学习c的时候,老是会看到有人说 ={” jd“} 是个字符串常量,那时候我还没有仔细的观察, 直到现在,我好像有点明白了, 对于 ={"dkfj"},你要怎么看他,要看你是怎么定义的,就是你要看你的左值写的是什么,对于1来说他是字符串常量,对于2来说他是字符串,也是个变量。
四、指针常量和常量指针
1.指针常量
int *const p;
从前往后读,就是指针常量,但是重点在最后,他是一个常量;我的理解是,我们定义了一个常量,他是指针类型的,那么常量必须在定义的时候就初始化,例如我给他初始化为s;之后常量的值就不可以改变了,它一值指向s,但是呢,我们可以通过*p来修改他所指向内容的值。
int main()
{
char s[] = {"lslslslsjfjf"};
char t[] = {"jiawenshi"};
char * const p = s;
printf("p = %s\n", p);
p[1] = 'u';
printf("p = %s\n", p);
p = t; //报错
printf("p = %s\n", p);
return 0;
}
2.常量指针
这里定义了常量指针 const char *p,或者可以这样定义:char const *p;读的时候从前往后读,就是常量指针。按照前面的理解就是他是一个指针,然后指向一个常量。也是一样的理解重点在指针,那么指针的值是可以改变的,但是所指向的常量值是不可以改变的。
int main()
{
char s[] = {"lslslslsjfjf"};
char t[] = {"jiawenshi"};
const char *p = s; // char const *p = s;
// printf("p = %s\n", p);
// p[1] = 'u'; //报错
printf("p = %s\n", p);
p = t;
printf("p = %s\n", p);
return 0;
}
3.总结
我在网上看到有的人的定义完全相反,其实我觉的没有什么太大的关系,只要记住" * "和 const谁更靠近p就可以决定哪个能改哪个不能改。
下面是一些参考,不过我认为我写的挺详细的:
char * 与char []区别总结_char*_bitcarmanlee的博客-CSDN博客
C语言 char*和char[]用法_c char*_imxlw00的博客-CSDN博客
如果你觉得我写的有问题,欢迎你与我交流。