数组名
数组名代表数组首元素的地址,它是个常量。数组首元素的地址和数组地址是两个不同的概念。变量本质是内存空间的别名,一定义数组,就分配内存,内存就固定了。所以数组名起名以后就不能被修改了。 数组首元素的地址和数组的地址值相等。 怎么样得到整个一维数组的地址?
int a
[10];
printf("得到整个数组的地址a: %d \n", &a
);
printf("数组的首元素的地址a: %d \n", a
);
数组类型
int a[] = { 1, 3, 5 }; //3个元素
a: 数组首行首元素地址,一级指针
&a: 整个数组的首地址,二级指针
首行首元素地址和首行(整个一维数组)地址值虽然是一样,但是它们的步长不一样
a+1: 跳过1元素,一元素为4字节,步长4个字节
&a+1: 跳过整个数组,整个数组长度为 3*4 = 12,步长 3 * 4 = 12
sizeof(a): 传参为:数组首行首元素地址,测数组(int [3])的长度,3 * 4 = 12
sizeof(a[0]): 传参为:数组首元素(不是地址),每个元素为int类, 4字节
sizeof(&a):传参为:一维数组整个数组的地址(首行地址),编译器当做指针类型,4字节
(重要)首行地址 --> 首行首元素地址(加*)
&a:首行地址
*&a -> a : 首行首元素地址
//数组也是一种数据类型,类型本质:固定大小内存块别名
//由元素类型和内存大小(元素个数)共同决定 int a[5] int[5]
//可以通过typedef定义数组类型
//有typedef:类型
//没有typedef:变量
typedef int ARRARY[5]; //定义了一个名字为ARRARY的数组类型
//等价于typedef int (ARRARY)[5];
//根据数组类型,定义变量
//ARRARY的位置替代为d,去掉typedef,int d[5]
ARRARY d; //相当于int d[5];
基本数据类型大小x数组元素个数=数组大小
数组的类型由元素类型和数组大小共同决定
int array[5] 的类型为 int[5];
一维数组的初始化
int a
[] = { 1, 3, 5 };
int b
[5] = { 1, 2, 3 };
int c
[10] = { 0 };
memset(c
, 0, sizeof(c
));
多维数组
1)二维数组初始化
int a1[3][4] = {
{1, 2, 3, 4},
{5, 6, 7, 8},
{9, 10, 11, 12}
};
int a2[3][4] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12 };
int a3[][4] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12 };
2)内存中并不存在多维数组,多维数组在内存中都是线性存储
int a[3][5] = { 0 };
int *b = (int *)a;
int i = 0;
for(i = 0; i < 15; i++)
{
printf("%d ", b[i]);
}
3)多维数组名
//学会类比
int b[5] = {0};
b: 首行首元素地址, +1,跳 4 个字节
&b:首行地址,+1,跳 4*5 = 20个字节
//二维数组实际上就是 N 个一维数组
//把二维数组第一个[]的值看做标志位,0 -> 2
//第0个一维数组a[5] -> 第2个一维数组a[5]
int a[3][5] = { 0 };
a:
二维数组首元素地址
代表首行地址,相当于一维数组整个数组的地址,相当于上面的 &b,本来就是一个二级指针
//(重要)首行地址 --> 首行首元素地址(加*)
*a:首行首元素地址,相当于一维数组首元素地址,相当于上面的 b
a + i -> &a[i]: 第i行地址
//(重要)某行地址 --> 某行首元素地址(加*)
*(a+i) -> *&a[i] -> a[i]: 第i行首元素地址
//第i行j列元素的地址,某行首元素地址 + 偏移量
*(a+i)+j -> a[i]+j -> &a[i][j]: 第i行j列元素的地址
//第i行j列元素的值,第i行j列元素的地址的基础上(加 *)
*(*(a+i)+j) -> a[i][j]: 第i行j列元素的值
int a[3][5] = { 0 };
sizeof(a): 二维数组整个数组长度,4 * 3 * 5 = 60
sizeof(a[0]):a[0]为第0行首元素地址,相当于测第0行一维数组的长度:4 * 5 = 20
sizeof(a[0][0]):a[0][0]为第0第0列元素(是元素,不是地址),测某个元素长度:4字节
4)多维数组名,实际上是一个数组指针,指向数组的指针,步长为一行字节长度
int a[3][5] = { 0 };
//定义一个数组指针类型的变量
int(*p)[5];
//编译会有警告,但不会出错,因为 a 和 &a的值一样
//但是&a代表整个二维数组的首地址
//就算p = &a这样赋值,编译器内部也会自动转换为 p = a
//不建议这么做
p = &a;
//a 本来就是第0个一维数组整个数组的地址,所以,无需加&
p = a;
5)二维数组做形参的三种形式
//一维数组做函数参数退化为一级指针
//二维数组(多维数组)做函数参数,退化为数组指针
int a[3][5] = { 0 };
void print_array1(int a[3][5]);
//第一维的数组,可以不写
//第二维必须写,代表步长,确定指针+1的步长 5*4
void print_array2(int a[][5])
//形参为数组指针变量,[]的数字代表步长
void print_array3(int (*a)[5]);
//a+1和二维数组的步长不一样
//这里的步长为4
//上面二维数组的步长为 5 * 4 = 20
void print_array3(int **a); //err
字符数组初始化方法
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
int main()
{
char buf1
[] = {'a', 'b', 'c', 'd'};
char buf2
[100] = {'a', 'b', 'c', 'd'};
printf("buf1: %s\n", buf1
);
printf("buf2: %s \n", buf2
);
printf("buf2[88]:%d \n", buf2
[88]);
char buf3
[] = "abcd";
int len
= strlen(buf3
);
printf("buf3字符的长度:%d \n", len
);
int size
= sizeof(buf3
);
printf("buf3数组所占内存空间大小:%d \n", size
);
char buf4
[128] = "abcd";
printf("buf4[100]:%d \n", buf4
[100]);
return 0;
}
数组法和指针法操作字符串
#include <stdio.h>
#include <string.h>
int main(void)
{
int i
= 0;
char *p
= NULL;
char buf
[128] = "abcdefg";
for (i
=0; i
<strlen(buf
); i
++)
{
printf("%c ", buf
[i
]);
}
p
= buf
;
for (i
=0; i
<strlen(buf
); i
++)
{
printf("%c ", *(p
+i
) ) ;
}
for (i
=0; i
<strlen(buf
); i
++)
{
printf("%c ", *(buf
+i
) ) ;
}
return 0;
}
字符串做函数参数
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
int main(void)
{
char a
[] = "i am a student";
char b
[64];
int i
= 0;
for (i
=0; *(a
+i
) != '\0'; i
++)
{
*(b
+i
) = *(a
+i
);
}
b
[i
] = '\0';
printf("a:%s \n", a
);
printf("b:%s \n", b
);
return 0;
}
字符串拷贝函数的实现
```handlebars
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main01(void)
{
char src
[] = "abcedfdgds";
char dst
[100] = { 0 };
int i
= 0;
for (i
= 0; src
[i
] != '\0'; i
++)
{
dst
[i
] = src
[i
];
}
dst
[i
] = 0;
printf("%s\n", dst
);
printf("\n");
system("pause");
return 0;
}
void my_strcpy(char *dst
, char *src
)
{
int i
= 0;
for (i
= 0; *(src
+i
) != '\0'; i
++)
{
*(dst
+i
) = *(src
+i
);
}
*(dst
+ i
) = 0;
}
void my_strcpy2(char *dst
, char *src
)
{
while (*src
!= 0)
{
*dst
= *src
;
dst
++;
src
++;
}
*dst
= 0;
}
void my_strcpy3(char *dst
, char *src
)
{
while (*dst
++ = *src
++)
{
NULL;
}
}
int my_strcpy4(char *dst
, char *src
)
{
if (dst
== NULL || src
== NULL)
{
return -1;
}
char *to
= dst
;
char *from
= src
;
while (*to
++ = *from
++)
{
NULL;
}
printf("my_strcpy4: dst = %s\n", dst
);
return 0;
}
int main(void)
{
char src
[] = "abcedfdgds";
char dst
[100] = { 0 };
int ret
= 0;
ret
= my_strcpy4(dst
, src
);
if (ret
!= 0)
{
printf("my_strcpy4 err:%d\n", ret
);
return ret
;
}
printf("%s\n", dst
);
printf("\n");
system("pause");
return 0;
}
希望关注点赞评论,传递知识
想要关注我一起学习的请关注公众号:莫林的日常
想要和志同道合的伙伴一起学习的请加QQ群:515271405