指针和数组

1 int i=3;
2 int* p=&i;
3 int*pp; pp=&i;
4 int* ppp; *ppp=i;

指针:
本质上也是变量;需要占用内存空间;存储另一个变量的地址值

不同类型的指针:(int* char* long*)

不同类型的指针,它本身所占内存大小(var_name)是相同的,不过它指向的内存空间大小(*var_name)不一样。由于指针变量存储的是内存地址,所以对于32位机上,指针变量应该占用32位。

*:

在指针声明时,*表示声明的变量为指针

在指针使用时,*表示指针所指向的内存空间中的值

传值调用与传址调用:

当一个函数体内部需要改变实际参数的值,则需要指针参数

函数调用时,实际参数的值复制到形式参数的空间,值有两种情况的取值:实际的值,地址值:

 1 struct test 
 2 {
 3   int a[10000];
 4   char b[100000];
 5 };
 6 void ff(struct test tt)
 7 {
 8    for(int i;i<10000;i++)
 9       tt.a[i]=0;
10 }
11 int main()
12 {
13 ff(ss); 14 return 0; 15 }

此时传值调用,这将复制大量的数据,而传址调用,只会复制一次。

数组:

数组是相同类型的变量的有序集合。

int a[5];

a代表这个有序集合的起始地址,第一个元素的地址,即:

a=&a[0],

a+1=&a[1]

a[3]=*(a+3)

a是一个常量指针,在表达式中只能作为右值使用,只能在以下情况下不能看作是常量指针:

sizeof(a)  //表示整个数组的长度

&a   //a=&a

分配了5个int型的内存空间——a[0]-a[4]

数组空间大小:sizeof(int)*5=sizeof(a)

数组元素的个数可以显式或隐式之指定:

int a[5]={5,2};//a[0]=5,a[1]=2;a[2],a[3],a[4]均为0

int b[]={1,2}; //只分配两个int型空间:b[0]=1,b[1]=2

int c[5]={0}; //将所有变量赋值为0

当初始化列表小于变量个数,剩余的变量以0进行初始化;如果变量不进行初始化,那么将分别是随机值

a与&a的区别:

a代表数组的首元素地址,&a表示整个数组的地址,a=&a

a+1=&a[1]

&a+1表示整个数组空间所占内存空间的下一个空间地址

1 int a[5]={0};
2 p=a;
3 p+14 a+1;
 1 #include <stdio.h>
 2 int main()
 3 {
 4     int a[5] = {1, 2, 3, 4, 5};
 5     int* p1 = (int*)(&a + 1);  
 6     int* p2 = (int*)((int)a + 1);
 7     int* p3 = (int*)(a + 1); 
 8     printf("%d, %d, %d
", p1[-1], p2[0], p3[1]);   
 9     return 0;
10 }
11 
12 // p1[-1]==>*[p1-1];a[3]=*[a+3]
13 //a+1区别于(int)a+1,因为每个字节对应一个地址,那么(int)a+1表示的是第一个数组变量的第二个字节的地址,a=(int)a,
14 //a+1表示第二个数组变量的地址

c语言中,数组作为函数参数时,编译器将其编译成对应的指针:

1 void func(int a[]);-->void func(int* a);
2 void func(int a[4]);-->void func(int* a); //调用时并不执行int a[4]

一般情况下,当定义的函数中有数组参数时,需要另一个参数标识数组的长度。

内在的趣味,表面的繁琐
原文地址:https://www.cnblogs.com/data1213/p/4823481.html