《C Primer Plus》笔记

来源:互联网 发布:软文软件 编辑:程序博客网 时间:2024/05/16 05:03

一个C程序就是由若干头文件和函数构成。#include<stdio.h>通知C编辑器在对C程序进行编译之前做一些预处理工作。一个C程序有且只有一个主函数,即main函数了,C程序就是执行主函数里面的代码,也就是说主函数是C语言的唯一入口。
注释:/*注释内容*/,//注释内容。
数据类型

类型 字节 类型 字节 类型 字节 int 2 unsigned int 2 float 4 short int 2 unsigned short int 2 double 8 long int 4 unsigned long int 4 long double 16

格式化输出:c字符、d整数、f浮点数、s字符串、p指针
符号常量#define 标识符 常量值
自动转换类型:char -> int -> float
强制类型转换:(数据类型)(表达式)
- 转换后不会改变原数据类型及变量值,只是在本次运算中临时性转换;
- 强制转换后的结果遵循舍入原则。
自增、自减运算符:a++先赋值再运算,++a先运算再赋值
复合运算符:+=,-=,*=,/=,%=
逻辑运算符:&&,||,!
三目运算符:表达式1?表达式2:表达式3
标量储存类型:auto,static,register,extern。
auto为默认;static,在定义时就赋值,不然默认为0或空字符;局部auto变量和形式参数作为register变量;extren可以调用之后定义的变量。
不能被其他源文件调用的函数称为内部函数,即该函数只能在其所在的源文件中使用,在不同源文件中出现相同名称的函数是没有问题的。定义形式为static [数据类型] 函数名([参数])
能被其他源文件调用的函数称为外部函数,当没有指定函数的作用范围时,默认为外部函数,定义形式为extern [数据类型] 函数名([参数])
字符串
strlen(s1),获取字符串长度,中英文长度不一样且不包括’\0’;
strcmp(s1,s2),s1>s2返回1;
strcpy(s1,s2),会覆盖原字符串且不能对字符常量操作;
strcat(s1,s2),s1要有足够的空间来容纳s2.
多维数组

数据类型 数组名[][]={{'a'},...,{'z'}}  //必须制定列数数据类型 数组名[][];数组名[i][j]=值     //必须制定行列

一个字节8个二进制位,32位操作系统最大只能使用4G内存,32位计算机的地址总线是32位,32位是指给内存的编号只能编到32个二进制位,232=4G。在64位的操作系统中,可以使用的内存只有前面48位,其余给操作系统内核使用。计算机内存规划(从低到高)为代码段、数据段、堆、自由使用段、栈、内核。运行C程序时,函数位于代码段,全局变量位于数据段,临时变量位于栈。分配规则为代码段先分配低位,栈先分配高位。
变量名只是一个代号,变量的本质就是内存。
一个十六进制的数字可以表示四位二进制的数字。
与循环相比,每次递归都会在栈中创建一组变量,因此递归调用的数量受限于内存空间,且每次调用函数需要花费一定时间,导致递归慢。递归处理倒序很方便,如二进制转化为十进制。
形式参数是定义在被调函数中的变量,实际参数可以视为函数调用时初始化形式参数的值。
指针运算符:&,后跟一个变量,得到该变量的地址;*,后跟一个地址,得到该地址上的值。指针的声明:int *p,声明了指针p,*p是int类型。数组名是数组首元素的地址。系统中地址按字节编码,指针加1指增加一个储存单元,对数组而言,加1后的地址是指向下一个元素的地址,不是下一个字节的指针,这也是必须声明指针所指对象类型的原因之一。dates+2==&dates[2];*(dates+2)=dates[2]
系统用8字节储存地址,所以指针变量的大小是8字节。创建一个指针时,系统只是分配了指针本身的内存,并未分配储存数据的内存。
只有程序需要在函数中改变数组值时才会传递指针。对于数组,必须传递指针,让函数直接处理原数组,不然函数会拷贝一份原数组。
对数组形参使用const可以确保数组数据不被修改。
const数组可以赋值给const指针,不能赋值给普通指针。

