数组名的技术盲点
- 数组首元素的地址和数组地址是两个不同的概念
- 数组名代表数组首元素的地址,它是个常量。
- 解释如下:变量本质是内存空间的别名,一定义数组,就分配内存,内存就固定了。所以数组名起名以后就不能被修改了。
- 数组首元素的地址和数组的地址值相等
- 怎么样得到整个一维数组的地址?
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
void main()
{
int a[] = { 1, 2};
int b[100] = { 1, 3 };
int c[200] = { 0 }; //编译时 就已经确定 所有的值 为零
memset(c, 0, sizeof(c)); //显示的 重置内存块
// 对一维数组C规定:
// c 是数组首元素的地址 c+1 步长 4个字节
// &c 是整个数组的地址 &c+1 步长 200*4
system("pause");
return;
}
C语言规定:
Int a[10];
printf("得到整个数组的地址a: %d \n", &a); // 整个数组的地址
printf("数组的首元素的地址a: %d \n", a); // 首元素的地址
怎么样表达int a[10]这种数据类型那?
数组类型、数组指针类型、数组指针类型变量
数组类型
- 1数据类型分为基础、非基础,思考角度应该发生变化
- 2 C语言中的数组有自己特定的类型
- 数组的类型由元素类型和数组大小共同决定
- 例:int array[5]的类型为int[5]
数组定义:
typedef int(MYINT5)[5]; //int
typedef float(MYFLOAT10)[10];
MYINT5i Array; int array[5];
MYFLOAT10fArray
定义数组类型,并用数组类型定义变量
void main()
{
typedef int(MyArrayType)[5]; // 定义了一个数据类型 数组数据类型
int i = 0;
MyArrayType lessons;
for (i = 0; i < 5; i++) {
lessons[i] = i + 1;
}
printf("lessons:%d lessons+1:%d\n", lessons, lessons + 1); // lessons : 4193968 lessons + 1 : 4193972 步长4
printf("&lessons:%d &lessons+1:%d\n", &lessons, &lessons + 1); // &lessons : 4193968 &lessons + 1 : 4193988 步长20
system("pause");
return;
}
数组指针类型
- 定义数组指针变量的方法1:用数组类型 加*
void main()
{
char *MyArray[] = { "111","2222","3333" }; // 指针 数组
typedef int(MyArrayType)[5]; // 定义了一个数据类型 数组数据类型
int i = 0;
MyArrayType lessons; // 数据类型 定义变量
MyArrayType *pLessons; // 数据类型 定义一个指针变量 这个指针变量 指向一个数组
{
int a;
int *p = NULL;
p = &a;
}
{
int lessons2[5];
// 可以通过指针变量pLessons来操作lessons2的内存空间
pLessons = &lessons2; // pLessons = &lessons;
for (i = 0; i < 5; i++) {
// lessons2[i] = i + 1;
(*pLessons)[i] = i + 1;
}
for (i = 0; i < 5; i++) {
printf("%d ", (*pLessons)[i]); // 1 2 3 4 5
}
}
system("pause");
return;
}
- 定义数组指针变量的方法2
void main()
{
typedef int (*MyArrayType)[5]; // 定义了一个数组指针类型
MyArrayType pLessons; // 告诉编译器 分配一个指针变量
int c[5];
int i = 0;
pLessons = &c;
for (i = 0; i < 5; i++) {
(*pLessons)[i] = i + 1;
}
for (i = 0; i < 5; i++) {
printf("%d ", (*pLessons)[i]); // 1 2 3 4 5
}
system("pause");
return;
}
- 定义数组指针变量的方法3
- 前面两种方法 通过类型定义 比较麻烦
- 直接定义 int (*pLessons)[5]
void main()
{
int c[5];
int i = 0;
int (*pLessons)[5]; // 直接定义了一个指向数组的 指针变量
pLessons = &c;
for (i = 0; i < 5; i++) {
(*pLessons)[i] = i + 1;
}
for (i = 0; i < 5; i++) {
printf("%d ", (*pLessons)[i]); // 1 2 3 4 5
}
system("pause");
return;
}
多维数组的本质
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
void printfArr1(int a[3][5])
{
int i, j, tmp = 0;
for (i = 0; i < 3; i++)
{
for (j = 0; j < 5; j++)
{
printf("%d ", a[i][j]);
}
}
return;
}
void printfArr2(int a[][5])
{
int i, j, tmp = 0;
for (i = 0; i < 3; i++)
{
for (j = 0; j < 5; j++)
{
printf("%d ", a[i][j]);
}
}
return;
}
//多维数组做函数参数的推演
void printfArr3(int(*b)[5])
{
int i, j, tmp = 0;
for (i = 0; i < 3; i++)
{
for (j = 0; j < 5; j++)
{
printf("%d ", b[i][j]);
}
}
return;
}
void main()
{
int a[3][5];
int i = 0, j = 0, tmp = 1;
for (i = 0; i < 3; i++)
{
for (j = 0; j < 5; j++)
{
a[i][j] = tmp++;
}
}
printf("\n-------------------\n");
printfArr3(a);
printf("\n-------------------\n");
for (i = 0; i < 3; i++)
{
for (j = 0; j < 5; j++)
{
printf("%d ,", a[i][j]);
}
}
printf("\na:%d , a+1:%d\n ", a, a + 1);//a+1的步长是20个字节 5*4
printf("&a:%d , &a+1:%d\n ", &a, &a + 1);
{
//定义一个指向数组的指针变量
int(*pArray)[5];//告诉编译器 分配4个字的内存 32bit平台下
pArray = a;
for (i = 0; i < 3; i++)
{
for (j = 0; j < 5; j++)
{
printf("%d,", pArray[i][j]);
}
}
}
/*
多维数组的本质 数组指针 ,步长 一维的长度
(a) 代表是第0行的整个地址 (第一行的地址 和 第一行首元素的地址是重叠的。。。)
(a+i) 代表是第i行的首地址 2级指针
*(a+i) 代表 1级指针 第i行的首元素的地址
*/
/*
转化推演:
*( *(a+i) + j) ===>a[i][j] 元素的值
a[i][j] <===> *(*(a+i)+j)
a[i] ===> a[0+i] ===>*(a+i) 0是占位符
a[i][j]===a[0+i][j] ==> *(a+i)[j] ===>*(a+i)[0+j] ===>* ( *(a+i) + j)
**/
system("pause");
return;
}