《c primer plus 再看》
sizeof运算符 strlen()函数
对于指针的实质——包含长度与地址的结构体(有误,反面典型)
4月24日——23:25
----------------------------------------------------------------------------------------------------------------------------------
对于scanf()函数的读取字符,整数,字符串等时的一些特性p94
4月25日
c标准数学库 math.h
pow(double a,double b)返回a的b次幂
求模运算只能用于整数
typeof int myint;领会不到起个别名有jm用
c中声明变量则为其创建了名称和类型,并分配了内存,但内存中的数据还未初始化
强制类型转换
char 1 字节 char* 4字节? int 4字节 short 2 字节 float 4字节 double 8字节
----------------------------------------------------------------------------------------------------------------------------------
题外话,关于字符数组指针的实验—数组名以及首元素地址为常量(左值)不可操作(自增等)
下午的时候写了下面的代码
sizeof运算符 strlen()函数
对于指针的实质——包含长度与地址的结构体(有误,反面典型)
4月24日——23:25
----------------------------------------------------------------------------------------------------------------------------------
对于scanf()函数的读取字符,整数,字符串等时的一些特性p94
4月25日
c标准数学库 math.h
pow(double a,double b)返回a的b次幂
求模运算只能用于整数
typeof int myint;领会不到起个别名有jm用
c中声明变量则为其创建了名称和类型,并分配了内存,但内存中的数据还未初始化
强制类型转换
char 1 字节 char* 4字节? int 4字节 short 2 字节 float 4字节 double 8字节
----------------------------------------------------------------------------------------------------------------------------------
5.7
题外话,关于字符数组指针的实验—数组名以及首元素地址为常量(左值)不可操作(自增等)
下午的时候写了下面的代码
int main()
{
int i;
char a[10]={'a','a','a','a','a','a','a','a','a','a'};
for(i = 0 ; i<10 ; i++){
printf("*%c",*(a++));
}
return 0;
}
- 编译器提示a为左值即常量,无法进行修改。这也正符合了下面数组与指针一节数组名即数组首元素的地址是常量这一事实。后遂改成如下,先将首地址赋给变量p,再对p进行操作,成功输出10个*a。
int main() { int i; char a[10]={'a','a','a','a','a','a','a','a','a','a'}; char *p = a; for(i = 0 ; i<10 ; i++){ printf("*%c",*(p++)); } return 0; }
而后又增加
printf("%s\n",a);
发现可以成功输出,结果为aaaaaaaaaa???,字符串数组中并没有在最末尾‘\0’,但也可以输出,不解
-------------------------------------------------------------------------------------------------------------------------------------
数组
- 数组除初始化之外,是不允许用花括号去进行赋值的 p282
数组与指针
- 一维数组,数组名即是数组首元素的地址。声明了一个数组后,数组的首元素地址即确定了,为常数。详看上面字符串的例子。再次重申--绝对不要对a或&a[0]做类似自增操作,若要操作先char *p = a,再对p操作;
int a[N]; a == &a[0]//两者都是常量,左值
- 指针加一,指针的值递增它所指向类型的大小。
- 看下面代码p298
切记:创建一个指针时,系统只分配了储存指针本身的内存,并未分配储存数据的内存,可用malloc开辟对应数据存储空间。int *p; *p = 5;//解引用未初始化指针,严重错误
指针作为函数参数
- 若写一个函数想要计算数组的所有元素和,只传指针是不行的,因为无法推断出指针代表的数组长度。所以必须再加一个长度的参数;
- ①往函数中传指针,不管这个指针是否在声明时代表了一个数组,在函数中都视为一个指针(sizeof结果不是数组长度); ②只有在刚刚声明过数组且用原生数组名才能sizeof出数组长度,其他一概是被视为普通的char *;③char p[]以及char* p这两种形参方式都被允许。
int main() { int i; char a[10]={'a','a','a','a','a','a','a','a','a','a'}; char *p = a; printf("%d\n",sizeof(a));//10 只有在相邻上下文,传数组名能够通过sizeof获取指针代表 printf("%d\n",sizeof(p));//4 printf("%d\n",sizeof(&a[0]));//4 sum(a);//4 sum(p);//4 _sum(a);//4 _sum(p);//4 for(i = 0 ; i<10 ; i++){ printf("*%c",*(p++)); } return 0; } void sum(char *p) { printf("%d\n",sizeof(p)); } void _sum(char p[]) { printf("%d\n",sizeof p); }
- c保证指向数组后面第一个位置的指针仍是有效的(可以解引用,但该指针上的值),这在一些while循环的条件判断上很有用。P294
- “利用c中数组与指针的特殊关系,可以用数组表示法来表示指针”p292
- 若函数的意图不是修改数组中的数据内容,可在函数形参中使用关键字const p299;const指针 ,const数组等见p300
int sum(const int a[]){ //该函数在处理数组时将其看做常量,不可修改;而不是要求原数组是常量 }
一维数组
- int a = { 0 , 1 }
- a——一维数组的首元素地址 &a[0]
- a+1——一维数组第二个元素的地址 &a[1]
- *(a+1)——一维数组第二个元素的值 a[1]
二维数组 p302
- 记住二维数组的数组名就相当于一个二重指针(不要和int **p搞混),想要取到甭管哪一个具体值都必须两个*,必须两个*!!
- 对于 int a[2][2]={ { 0 , 1} , { 2 , 3 } };
- a —— 二维数组的首元素地址(每个元素都是内含两个int的一维数组)&a[0] &&a[0][0]
- a+1——二维数组第二个元素(第二个一维数组)的地址 &a[1] &&a[1][0]
- *(a+1)—— 二维数组第二个元素的首元素的地址 &a[1][0]
- *(a+1)+1——二维数组第二个元素的第二个元素的地址 &a[1][1]
- *(*(a+1)+1)——二维数组第二个元素的第二个元素的值 a[1][1]
- 个人感觉a就可以看指向一个一维数组的指针,对其进行一次解引用出来的就是一维数组名
指向多维数组的指针
前提:int a[2][2]={ { 0 , 1} , { 2 , 3 } };
- 不能用int *p = a 因为a代表的是指向两个int值的数组的指针。正确方式是int (*p)[2] = a,p是指向内含两个int的数组的指针(不好记)。一层解引用*p代表内含两个int类型数组的数组名---仍是一个指针。反正就是*p了以后就只能对首个一维数组操作了。
int a[2][2]={{0,1},{2,3}}; int (*p)[2] = a; p == a;//类型相同 **p == a[0][0]
其次指向含有两个int的一位数组的指针 int (*p)[2] = a; 对于p,也可以把它当作数组名用p[1][1]这样的写法
2.int * p[2]是一个内含两个int类型指针的数组。可以这样记 int a[] 是int 类型数组;int* p[2]就是int*类型的数组
3. int** p代表的是一个指向指针的指针,下面节选一部分。p305页还有许多例子非常棒(一定要看)
int a[2][2];
int **p;
*p = a[1];//有效,都是指向int的指针
p = a;//无效,涉及的两个指针是不同类型的;p是指向指针的指针,而a是指向含有两个int的数组的指针
------------------------------------------------
5.26
- c语言中指针作为函数参数,实质上也是按值传递。指针的值无法进行改变。那如果想要改变有两种方法:
1.使用返回值,把修改后的指针return过去
2.使用二重指针,即int**p指向指针的指针,通过二重指针来修改其指向的指针的值。