深度理解C语言的指针与数组
“qyt880616”通过精心收集,向本站投稿了3篇深度理解C语言的指针与数组,以下是小编收集整理后的深度理解C语言的指针与数组,欢迎阅读与借鉴。
篇1:深度理解C语言的指针与数组
写个简单的yuv读取的库,卡在多维数组动态分配的问题上,唉,还是C基本功不扎实,于是花了一下午时间,算是给自己有了点交代。参考《C专家编程》。水平有限,欢迎看客指正。
Section 1 左值与右值
编译器为每个变量分配一个地址(左值),该地址在编译时可知,且变量在运行时一直存于该地址。存于该地址的变量的值(右值)只有在运行时可知。因此,编译器如果需要一个地址来执行某种操作,它可以直接进行操作,如果需要一个变量的值,它需要发出指令从指定地址中读入变量值并存于寄存器中。到这里,可以理解作为一个指针变量,它本身的地址是左值,它变量的值(即指向的地址值)为右值。所以指针首先需要在运行时取得它的当前值,然后才能对它进行解除引用操作。
数组名是一个左值,即内存中的位置。但数组名是一个不可修改的左值,即不可被赋值。
int main
{
int a[3] = {0};
int b = 1;
a = &b; //ERROR: “=” : 左操作数必须为 l 值。
return 0;
}
Section 2 数组与指针的不同
一个例子:
int main()
{
char arr[4] = “abc”; // Note 1
//char arr[4] = {''a'', ''b'', ''c'', ''\0''}; // Note 2
char *ptr = “ABC”; // Note 3
//ptr+1 = &arr[2]; // Note 4
printf(“arr: %x, %x, %x %x \n”, &arr, &arr[0], &arr[1]); //Note 5
printf(“ptr: %x, %x, %x %x \n”, &ptr, &ptr[0], &ptr[1]);
return 0;
}
Note 1&2等价定义,其结构如下:
a b c \0
[__] [__] [__] [__]
12fed4 +1 +2 +3
Note 3结构如下
42703c A B C \0
[__] [__] [__] [__] [__]
12fec8 42703c +1 +2 +3
Note 4复习一下Section 1.显然的错误,因为p+1首先需要知道p的值(右值),只有在运行时刻才能得到,编译时刻就希望对其所在的地址进行赋值显然错误,
Note 5验证Note1和3,运行结果如下:
arr: 12fed4, 12fed4, 12fed5
ptr: 12fec8, 42703c, 42703d
可以发现,arr的地址(左值)的结果与数组中首元素的地址一致,而ptr的变量值(右值)与数组的首元素地址一致。
因此对一个数组中的元素进行引用,c=arr[i]和c=ptr[i]都能够取出相应数组中的第i个元素。但要注意这两个操作的过程完全不同:
c = arr[i]; c = ptr[i];
1:取地址12fec8的内容,即42703c
1 取出i的值与12fed4相加 2:取出i的值与42703c相加
2 取地址(12fed4+ i)的内容 3:取地址(42703c+i)的内容
得到结论:尽管c=arr[i]和c=ptr[i]用同样的形式完成了同样的功能,但绝不可以混用。注意数组原始的声明方式,如果原始声明为数组式的,那么对其元素的引用要使用数组形式,反之亦然。
文件1中:
篇2:C语言其实不简单:数组与指针
之前在写C的时候,没怎么留意数组,就这么定义一个,然后颠来倒去的使用就行了,不过后来碰到了点问题,解决后决定写这么一篇博客,数组离不开指针,索性就放一起好了。
现在我定义了一个数组:int cc[10];
围绕这个数组有好几种指针:cc, cc+1, &cc[0], &cc, &cc+1等等。你知道它们都是什么含义吗?试试运行以下带代码:
?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#include
int main()
{
int cc[10];
printf(“%x\n”, cc);
printf(“%x\n”, cc+1);
printf(“%x\n”, &cc[0]);
printf(“%x\n”, &cc);
printf(“%x\n”, &cc+1);
getchar();
return 0;
}
cc,这是学数组时第一个接触的“指针”,最为熟悉,它是数组的首个元素。cc+1,这是指向数字第二个位置的指针。
&cc[0],这个其实就是cc,指向数组的首个元素。
&cc,这是什么玩意儿?指向指针的指针?
&cc+1,如果上面的意思是指向指针的指针,那这个岂不是指向野地址了?
假设运行环境是32位机,并且数组首地址为0x28ff00,那么:
cc的结果为0x28ff00,这点毫无疑问。
cc+1的地址是0x28ff04而不是0x28ff01,因为一个int占用了4个字节的空间。cc+1其实是当成cc+1*sizeof(int)来看待。
&cc[0]的结果是0x28ff00,cc[0]表示的是数组的首个元素,那么&cc[0]自然就是首个元素的地址了。&cc[0] == cc。
&cc,这个就难说了,指针cc的值是0x28ff00,&cc表示这个指针本身的地址,我们怎么可能会知道这个地址?输出是个随机地址吗?随机数的话这个输出完全没有意义啊。如果不是随机地址的话,难不成还是0x28ff00?这样的话a不就等于&a了?明显不对吧,
。。
对于基本类型的指针,如int *tt; 那么*tt是其值,&tt是指针的地址,&tt != tt
但是上述的cc是个数组,实际上,&cc被编译成了&cc[0],但是其含义不同,&cc指向的是整个数组的开头。&cc与cc的指向可以用下图来形象表示:
上图可以看出,&cc其实代表的是int(*)[10],那么&cc+1就可以理解为cc + sizeof(cc)/4,之所以除以4是因为int型指针++其实是移动了4个字节。
又或者说%cc == cc + sizeof(cc)/4 == cc + 10,所以&cc+1的值为0x28ff28。
可见我们平常使用的数组名,并不能单纯的当成指针看待。数组名的本质是代表数组对象的变量名,是一个左值,是一个不能被改变的左值。但是由于在程序中不保存数组的大小,所以通过数组名只能访问数组的左值,不能访问数组的右值。由于这个原因,数组名在作为右值使用的时候被赋予另外一个新的意义——指向数组第一个元素的指针,这就是array-to-pointer转换规则。根据标准规定,只有当数组名作为sizeof、&运算符的操作数的时候,它是一个左值,其类型为数组类型。除此之外的所有情况,数组名都是一个右值,被编译器自动转换为指针类型,这种情况下我们就说数组名是一个指针,并且是一个指针常量。
接下来是另外一些有趣的东西,我们结合sizeof与数组输出各类值。以下程序的输出结果是什么?建议思考后再运行程序来验证答案。
?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
#include
int main()
{
int cc[10];
printf(“%d\n”, sizeof(cc[0]));
printf(“%d\n”, sizeof(cc));
printf(“%d\n”, sizeof(&cc));
printf(“%d\n”, sizeof(int(*)[10]));
getchar();
return 0;
}
sizeof(cc[0]),一个int的大小,输出4,没问题。sizeof(cc),注意不要和上面搞混,这不是数组首地址的指针,cc在这里是左值,其为数组类型,所以结果为40。
sizeof(&cc),这个的答案应该是多少呢?注意了,cc在这里还是左值,其为数组类型,但&cc不同于cc,不管数组怎么复杂它始终是个指针,32位机上指针大小始终是4个字节,所以结果为4。
篇3:(C语言)字符串比较函数,指针数组与数组指针
问题描述:
写一个函数,用于比较两个字符串的比较(string_compare).
程序分析:
(1)主要思想:传入两个字符串后,比较这两个字符串中的每个元素,如果第一次比较就不相等,就不要让它进入到下面的比较中,这样一来,将它返回一个相减的值(即:两数组中开始不相等的那两个元素相减,返回值(int类型),是ASCII码值相减)。进入比较的过程中时,相等就返回0;其他情况都返回那个相减的值。
(2)主要方式:定义指针数组,并对其初始化。然后照上面的思想,进行代码的实现。
代码如下:
/***指针数组(1)int *a[10] 是一个指针数组--->是一个数组(每个数组中的元素都是int*类型)(2)int (*a)[10] 是一个数组指针--->指向一个数组(十个int类型的数组) 注意:*,[],()的优先级依次递增。下面使用了指针数组的例子,至于数组指针。。**/#include
【深度理解C语言的指针与数组】相关文章:
4.C语言指针笔试题
6.c语言学习方法
7.c语言面试题
8.c语言实验报告
9.c语言练习题
10.C语言求职信






文档为doc格式