数组与指针

1.数组
数组的初始化必须出现在定义语句中
如  int a[3] = {1,2,3}
a 表示a[0]的地址,&a 代表数组a的取地址。
[]内不可为负数。C/C++语言中数组下标越界,编译器不会检查处错误,但是实际上会导致程序崩溃。
 
数组也可以这样表达:
int b[100] = {[0...49]=100,[50...99]=200};    //意思是b[0]到b[49]都等于100,b[50]到b[99]都等于200
(延伸:...也可以用于switch 中
如:
switch()
{
    case 1:
    case 2:
    case 3...10:
})
 
 
二维:int b[2][3]解析:第一部分 b[2], 第二部分 int [3];b是一维数组,只不过其中的两个要素都是一个int [3]的一维数组罢了
 
1.1变长数组(不初始化的赋值
int i = 3;
int a[i];
a[0] = 100;
 
1.2柔性数组    code1 
 
 1 #include <stdio.h>
 2 #include <malloc.h>
 3 
 4 typedef struct _soft_array
 5 {
 6     int len;
 7     int array[];
 8 }SoftArray;
 9 
10 int main()
11 {  
12     int i = 0;
13     SoftArray* sa = (SoftArray*)malloc(sizeof(SoftArray) + sizeof(int) * 10);//分配内存并命名为sa 空间大小为10个int类型和一个空int型数组类型 
14     
15     sa->len = 10;
16     
17     for(i=0; i<sa->len; i++)
18     {
19         sa->array[i] = i + 1;
20     }
21     
22     for(i=0; i<sa->len; i++)
23     {
24         printf("%d
", sa->array[i]);   
25     }
26     
27     free(sa);        //释放内存!!!必须记得 
28     
29     return 0;
30 }
* 柔性数组即数组大小待定的数组
 
* C语言中结构体的最后一个元素可以是大小未知的数组
 
* C语言中一般由结构体产生柔性数组
 
 
1.3字符数组与字符串
char s1[5] = {'a', 'b', 'c', ''};
char s2[5] = {"abc"};
char s3[5] = "abc";        //三个表达式所达到的效果一样
 
任何数组的名字代表了首元素的地址,即s1 = &s1; “abc”代表 a 字符的地址,故有:字符串变量和字符数组,它们的变量名代表首字符地址
注意:字符串默认有一个null结束符,字符数组没有
printf("%c ", s3[1]);
printf("%c ", "abc"[1]);
 
--->延伸:常量字符串是一个匿名的字符数组的名字
 
 
顺便提一下 sizeof 和 strlen 的区别
sizeof(s2) = 3   //求s2字符串有几个字符(不包括'')
strlen(s2) = 5   //求s2有几个字符 (包括''和乱码的字符)
 
 
 
2.内存地址(指针)
内存组织单元:字节(32位的计算机有内存2^32个字节)
 
2.1指针定义和初始化( 定义初始化分开写也行 )
int * p  = &a;
 
2.2指针赋值
int b = 200;
p = &b;
 
2.3取目标(解引用)
*p = 201;
==>  b = 201;
 
2.4取地址
int *(*k);
k = &p;
*p = 202;    ==>  b = 202;
 
2.5加减法(数组运算/指针运算)
int number[4] = {11,22,33,44};
int *p;
p = number;        //等价于p = &number[0];   数组运算时,数组名字代表首元素的地址
p = p+2;        //若p原来指向  0x008000,运行之后p指向0x008008.因为p是int *类型的。 //等价于p = &number[2];
 
 
 
以下解释类型的思想:
1 int *p1;    //p1是int *类型
2 p1 = &a;    
3  
4  
5 int *(*q);        //   *q  是 int*的类型
6   2      1     
7  
8  q = &p1;    //故写成这样是可行的
==》取得的函数或者变量的类型方法:是将函数/变量的名字盖住,剩下的就是类型
如:int a[3];  的类型是  int[3]
 
例子1:
int a[5] = {1,2,3,4,5};
int (*p)[5];
p = &a;    //此处的 a 代表整个数组,取数组a的地址,也就是取数组第一个元素的所在的地址
p =a;      //此语句错误!!!!!因为p指向整个数组a的,因为p的类型是int [5] 的指针,只能用来指向整个数组,不可以用来指向一个变量
 
例子2:
float f[5] = {1,2,3,4,5};
float (*p2)[5] = {1,2,3,4,5};
==>     p2 = &f;        //p2指向float的整体(f在此处不看做地址,而是一个数组的名字)   *p2 = f;  p2 = &f;
因此,f[2] = 30;
可以写成:  (*p2)[2] = 30;
 
匿名内存:malloc
int *p = malloc(100);//malloc分配的内存是没有名字的,然后给它定义类型 int *  和名字 p
 
 
 
函数声明
int sumup(int a, float b);
int (*p3) (int a, float b);    //指针p3使用来指向函数sumup的
【回顾:两者的类型都是  int    (int a, float b);】
 
int* (*p4)(int a, float b);
从类型上看,int*  (int a, float b) 是上式函数的指针。故有:p4 = &p3;
 
函数的调用
sumup (100,1.21);
(*p3) (100,1.21);      //与上等价
*(p4) (100,1.21);       //与上等价
 
 
4.void指针
(通常用于在分配完成后,不知是什么类型的指针。好处在于:void指针可以赋值给任何类型的指针)
定义与初始化:
void * p5 = malloc(100);        //malloc函数就是一个void指针
 
在内存中放置数据需转化内存
int i;
for(i=0; i<25; i++)
{
    *((int*)p5+1) = i+1;            //将p5指向的那一块占100字节的内存存入{1,2,3,4....25}一共25个int型数据
}
 
 
5.空指针
表达形式:
int *p6 = NULL;
int *p7 = 0;    
 
 
6.const指针
在C语言中不可以用来定义常量
const int b;
int const b;        //等效上式
 
(在c++中,const int globle ;为const常量)
 
只能在初始化的时候赋值 !
int const b = 5;
 
在指针应用中,const前后的差别:
-->可以通过p来修改目标
const char *p = &b;
char const *p = &b;
 
-->p本身不能修改
char *const p = &b;
原文地址:https://www.cnblogs.com/simonLiang/p/5691661.html