欢迎来到淘文阁 - 分享文档赚钱的网站! | 帮助中心 好文档才是您的得力助手!
淘文阁 - 分享文档赚钱的网站
全部分类
  • 研究报告>
  • 管理文献>
  • 标准材料>
  • 技术资料>
  • 教育专区>
  • 应用文书>
  • 生活休闲>
  • 考试试题>
  • pptx模板>
  • 工商注册>
  • 期刊短文>
  • 图片设计>
  • ImageVerifierCode 换一换

    《C和指针》《C专家编程》《C陷阱与缺陷》《C语言编程要点》总结.docx

    • 资源ID:83245741       资源大小:236.63KB        全文页数:96页
    • 资源格式: DOCX        下载积分:12金币
    快捷下载 游客一键下载
    会员登录下载
    微信登录下载
    三方登录下载: 微信开放平台登录   QQ登录  
    二维码
    微信扫一扫登录
    下载资源需要12金币
    邮箱/手机:
    温馨提示:
    快捷下载时,用户名和密码都是您填写的邮箱或者手机号,方便查询和重复下载(系统自动生成)。
    如填写123,账号就是123,密码也是123。
    支付方式: 支付宝    微信支付   
    验证码:   换一换

     
    账号:
    密码:
    验证码:   换一换
      忘记密码?
        
    友情提示
    2、PDF文件下载后,可能会被浏览器默认打开,此种情况可以点击浏览器菜单,保存网页到桌面,就可以正常下载了。
    3、本站不支持迅雷下载,请使用电脑自带的IE浏览器,或者360浏览器、谷歌浏览器下载即可。
    4、本站资源下载后的文档和图纸-无水印,预览文档经过压缩,下载后原文更清晰。
    5、试题试卷类文档,如果标题没有明确说明有答案则都视为没有答案,请知晓。

    《C和指针》《C专家编程》《C陷阱与缺陷》《C语言编程要点》总结.docx

    C和指针C专家编程C陷阱与缺陷C语言编程要点编程精粹一Microsoft编写优质无错C程序秘诀心 口说明:总结的知识点主要源于上面的4本书,编程精粹一Microsoft编写优质无错C程序秘诀这本书未做总结,该书有清晰版的pdf格式的电子版。-wuliming-2007-04-25wuliminq sc指针和数组相关概念字符与字符串的区别指针与数组1指针与数组2指针和数组的相同与不同用malloc为字符串分配存储空间时的注意事项作为常数的数组声明(c缺陷与陷阱3.3节.在其它部分有包含该节的知识点,了解。r略过) 字符串常量用字符串常量初始化指针和数组二维数组下标操作的相关概念指向维、二维数组的指针array_name 和&array_name 的异同数组叔函数的参数时,不能通过sizeof运算符得到该数组的大小用strlenQ求字符串的长度匕har * *'和'const char *'的兼容性问题空指针相关的问题NULL和NUL的区别未初始化的指针和NULL指针的区别理解函数的声明函数参数的传值调用作为函数参数的多维数组强制类型转换相关概念可变参数相关问题malloc(), calloc(), realloc()在程序退出main()函数之后,还有可能执行一部分代码吗?总线错误和段错误相关概念数字和字符串之间转换相关的国数怎样判断个字符是数字、字母或其它类别的符号?怎样将数字转换为字符串?怎样将字符串转换为数字?字符串以及内存操作相关函数*字符串拷贝和内存拷贝国数:st ropystrncpymemcpymemmovemem copy bcopy字符串和内存数据比较函数:st rem p streaseemp strncasecmp mememp strcoll bemp连接字符串的函数:strcat st meat查找字符/字符串的函!数:strstr strehr strrehr memchr其它相关的函数: index rindexstrlen strdup mem set bzero strspn strespn strpbrk strtok数据结构及算法相关国数qsort () bsearch() Isearch (线性搜索) Ifind (线性搜索) srand (设置随机数种子) rand (产生随机数)OTHER*什么是标准预定义宏?断言assert(表达式)相关概念连接运算符“# # "和字符串化运算符"# "有什么作用? 注释掉一段代码的方法 Typedef相关概念 = 不同=词法分析中的“贪心法”运算符的优先级问题变量的存储类型及初始化相关概念左值和右值相关的概念变量的值和类型相关的概念怎样删去字符串尾部的空格?怎样删去字符串头部的空格?怎样打印字符串的一部分?结构的自引用结构的存储分配边界计算与不对称边界整数溢出返回整数的getchar図数更新顺序文件随机数的相关概念用递归和迭代两种办法解fibonacci字符与字符串的区别(C缺陷与陷阱1.5节)C语言中的单引号和双引号含义迥异,在某些情况如果把两者弄混,编译 器并不会检测报错,从而在运行时产生难以预料的结果。用单引号引起的个字符实际上代表个整数,整数值对应于该字符在编译 器采用的字符集中的序列值。因此,对于采用ASCI!字符集的编译器而,的 含义与0141 (进制)或者97 (十进制)严格一致。用双引号引起的字符串,代表的却是一个指向无名数组起始字符的指针,该 数组被双引号之间的字符以及个额外的二进制值为零的字符、初始化。下面的这个语句:printf (',Hello worldn");与char hello = 'H' , 'e', '1' , '13 'o','','W, 'o', 'r', 'I', 'd', 'n', 0;printf (hello);是等效的。整型数(一般为16位或32位)的存储空间可以容纳多个字符(一般为8位), 因此有的C编译器允许在一个字符常量(以及字符串常量)中包括多个字符。也 就是说,用yes,代替“yes"不会被该编译器检测到。后者(即"yes")的含义是“依 次包含、£以及空字符V)的4个连续内存单元的首地址”。前者(即e) 的含义并没有准确地进行定义,但大多数C编译器理解为,“个整数值,由V、 、所代表的整数值按照特定编译器实现中定义的方式组合得到、因此,这两 者如果在数值上有什么相似之处,也完全是一种巧合而已。译注:在801<!+丫5.5和0:丫3.6中果取的做法是,忽略多余的字符,最后的整数值即第一个字符的整效值;而在Visual C+ 6.0和GC v2.95中采取的做 法是,依次用后一个字符覆葢前个字把,最后得到的整数值即最后个字符的整 数值. # include < stdio.h>>int main()J:char ch = 'abcdefghijklmnopqrstuvwxyz'char str= °abcdefghijklmnopqrstuvwxyz"printf("% c n% s n'ch, str);return 0;):编译该程序可以通过,但是会产生警告:输出结过为:2Abcdefghijklmnopqrstuvwxyz/ /在Dev-C+ 4.9,9.2编译环境中可以通过,但是在VC.0中通不过:指针与数组1(C缺陷与陷阱3.1节)C语言中的数组值得注意的地方有以下两点:1c语言中只有一维数组,而且数组的大小必须在编译期间就作为一个常数确定下来(C9 9标准允许变长数组, GCC编译器中实现了变长数组)。然而,c语言中数组的元素可以是任何类型的对象,当然也可以是另外一个数 组。这样,要仿真出个多维数组就不是一件难事。2、对于个数组,我们只能够做两件事:确定该数组的大小,以及获得指向该数组下标为0的元素的指针。 其他有关数组的操作,哪怕它们乍看上去是以数组下标进行运算的,实际上都是通过指针进行的。换句话说, 任何个数组下标运算都等同于一个对应的指针运算,因此我们完全可以依据指针行为定义数组下标的行为。现在考虑下面的例子:int i;int *p;int calendar1231;上面声明的calendar是 个数组,该数组拥有1 2个数组类型的元素,其中的每个元素都是个拥有31个整 型元素的数组。因此,sizeof(calendar)的值是:31 xi2xsizeof(int)o考虑下,calendar4的含义是什么?因为calender是个有着12个数组类型元素的数组,它的每个数组 类型元素又是一个布着31个整型元素的数组,所以calendar4是calendar数组的第5个元素,是calendar 数组中12个有着31个整型元素的数组之一。因此,calendar的行为也表现为个有着31个整型元素的 数组的行为。例如,sizeof(calendar4)的结果是:31 Xsizeof(int)又如,p = calendar4!这个语句使指针p指向了数组calendar4中下标为的元素。因为calendar4 是一个数组,我们可以通过下标的形式来指定这个数组中的元素:i = calendar47,这个语句也可以写成 下面这样而表达的意思保持不变:i = * ( calendar4 + 7 )»还可以进步写成:i = * ( * ( calendar + 4) + 7).下面我们再看:p = calendar;这个语句是非法的,因为calendar是个二维数组,即“数组的数组”,在此 处的上下文中使用calendar名称会将其转换为个指向数组的指针。而p是个指向整型变量的指针,两个指 针的类型不一样,所以是非法的。显然,我们需要一种声明指向数组的指针的方法。int calendarf 1231 ;int (*monthp)31;monthp = calendar;int (* monthp)31语句声明的monthp是个拥有31个整型元素的数组,因此,monthp就是个指 向这样的数组的指针。monthp指向数组calendar的第一个元素。HERE指针与数组2 (c和指针.P141.) 1、数组的名的值是个指针常量,不能试图将一个地址赋值给数组名; 2、当数组名作为sizeof操作符的操作数时,sizeof(arrayname)返冋的是整个数组的长度,而不是指向数组的指 针的长度; 3、当数组名作为单目操作符&的操作数,取个数组名的地址所产生的是个指向数组的指针,而不是个 指向某个指针常量值的指针。 4、指针和数组并不总是相等的。为了说明这个概念,请考虑下面这两个声明:int a5;int * b;a和b能够互换吗?它们都具有指针值,它们都可以进行间接访问和标操作。但是,它们还是有很大的区 别的:声明一个数组时,编译器将根据声明所指定的元素数量为数组保留内存空间,然后再创建数组名,它 的值是个常量,指向这段空间的起始位置。声明一个指针变量时,编译器只为指针本身保留内存空间,它 并不为任何整型值分配内存空间。而且,指针变量并未被初始化为指向任何现有的内存空间,如果它是个 自动变量,它甚至根本不会被初始化。把这两个声明用图的方法表示,可以发现它们之间存在显著的不同:因此,上述声明后,表达式 a是完全合法的,但表达式 b却是非法的。b将访问内存中某个不确定的位 置,或者导致程序终止。另一方面,表达式b+ +可以通过编译,但是a+ +却不能,因为a的值是个常 量。;# include< stdio.h>D"int main()» / /注意sizeof(num)的长度应该为10*4=40S int num = 0,1,2,3,4,5,6,7,8,9;printf(" sizeof(num) = % d n", sizeof(num);I / /注意sizeof(str)的长度应该为11,包括字符串后面的' 0'S char str = "0123456789" printf(" sizeof(str) = % d n", sizeof(str);B/注意sizeof(strl)的长度应该为10,不包括字符串后面的、,,但是,最好将字符串的最后个字符设定为空 " char str1 = '0*,'1 ','2','3,t,4','5','6','7',8',9,;g print”sizeof(str1) = % d n”, sizeof(str1) );/&num的类型为int表示的是一个指向长度为1 0的整形数组的指针int (* ptoint) 1 0 = & num ;printf (" sizeof( ptoint) = % d, (* ptoint) 9 = % d n", sizeof( ptoint), (*ptoint)(9);/&str的类型为char ()11,表示的是一个指向长度为11的字符数组的指针,注意str数组的长度是11,而不是10 char ( ptostr) 11 = &str;printf(" sizeof( ptostr) = % d, (* ptostr)9 = % c n", sizeof (ptostr), (*ptostr)9);/由于p指向的是数组num5,所以对下标取负值后,不会超出数组的正常取值范围/该例子也说明了为什么下标检査在c语言中是项困难的任务:下标引用可以作用于任意的指针,而不仅仅是数组名U作用于指针的下标引用的有效性即依赖于该指针当时恰好指向什么内容,也依赖于下标的值int * p = num + 5;printf(" p-1 = %d, p0 = %d, p1 = %d n", p-1 ,p0 ,p 1 );/下面的表达式中,,num5和5num的值是样的,把它们转换成对等的间接访问表达式,它们都等同于(num + 2) /巧num这个古怪的表达式之所以可行,缘于C实现下标的方法。对编译器来说,这两种形式并无差别/但是,决不应该编写形如节num厂的表达式,因为它会大大的影响程序的可读性printf(" num5 = % d, 5num = % d n", num5, 5num);getchar();return 0;输出结果为:sizeof<nun> = 40sizeof<str> = 11sizeof<strl> = 10sizeof<ptoint> = 4, <*ptoint>9 = 9sizeof <ptosti»> = 4, <*ptostr> 9 = 9p-l = 4,p0 = 5- ptl = 6num5 = 5,5num = 5指针和数组的相同与不同(C专家编程.P199.)在实际应用中,数组和指针可以互换的情形要比两者不可互换的情形更为常见。让我们分别考虑“声明”和“使 用”这两种情况。声明本身还可以进步分为3种情况:外部数组的声明;«数组的定义(定义是声明的种特殊情况,它分配内存空间,并可能提供个初始值);函数参数的声明;也既是:作为函数参数时、在语句或表达式中使用数组时,我们可以采用数组或者指针的任何种形式,除此 之外的其他情况下,指针和数组不要互换。下面就数组和指针相同的情况做详细的说明: «规则1、表达式中的数组名被编译器当作一个指向该数组第一个元素的指针。假如我们声明:int a10;int * p = a;就可以通过一下任何种方式来访问ai:pi *(P+i)*(a+i)事实匕 可以采用的方法很多。对数组的引用如ai在编译时总是被编译器改写成 (a+i)的形式,C语言 标准耍求编译器必须具备这个概念性的行为。编译器自动把下标值的步长调整到数组元素的大小。如果整型数的长度是4个字节,那么ai+1和ai在 内存中的距离就是4。对起始地址执行加法操作之前,编译器会负责计算每次增加的步长。这就是为什么指 针总是有类型限制,每个指针只能指向种类型的原因所在,因为编译器需要知道对指针进行解除引用操作 时应该取几个字节,以及每个标的步长应取几个字节。规则2、下标总是和指针的偏移量相同。把数组下标作为指针加偏移量是C语言从BCPL(C语言的祖先)继承过来的技巧。在人们的常规思维中,在 运行时增加对c语言下标的范围检查是不切实际的。因为取标操作只是表示将要访问该数组,但并不保证 一定要访问。而且程序员完全可以使用指针来访问数组,从而绕过下标操作符。在这种情况下,数组下标范 围检测并不能检测所有对数组的访问的情况。事实上,下标范围检测被认为不值得加入到c语言当中。还有一个说法是,在编写数组算法时,使用指针比使用数组更有效率。这个颇为人们所接收的说法在通常情 况下是错误的。使用现代的产品质量优化的编译器,维数组和指针引用所产生的代码并不具有显著的差别。 不管怎样,数组下标是定义在指针的基础上,所以优化器常常可以把它转化为更有效率的指针表达式,并生 成相同的机器指令。规则3、在函数参数的声明中,数组名被编译器当作指向该数组第一个元素的指针。在函数形参定义这个特殊情况,编译器必须把数组形式改写成指向数组第一个元素的指针形式。编译器只 向函数传递数组的地址,而不是整个数组的拷贝。这种转换意味着在声明函数的时候,以下三种形式都是合 法的(同时无论实参是数组还是真的指针也都是合法的):my_function( int * turnip ) my_function( int turnip ) my_function( int turnip200 ) 用m alloc为字符串分配存储空间时的注意事项(c缺陷与陷阱3.2节)在c语言中,字符串常量代表了一块包括字符串中所有字符以及个空字符 (、,)的内存区域的地址。因为C语言要求字符串常量以空字符作为结束标志, 对于其他字符串,C程序员通常也沿用了这惯例。假定我们有两个这样的字符串S和我们希望将这两个字符串连接成单个字 符申r。要做到这一点,我们可以借助常用的库函数strcpy和strcat.下面的方法 似乎一目了然,可是却不能满足我们的目标:char *r;strcpy(rr s);strcat(r, t);之所以不行的原因在于不能确定r指向何处。我们还应该看到,不仅要让r 指向个地址,而且r所指向的地址处还应该有内存空间可供容纳字符串,这个 内存空间应该是以某种方式已经被分配了的。我们再试一次,记住给r分配一定的内存空间:char r ,1 00;strcpyr, s);strcat(,t);只要s和t指向的字符串并不是太大,那么现在我们所用的方法就能够正常 工作.不幸的是,C语言强制要求我们必须声明数蛆大小为个常量,因此我们 不够确保r足够大。然而,大多数C语言实现为我们提供了一个库函数inalloc, 该函数接受个整数,然后分配能够容纳同样数冃的字符的块内存。大多数C 语言实现还提供了一个库函数strlen,该函数返回一个字符串中所包括的字符数。 有了这两个座函数,似乎我们就能够像面这样探作了:char *r, *malloc();r = ma Hoc (str len (s > + s rlen(匕);strcpy(r, s);strcat(rt t);这个例子还是错的,原因归纳起来有三个。第一个原因,malloc函数有可能 无法提供请求的内存,这种情况下malloc函数会通过返回一个空指针来作为“内 存分配失败”事件的信号”第二个原因,给r分配的内存在使用完之后应该及时释放,这一点务必要记 住。因为在前面的程序例子中r是作为一个局部变量声明的,因此当离升作用 域时,r自动被释放了。修订后的程序显式地给r分配了内存,为此就必须显式地 释放内存。第三个原因,也是最重:要的原因,就是前面的例程在调用malloc函数时并未 分配足够的内存。我们再回忆一下字符串以空字符作为结束标志的惯例库函数 strlen返回参数中字符串所包括的字符数目,而作为结束标志的空字符并未计算在 内。因此,如果strlen的值是n,那么字符串实际需要n+1个字符的空间。所以,我们必须为r多分配个字符的空间。做到了这些,并已.注意检査了函数malloc 是否调用成功,我们就得到正确的结果:char *malloc();r = malloc(strlen(s) + strlen(t) + 1>;if (lr)(complain();exit(1);|strcpy(r, s);strcat(r, t);/* 一段时冋之后再使用/free(r);作为常数的数组声明(缺陷与陷阱3. 3节.在其它部分有包含该节的知识点,了解"略过)在c语言中,我们没有办法可以将一个数组作为函数参数直接传递。如果我 们使用数组名作为参数,那么数组名会立刻被转换为指向该数组第1个兀素的指 针。例如,下面的语句:char hello = "he丄0”;声明了 hell。是个字符数组,如果将该数组作为参数传递给,个函数,print.f ( " %sn" , hallo);实际上与将该数组第1个元素的地址作为参数传递给函数的作用完全等效,即:print f (*' %sn" , &hel Lo 0 j );因此,将数蛆作为函数参数毫无意义.所以,C语言中会自动地将作为参数 的数组声明转换为相应的指针声明.也就是说,像这样的写法:int strIon(ehar s)/*具体内容*/与下面的写法完全相同: int strlen(char* s) (/具体内容/)C程序员经常错误地假设,在:其他情形也会冇这种自动地转换。木书4.5节洋细地讨论r个具体的例子,程序员经常在此处遇到麻烦:extern char *hello;这个语句与下面的语句有着天渊之别:extern char hello(;如果一个指针参数并不实际代表个数组,即使从技术上而二是正确的,采用数组形式的记法经常会起到误导作用.如果个指针参数代表个数蛆,情况乂是如何呢? 一个常见的例子就是函数main的第二个参数:main(in argc, char* argv|J) (/具体内容/ )这种写法与下面的写法完全等价:main(int argc, char* argv) (/具体内容/需要注意的是,前种写法强调的重点在于argv是个指向某数组的起始元索的指针,该数组的元素为字符指针类型。因为这两种写法是等价的,所以读者 可以任选种最能清楚反映自己意图的写法。字符串常量(c和指针.P269.)当个字符串常量出现在表达式中时,它的值是指针常量。编译器把该字符串的一份拷贝存储在内存的某个位 置,并存储个指向第一个字符的指针。我们可以对字符串常量进行下标引用、间接访问以及指针运算。"xyzn+1字符串常量实际上是个指针,这个表达式计算“指针值加上1”的值。它的结果也是个指针,指向字符串中的第 二个字符y*"xyz"对个指针执行间接访问操作时,其结果就是指针所指向的内容。字符串常量的类型是“指向字符的指针”,所 以这个间接访问的结果就是它所指向的字符:X。注意表达式的结果并不是整个字符串,而只是它的第一个字符。Mxyz"2同样可以推断出上面这个表达式的值就是字符Z。# include< stdio.h>/接受一个无符号整型值,把它转换成字符,并打印出来3 /如果是打印16进值的数,可以用这种方法:putchar( "01 23456789ABCDEF"( value % 16):void binary_to_ascii( unsigned long value ), unsigned long quotient; quotient = value / 1 0;tif( quotient != 0 ):binary_to_ascii( quotient );: putchar( "0123456789"( value % 10 );int main():/Z字符串常量实际上是个指针,这个表达式计算"指针值加上1"的值。它的结果也是个指针,:r”指向字符串中的第二个字符:y:printf( "% s n", "xyz"+ 1 );:s/对个指针执行间接访问操作时,其结果就是指针所指向的内容。!""字符串常量的类型是"指向字符的指针”,所以这个间接访问的结果就是它所指向的字符:x:eprintf( "% c nw, * "abcdefg");>1/Z同样可以推断出上面这个表达式的值就是字符z:I printf( "% c n", "abcdefg"3);binary_to_ascil( 1234567 );c;getchar();"creturn 0;:Lk;用字符串常量初始化指针和数组(C专家编程.P87.)定义指针时,编译器并不为指针所指的对象分配空间,它只是分配指针本身的空间,除非在定义时同时赋给指针 个字符串常量进行初始化。例如,下面的定义创建一个字符串常量(为其分配内存):char * p = -breadfruit"注意只有对字符串常量是如此。不能指望为浮点数之类的变量分配空间,如:float * pip = 3.14;/错误,无法通过编译/在ANSI C中,初始化指针时所创建的字符串常量被定义为只读。如果试图通过指针修改这个字符串值,程序会 出现未定义的行为。在有些编译器中,字符串常量被存放在只允许读取的文本段中,以防止它被修改。数组也可以用字符串常量进行初始化:char a = "gooseberry"与指针相反,由字符串常量初始化的数组是可以修改的。比如下面的语句:strncpy( a, "black", 5 );将数组的值修改为“blackberry”。# include< stdio.h># include< string.h>int main(void)char * p = "this is a exam pie"/ / char * pi = 3.1 4;/这拜定义是错误的,无法通过编译Z/pO = '/修改该字符串常量时,编译是没问题,但是运行时会出现异常char a = "gooseberry"strncpy( a, "black", 5 );printf("% s n", p );printf("%snM, a );return 0;二维数组下标操作的相关概念(c和指针.P156.)如果要标识个多维数纣的某个兀素.必须按照与数组声明时相同的顺序为每维都提供一个 卜.林,而毎个卜标都单独位于对方括内.。而的声明中:int matrix310;友达式matrixl5访冋下面这个兀素:但是,标引用实际上只是间楼访同表込式的种伪装形式,即使在多维数组中也是如此"考卜面这个表达式:matrix它的类型是“指向包含10个整型元素的数组的指针它的值是:它指向包含10个整型元素的第1个子数组。 衣达式matrix +也是个“指向包含10个整型兀素的数组的指针”,但它指冋matrix的另一行:为什么?因为!这个值根据包含W个整型元素的数组的氏度进行调整,所以宮指向matnx的 卜行,如果对其执行间接访问操作,就如卜图随箭头选择屮间这个数组:所以表达式*( matrix + 1 )事:实上标识r 个包含10个整兀素的了数卽数组名的值是个常量指针,它指向数组的第1 个元素,在这个表达式中也是如此.它的此型是“指向整型的指针”,我们现在E以农卜.以的上下 文环境中显示它的值:猜倩卜面这个表达式的结果足I么?现在请拿稳你的帽,*( matrix + 1) + 5前个表达式是个指向整型值的指针,所以5这个值根据整型的长度进行弱整。整个表込式的 结果是个指针,它指向的位置比原先那个表达式所指向的位置向后移动了 5个整型元素:对其执行间接访问操作:*( *( matrix +1) + 5)它所访问的正是图中的那个整型元素。如果它作为右值使用,你就取得存储那个位置的值。如果它作为比值使用,这个位置将存储 个新值,这个看上去吓人的表达式灰包上正是我们的老朋友下标、我们可以把子表达式*(matrix + 改写为把这个下标去达式代入原先的表达式,我们将得到:* ( nidtrix 111 + 5 )这个表达式是完全合法的.matrix”选定一个子数组,所以它的类型是个指向整型的指针” 我们对这个指针加上5,然后执行间接访问噪作。但是,我们可以舟次用下标代替间接访问,所以这个表达式还可以写成:Fidtrixfl (5这样,即使对于多维数组,卜标仍然是另种形式的间接访问表达式。这个练习的要点在于它说明了多维数组中的卜标引用是如何工作的,以及它们是如何依赖于指 向数组的针这个概念、下标是从左向右进行计算的.数组名足个指向第1雑第1个兀素的指针, 所以第1个下标值根据该元素的长度进行调整,它的结果,是个指向那维中所需元素的指计“间 接访问操作随后选拝那个特定的兀素,由于该元素本身是个数组,所以这个表达式的类型是一个喑 向纬第I个元素的指针。下个下标值根据这个长度进行调整,这个过程重気进行,直到所有 的F标均算完毕,指向一维、二维数组的指针(c和指针.P158.)而这些声明合法吗?int vector10, *vp = vector;int matrix310, *mp = matrix;弟1个声明是合法的。它为个整型数组分配内存,并把vp声明为个指向整型的指针,并把 它初始化为指句veclor数组的第1个元素。vector和vp具有相同的类型:指向整型的指针,但是, 第2个声明是非法的。它正询地创建了 matri数组,并把mp声明为个指向整型的指管。但是, mp的初始化是不止确的,因为matrix并不是个指向整型的指针,而是一个指向整型数组的推制, 我们应该怎样声明个指向整型数组的指针的呢?int (*p) 10;这个卢明代我们以前见过的所有声明更为复杂,也它事实上并不是很难。你只要假定它是个 込代并对它求值卜标引用的优先级爲丁间接访问,但由于括号的存在,首先执行的还是接而 时 所以,P是个指针,但它指向什么呢?接来执行的是下标引用,所以P指向某种类型的数组。这个声明表达式中并没有更多的操作符,所以数组的每个元素都是整数。声明并没有直接吿诉你P是什么,但推断它的类型并不困産当我们对它执行间接访问操作 时,我们得到的是个数组,对读数组进行下标引用操作得到的是个整型值0所以P是个指向整 型数组的指针。在声明中加上初始化后是卜面这个样子:int (*p) 10| = matrix;它使p疥向matrix的第1行。是个指向拥有1。个整型元素的数组的指针.当你把p与一个整数柜加时,该整数值首先根 据10个整型值的长度进行调整,然后再执行加怯。所以我们可以使用这个指针行一行地在matrix 中移动,如果你需要一个指针逐个访间整型元素而不是逐行在数组中移动,你应该怎么办呢?固两个 声明都创建了个简单的整型指针,并以两种不同的方式进行初始化,指向matrix的第1个整型兀 素。mt*pi = inatiix01 Cl;ini*pi matrix 0;増加这个指针的值使它指向下个整型兀素.警告:加果你打算在指针上执行任何指舒运菓,应该避免这种类型的声明:(*p) ( = Kairix;P然是个指向整型数史的指针,但数组的长度却不见了.当美个里数与这种类型的指针执 行指针运奪时,它的值将根据空数组的长度进行調整(也就是说,与零相乘,这根可能不是你所设 想的.有些编译器可以捕捉到这类错误.但有些编译器却不能array_name 和&array_name 的异同前者是指向数组中第一个元素的指针,后者是指向整个数组的指针。char aMAX;/* array of MAX characters*/char * p = a;/* p为指向数组的指针/char * pa = &a;/该语句是不正确的,pa的类型为char *',而&a的类型为char (* )MAX' */char (*pb)MAX = &a;/* 该语句是正确的,pb 的类型为'char (*)MAX'*/:# include< stdio.h>I void main()S(" char a5 = 'a','b','c'd',、':char * p = a;运行下而这句后,vc6.0提示的错误为:cannot convert from 'char (* )5, to ,char *&a的类型应该是指向个数组的指针 /char * pa = &a;I/所以,应该定义 个指向相同类型和大小的数组的指针来获得“&a”的值-char ( point_to_str)5;jpoint_to_str = &a;Qprintf("%dn%dn",&p, &point_to_str);printf("%sn%sn", p, point_to_str);:)2运行结果为:j 1245044-1245040" abedabed数组作为函数的参数时,不能通过sizeof运算符得到该数组的大小不可以。当把数组作为函数的参数时,你无法在程序运行时通过数组参数本身告诉函数该数组的大小,因为函 数的数组参数相当于指向该数组第一个元素的指针。这意味着把数组传递给函数的效率非常髙,也意味着程序 员必须通过某种机制告诉函数数组参数的大小。为了告诉函数数组参数的大小,人们通常采用以下两种方法:第一种方法是将数组和表示数组大小的值起传递给函数,例如memcpyO函数就是这样做的: memcpy( dest, source, length );第二种方法是引入某种规则来结束个数组,例如在C语言中字符串总是以ASCII字符NUL (、0)结束,而一个 指针数组总是以空指针结束。请看述函数,它的参数是个以空指针结束的字符指针数组,这个空指针告诉该 函数什么时候停止工作:void printMany( char * strings)(int i = 0;while( stringsi != NULL )(puts(stringsi+ + );)C程序员经常用指针来代替数组下标,因此大多数C程序员通常会将上述函数编写得更隐蔽一些:void printMany( char * strings)(while( * strings )(puts(*strings+ + );)尽管你不能改变个数组名的值,但是strings是个数组参数,相当于个指针,因此可以对它进行自增运算, 并且可以在调用putsO函数时对strings进行自增运算。用strlen ()求字符串的长度(c和指针.P159.)库函数 strlen 的原型为:size_t strlen( char const * string );strlen返回一个类型为size_t的值。这个类型是在头文件stddef.h中定义的,它是个无符号整型类型。在表达式中使用无符号数可能导致不可预期的结果。例如,下面两个表达式看起来是相等的

    注意事项

    本文(《C和指针》《C专家编程》《C陷阱与缺陷》《C语言编程要点》总结.docx)为本站会员(文***)主动上传,淘文阁 - 分享文档赚钱的网站仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对上载内容本身不做任何修改或编辑。 若此文所含内容侵犯了您的版权或隐私,请立即通知淘文阁 - 分享文档赚钱的网站(点击联系客服),我们立即给予删除!

    温馨提示:如果因为网速或其他原因下载失败请重新下载,重复下载不扣分。




    关于淘文阁 - 版权申诉 - 用户使用规则 - 积分规则 - 联系我们

    本站为文档C TO C交易模式,本站只提供存储空间、用户上传的文档直接被用户下载,本站只是中间服务平台,本站所有文档下载所得的收益归上传人(含作者)所有。本站仅对用户上传内容的表现方式做保护处理,对上载内容本身不做任何修改或编辑。若文档所含内容侵犯了您的版权或隐私,请立即通知淘文阁网,我们立即给予删除!客服QQ:136780468 微信:18945177775 电话:18904686070

    工信部备案号:黑ICP备15003705号 © 2020-2023 www.taowenge.com 淘文阁 

    收起
    展开