目录
一、指针和数组
🍐 数组名指向首地址
int *p=&A[0]
int *p=A;
🍊 例子
#include<stdio.h>
int main()
{
int A[] ={2,4,5,8,1};
int i;
int *p = A;
p++;
// A++; // invalid!! compile error
printf("Address &A= %lu\n", &A);
printf("Address A= %lu\n", A);
for (int i=0; i < 5; i++) {
printf("Address = %lu\n", &A[i]);
printf("Address = %lu\n", A+i);
printf("Value = %lu\n", A[i]);
printf("Value = %lu\n", *(A+i));
}
return 0;
}
Notes:
数组名不能自增。
输出:
Address &A= 140737488347616
Address A= 140737488347616
Address = 140737488347616
Address = 140737488347616
Value = 2
Value = 2
Address = 140737488347620
Address = 140737488347620
Value = 4
Value = 4
Address = 140737488347624
Address = 140737488347624
Value = 5
Value = 5
Address = 140737488347628
Address = 140737488347628
Value = 8
Value = 8
Address = 140737488347632
Address = 140737488347632
Value = 1
Value = 1
二、数组作为函数参数
当数组作为函数参数时,当传入 数组名[] (A [] ) 并不会将整个数组拷贝一遍,编译器将形参的int A[ ]理解为指针,而非数组。
🍋 数组名作为函数参数,为什么必须传递数组大小?
#include<stdio.h>
// int SumOfElements(int *A)
int SumOfElements(int A[])
{
int i,sum=0;
int size=sizeof(A)/sizeof(A[0]); // 这里是A被理解为一个指针,sizeof(A)=8
printf( "size of A = %d,size of A[0] = %d\n",sizeof(A),sizeof(A[0]) );
for(i=0;i<size;i++)
{
sum += A[i];
}
return sum;
}
int main()
{
int A[] = {1,2,3,4,5};
int total= SumOfElements(A);
printf( "数组元素之和 = %d\n",total );
printf( "size of A = %d,size of A[0] = %d\n",sizeof(A),sizeof(A[0]) );
}
输出
size of A = 8,size of A[0] = 4
数组元素之和 = 3
size of A = 20,size of A[0] = 4
改进
#include<stdio.h>
// int SumOfElements(int *A, int size)
int SumOfElements(int A[], int size)
{
int i,sum=0;
for(i=0;i<size;i++)
{
sum += A[i];
}
return sum;
}
int main()
{
int A[] = {1,2,3,4,5};
int total= SumOfElements(A, sizeof(A)/sizeof(A[0]));
printf( "数组元素之和 = %d\n",total );
}
输出
数组元素之和 = 15
三、指针和字符数组
🍌怎么样存储一个string?
- (size of array) >= (num of characters in string + 1)
- 所有的字符串函数均假定字符串以 \0 结束
#include <stdio.h>
#include <string.h>
int main()
{
char C[10];
C[0] = 'J';
C[1] = 'O';
C[2] = 'H';
C[3] = 'N';
printf("%s\n",C); // 打印出乱码
C[4] = '\0';
printf("%s\n",C); // 正常打印
printf("字符串长度C=%d\n\n",strlen(C)); // \0不算入字符串长度
char s[] = "GZC"; // 自动计算长度,字符串子面值隐含了\0
// char s[4] = "GZC";
// char s[4] = {'G','Z','C','\0'};
printf("%s\n",s);
printf("字符串长度s=%d\n",strlen(s)); // \0不算入字符串长度
printf("size of s=%d\n",sizeof(s)); // 将\0也计算在内
}
输出
JOHN���
JOHN
字符串长度C=4
GZC
字符串长度s=3
size of s=4
🍉数组和指针是以相似方式使用的不同类型
- C2和C1在内存上是不一样的,一个以 \0 结尾,一个只是一个指针
- C2=C1 is valid, C1=C2 is invalid
- C1++也是invalid的
🍇 例子
上图的指针为4 bytes
char test[] = "hello"; //字符串存放在栈空间,可修改
char *test = "hello"; //字符串存放在只读数据区,不可修改
四、指针与二维数组
🍓 数组在计算机中的组织形式
上面这些可以通过画框法来进行理解
换算公式
五、指针与多维数组
🍈 例子
#include<stdio.h>
void func(int A[][2][2])
{
printf("hello world\n");
}
int main()
{
int C[3][2][2] = {{{2, 5}, {7, 9}},
{{3, 4}, {6, 1}},
{{0, 8}, {11, 13}}};
printf("%lu %lu %lu %lu \n",C,*C,C[0],&C[0][0]);
printf("%lu\n",*(C[0][0]+1));
func(C);
return 0;
}
输出
140737488347584 140737488347584 140737488347584 140737488347584
5
hello world
六、数组通过指针动态分配内存
🍟 一维数组
首先,考虑一个一维数组。如果你需要创建一个包含num_elements个unsigned int的数组,你可以这样做:
unsigned int* array = new unsigned int[num_elements];
🍕 二维数组
当你需要创建一个二维数组时,情况就变得复杂了。一个二维数组可以看作是一个数组,其中每个元素都是一个数组。因此,你需要一个指针来指向这些内部数组,而每个内部数组本身也需要一个指针来指向它们的元素。
假设你想要创建一个二维数组,其中有num_rows行和num_cols列(每行包含num_cols个unsigned int元素)。你可以这样初始化它:
unsigned int** array_2d = new unsigned int*[num_rows];
for (int i = 0; i < num_rows; ++i) {
array_2d[i] = new unsigned int[num_cols];
}
在这个例子中:
- array_2d是一个指向unsigned int*的指针(即二级指针)。它指向一个数组,这个数组的每个元素都是一个指向unsigned int的指针(即每行都是一个unsigned int数组)。
- array_2d[i]是一个指向unsigned int的指针(即一级指针),它指向第i行的数组。
- array_2d[i][j]访问的是第i行第j列的元素。
🥪二维数组妙用
#include <iostream>
#include <string.h>
using namespace std;
int main() {
unsigned int** new_table = nullptr;
int num_clks=5;
int alloc_size=num_clks*(1+num_clks)>>1; //分配一个三角形
new_table = new unsigned int*[num_clks]; // 分配一个包含5个int*的数组
new_table[0] = new unsigned int[alloc_size]; // 分配一个包含15个int的数组,并使new_table[0]指向它
bzero(new_table[0],alloc_size);
for(int i=1;i<num_clks;i++)new_table[i]=new_table[i-1]+i;
for(int i=0;i<alloc_size;i++)new_table[0][i]=i;
for(int i=0;i<alloc_size;i++)cout<<new_table[0][i]<<" ";
cout<<endl;
for(int i=0;i<num_clks;i++){
for(int j=0;j<=i;j++)cout<<new_table[i][j]<<" ";
cout<<endl;
}
return 0;
}
- 在例子中,new_table 是一个 unsigned int** 类型的变量,这意味着 new_table 是一个指向 unsigned int* 类型的指针的指针。