指针和数组并不是相等的,
当声明一个数组时,它同时也分配了一写内存空间,用于存储数组元素,
但当声明一个指针时,它只分配了用于容纳指针的空间(32位中4个字节的大小)。
如:
以下标方式 array[i]
站在c++编译器的角度, *p 相当于我们程序员手工(显示)利用间接赋值,去操作内存
"[]"是c++编译器帮我们程序员做了一个*p的操作
当一个数组名作为函数参数时,数组名的值就是指向数组第一个元素的指针,所以此时传递给函数的是指针的拷贝。
#include <iostream.h> int sum ( int ap[ ] , int n ) { int m = 0 ; for ( int i = 0 ; i < n ; i ++ ) { m += * ap ; ap ++ ; } return m; } void main() { int a [ 10 ] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 } ; cout << "sum = " << sum ( a , 10 ) << endl ; }
int sum(int ap[], int n) 和int sum(int *ap, int n)效果一样的
指针作为函数形参和数组作为函数形参是一样的.
二维数组名同样代表数组首元素的地址
//int b[2][5]===>b的类型为int(*)[5]不是char**
多维数组名的本质:数组指针即
指向一个数组的指针
int a[3][5]
(a+i) 代表是整个第i行的地址
*(a+i)就表示
第i行首元素的地址
*(a+i) + j ===> & a[i][j]
*( *(a+i) + j) ===>a[i][j]元素的值
一级指针做函数参数:
二维数组可以看做是一维数组
二维数组中的每个元素是一维数组
二维数组参数中第一维的参数可以省略
void f(int a[5]) ====》void f(int a[]); ===》 void f(int* a);
void g(int a[3][3])====》 void g(int a[][3]); ====》 void g(int (*a)[3]);
实参 ( 数组参数 ) | 所匹配的形参(等效指针参数) |
一维数组 char a[30] | 指针 char* (可直接char* p=a;下面的类似) |
指针数组 char *a[30] | 指针的指针 char **a 指针的指针([30]数组做函数参数退化为指针 , 况且又是个指针数组所以**) |
二维数组 char a[10][30] | 数组的指针 char(*a)[30](数组指针 |
数组指针(行指针)char(*c)[10] | char(*c)[10] 不改变 |
指针的指针 char**c(二重指针) | char**c 不改变 |
int printfArr23_1(char myArray[10][30], int iNum) { int i = 0; for (i=0; i<iNum; i++) { printf("%s \n", myArray[i]); } return 0; } int printf2Array_2(char myArray[][30], int iNum) { int i = 0; for (i=0; i<iNum; i++) { printf("%s \n", myArray[i]); } return 0; } int printf2Array_3(char (*myArray)[30],int iNum) { int i = 0; for (i=0; i<iNum; i++) { printf("%s \n", myArray[i]); } return 0; } void main() { int i = 0; char myArray[10][30] = {"ccccc", "aaaa", "bbbb","11111"}; // printf2Array_2(myArray, 4); printf2Array_3(myArray, 4); system("pause"); }
多维数组名本质就是一个数组指针
二重指针的用法
(1)二重指针指向一重指针的地址
(2)二重指针指向指针数组的
(3)实践编程中二重指针用的比较少,大部分时候就是和指针数组纠结起来用的。
(4)实践编程中有时在函数传参时为了通过函数内部改变外部的一个指针变量,会传这个指针变量的地址(也就是二重指针)进去。
int main() { char* str[] = {"abcde","aqw","ulk"}; char **str1 = str;// { "abcde", "aqw", "ulk" };不可以直接定义 **str1 = { "abcde", "aqw", "ulk" };指针数组指针 cout << "sizeof(str)" << sizeof(str) << endl; cout << "sizeof(str[1])" << sizeof(str[1]) << endl; cout << "sizeof(str[0])" << sizeof(str[0]) << endl; for (int i = 0; i < sizeof(str) / sizeof(str[0]);i++) { printf("%s\n", str1[i]); }system("pause"); return 0; }
华为的面试题:
若有函数声明voidf(char** p),则使得函数调用f(var)不正确的var定义是———?
A char var[10][10]; B char *var[10]
C void* var=NULL; D char* v=NULL,**var=&v;
解析:
1.char var[10][10];var的类型是 char (*)[10] 类型(不理解的话需要好好看看课本)
2.char *var[10]; var数组是存放char *类型的数组,数组名var是数组var元素的首地址,所以var的
类型是char**类型
3.void * 是定义没有指针类型的指针,void *可以指向任何类型的数据。在c99中举个例子int *p = malloc(sizeof(int)); 可以不写强制类型转换,因为malloc返回一个void *类型的指针,
char**p = malloc(100); 这样定义一样可以通过
4.v是char*类型的,那么取v的地址肯定是char**类型的,所以var是char**类型的。
结构体变量作为函数形参的时候,实际上和普通变量(类似于int之类的)传参时表现一样的。所以说结构体变量其实也是普通变量。
用结构体变量作实参时,采取的是“值传递”的方式