欢迎来到个人简历网!永久域名:gerenjianli.cn (个人简历全拼+cn)
当前位置:首页 > 范文大全 > 实用文>深度理解C语言的指针与数组

深度理解C语言的指针与数组

2024-10-13 07:59:17 收藏本文 下载本文

“qyt880616”通过精心收集,向本站投稿了3篇深度理解C语言的指针与数组,以下是小编收集整理后的深度理解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#includeint string_compare(const char *str1,const char *str2){ assert(str1); //ASSERT( f ) assert(str2);/*在Debug模式下,每次运行到这里后会计算括号中的表达式,如果表达式为0,则中断执行,弹出一个警告框,用户可选择“继续”,“重试”,“忽略”在Release模式下,这句语句不会被编译进代码, ASSERT一般用于程序内部确认参数的正确性,即调用内部函数的时候,要由调用者保证参数的正确,而被调用函数内部,就可以通过ASSERT来检查参数是否满足要求。*/ while(*str1 == *str2 ) //判断两个数组中的元素是否相等 { str1++; //使两个指针指向下一位;继续比较 str2++; if(*str1 == '\0') //双方比较到'\0'处,都相等 { return 0; //返回0,表示二字符串相等 } } return *str1-*str2; //若不相等,返回一个正值或负值}int main(){ char *ch[2]; ch[0] = “ab”; //对这个指针数组的元素初始化,使其指向这个字符串首元素的首地址 ch[1] = “a”; //同上 printf(“%d\n”,string_compare(ch[0],ch[1])); //调用这个函数 return 0;}

【深度理解C语言的指针与数组】相关文章:

1.c中指针指针、指针的指针、指针数组和数组指针

2.C语言实验报告《指针》

3.谭浩强c语言课件指针

4.C语言指针笔试题

5.C语言变长数组data[0]

6.c语言学习方法

7.c语言面试题

8.c语言实验报告

9.c语言练习题

10.C语言求职信

下载word文档
《深度理解C语言的指针与数组.doc》
将本文的Word文档下载到电脑,方便收藏和打印
推荐度: 评级1星 评级2星 评级3星 评级4星 评级5星
点击下载文档

文档为doc格式

  • 返回顶部