const int arr[]={1,2,3};const int *p1;int *p2;p1 = arr;    //允许p2 = arr;    //不允许,p2是普通指针,不然就可以通过*p2=10来改变arr的第一个值了
int arr1[] = {1,2,3};const int *p1=arr1;    //指针p1所表示的值(*p1)不可变,但p2本身可以变(p1++)int * const p2=arr1;    //指针p2本身不可变,但*p2可以变p1++    //允许(*p1)++    //不允许p2++    //不允许(*p2)++    //允许const int * const p3;    //(*p3)不允许,p3++也不允许

int arr[3][2]arr[0]是一个占1个int大小的地址,arr是一个占2个int大小的地址。arr是数组首元素(还是一个数组)的地址,即arr[0]的地址,arr=&arr[0],为地址的地址。*arr=arr[0]=&arr[0][0],**arr=*arr[0]=arr[0][0].

int (*p1)[2];    //p1为一个指针,指向一个含2个元素的数组int *p2[2];    //p2为一个数组,数组含有两个指向int类型的指针

int类型可以赋值给double类型,但不同类型的指针不能赋值。

int arr[2][3];int (*pa)[3];pa=arr;    //都是指向含3个int类型的数组的指针int **p3;   //p3为一个指向指针的指针p3=&arr;p3=arr;    //arr是一个指向数组的指针,

ch11

用双引号括起来的内容称为字符串字面量,或字符串常量,其本质是指向该字符串储存位置的指针。字符串常量属于静态储存类别。

printf("%s, %p, %c\n", "we", "are", *"space");    //->We, 0x100000f32, s

定义字符串数组时,要确保数组元素的个数至少比字符串长度多1(‘\0’),所有未被使用的元素都初始化为’\0’。

const char * pt1="some";const char arr[]="some";    //两者几乎等价

区别为arr为该数组首元素地址的别名,是地址常量,可进行arr+1这样的操作,但不可进行arr+=1以及++arr;pt1俩种运算都可以。字符串常量是const数据,所以应该把pt1声明为指向const数据的指针。

const char *p1[2]={"asdf", "qwertyui"};const arr[2][10]={"asdf", "wqertyui"};

p1是一个含2个指针的数组,占16个字节,其指针指向的字符串常量不能更改;arr是一个二维数组,占20个字节,arr储存效率要低。

const char *p1="asdf";const char *p2;p2=p1;printf("p2=%s; &p2=%p;, value=p2%p\n", p2,&p2,p2);

程序不发生字符串copy,p2=p1让p2也指向了p1指向的字符串。

char *p;scanf("%s", p);
  • p是一个未初始化的内存,可能指向任何地方,scanf()把输入信息拷贝到指针所指的地址上,可能为擦掉程序中数据代码。

  • 数组名会被转化为该数组首元素的地址。

  • Segmentation fault:程序试图访问未分配的内存。
#define STLEN 5char words[STLEN];fgets(words, STLEN, stdin);fputs(words, stdout);puts(words);
  • fgets()的第二个参数是读入字符的最大数量,如果参数是n,读入n-1个字符,或遇到第一个换行符为止。如果遇到换行符,会被储存在字符串中。fgets()函数返回一个char指针,与第一个参数(字符串数组)相同。
  • puts()会在输出字符末尾添加一个换行符。
  • 空字符与空指针:空字符(’\n’)是整数类型,用于标记字符串末尾的字符,对应ASCII值为0;空指针是指针类型,不会是任何数据的有效地址。
char word1[3];char word2[3];fgets(word1, 3, stdin);    //输入bing,word1实际值是"bi"fgets(wrod2, 3, stdin);    //没有提示用户输入,word2自动设为"ng"

word1输入行多出来的字符”ng”会被留在缓冲区中,第二次调用word2是从上次结束的地方继续读取数据的,所以”ng”成为word2的输入。scanf()输入字符时如果指定了字段宽度,也会有同样的问题。scanf()返回一个int,表示scanf()中成功读取的项数。

char strArr[] = "binggo";const char *p = "wnbing";puts(&strArr[4]);    //->"go"puts(p+3);    //->"ing"puts(strArr[4]);    //->报错printf("%c", strArr[4]);    //->"g"

puts()在遇到空字符’\0’才停止,如下,puts()会继续打印strArr后面内存中的内存,直到遇到’\0’。

char strArr[]={'g','o'};puts(strArr);
原创粉丝点击