黑马程序员——C语言学习之数组——字符串——指针
来源:互联网 发布:手机浏览器启动淘宝 编辑:程序博客网 时间:2024/06/05 23:49
------Java培训、Android培训、iOS培训、.Net培训、期待与您交流! -------
数组
一、数组的基本概念
1. 什么是数组
数组,从字面上看,就是一组数据的意思,没错,数组就是用来存储一组数据的
2. 数组的特点
1> 只能存放一种类型的数据,比如int类型的数组、float类型的数组
2> 里面存放的数据称为“元素”
二、数组的定义
1. 定义
想要定义一个数组,需要声明两点:
声明数组的类型
声明数组的元素个数(需要多少存储空间)
2. 格式
元素类型 数组名[元素个数];
比如:
int a [3];
3. 初始化
1> 初始化方式
int a[3] = {10, 9, 6};int a[3] = {10,9};int a[] = {11, 7, 6};int a[4] = {[1]=11,[0] = 7};
2> 常见错误
int a[];int[4] a;int a[b];a = {10, 11};a[4] = {10,9,8,5};
4>一维数组作为函数参数
数组名代表着整个数组的地址,如果一维数组的名字作为函数实参,传递的是整个数组,这样形参数组修改时,实参数组也同时被修改了。形参数组的元素个数可以省略。
三、二维数组
1> 二维数组的定义
其实二维数组就相当于装着一维数组的一维数组。
定义形式:
类型 数组名[行数][列数]
例如:
int a[2][3]; // 共2行3列,6个元素
2>二维数组的初始化
1> 按行进行初始化
int a[2][3] = { {2, 2, 3}, {3, 4, 5} };
2> 按存储顺序进行初始化(先存放第1行,再存放第2行)
int a[2][3] = {2, 2, 3, 3, 4, 5};
3> 对部分元素进行初始化
int a[2][3] = { {2}, {3, 4} };int b[3][3] = { { }, { , , 2}, {1, 2, 3}};
4> 如果只初始化了部分元素,可以省略行数,但是不可以省略列数
<strong>int a[][3] = {1, 2, 3, 4, 5, 6};int a[][3] = {{1, 2, 3}, {3, 5}, {}};</strong>
写在最后:
有些人可能想不明白,为什么可以省略行数,但不可以省略列数。也有人可能会问,可不可以只指定行数,但是省略列数?其实这个问题很简单,如果我们这样写:
int a[2][] = {1, 2, 3, 4, 5, 6}; // 错误写法
大家都知道,二维数组会先存放第1行的元素,由于不确定列数,也就是不确定第1行要存放多少个元素,所以这里会产生很多种情况,可能1、2是属于第1行的,也可能1、2、3、4是第一行的,甚至1、2、3、4、5、6全部都是属于第1行的
字符串
一、字符串
字符串可以看做是一个特殊的字符数组,并在字符串的尾部添加了一个结束标志 '\0'。
1. 字符串的初始化
// ‘\0’的ASCII码值是0 // 都是字符串 char name[5] = "it"; char name2[5] = {'i', 't', '\0'}; char name3[5] = {'i', 't', 0}; char name4[5] = {'i', 't'}; char name5[5]; name5[0] = 'i'; name5[1] = 't'; name5[2] = 0; name5[3] = 0; name5[4] = 0; // 不算是一个字符串(只能说是一个字符数组) char name6[] = {'i', 't'};
2. printf函数
printf函数在输出字符串的时候会从所给的字符串地址开始输出,直到遇到 '\0' 时结束输出。如下:
char name[20] = "helloworld\0welcome"; printf("%s\n", name);printf("%s\n", &name[3]);
输出:
helloworldloworld
分析:
printf 函数在输出字符串时,接收的是字符串的地址。
printf("%s\n", name); 中的name其实是name[20]数组中的首地址,和&name[0]同一意思,所以从name[0]开始输出,直到'\0'时结束。
printf("%s\n", &name[3]);也是一样的,从name[3]的位置开始输出,直到 '\0'时结束。
3. strlen函数
1> 计算的字符不包括 '\0'
2> 计算的是字符数,并不是字数。一个汉字算作3个字符
3> 从某个地址开始数字符的个数,直到遇到 '\0' 为止
例如:
int len = strlen("hello"); int len2 = strlen("helloćˆ‘"); int len3 = strlen("hello\0world"); printf("%d\n", len); printf("%d\n", len2);printf("%d\n", len3);
输出:
585
分析:
应用1、2、3点就可以理解了
二、字符串数组
1. 使用场合
1> 一维字符数组中存放一个字符串,比如一个名字char name[20] = "mj"
2> 如果要存储多个字符串,比如一个班所有学生的名字,则需要二维字符数组,char names[15][20]可以存放15个学生的姓名(假设姓名不超过20字符)
3> 如果要存储两个班的学生姓名,那么可以用三维字符数组char names[2][15][20]
2. 初始化
char names[2][10] = { {'J','a','y','\0'}, {'J','i','m','\0'} }; char names2[2][10] = { {"Jay"}, {"Jim"} }; char names3[2][10] = { "Jay", "Jim" };
指针
一、什么是指针?
指针是用来存放变量地址的。通过指针可以间接操纵变量。
二、指针的定义
变量类型 *变量名;
如:int *p;定义了一个int类型的指针p。
注意:任何类型的指针都占据8个字节的存储空间
三、指针的初始化
1. 先定义,后初始化
int a = 10; // 定义变量a intint *p; // 定义int型指针p p = &a; // 给指针p赋值,存放的是变量a的存储地址
2. 定义的同时初始化
int a = 10; // 定义变量a intint *p = &a; // 定义int型指针p,同时给指针p赋值,存放的是变量a的存储地址
四、指针的使用
1. 取出指向变量的值
int a = 10; intint *p = &a; int value = *p; // 访问指针p所指向的变量a的值,并赋值个value,value = 10;
2、给指针指向的变量赋值
int a = 10; intint *p = &a; *p = 20; // 指针p所指向的变量的值被改成20,也就是a的值被改成20
* 的含义:
int *p = &a 中的 * 用来说明 p 是一个指针类型的变量,和变量类型是一个整体。
*p 中得 * 用来访问 p 所指向的变量a
3. 使用注意
在指针指向变量之前,不要对其所指的内容赋值。因为此时指针指向的地址不确定。如下是错误的:
intint *p; *p = 10;
五、指针与数组
1. 基本使用
数组名就是数组的地址,也是数组首元素的地址,既然是地址,也就可以赋值给指针变量。
int values[5] = {10, 9, 8, 67, 56}; intint *p = values; intint *p2 = &values[0]; printf("%p\n", p); printf("%p\n", p2); int values[5] = {10, 9, 8, 67, 56}; int *p = values; int *p2 = &values[0]; printf("%p\n", p); printf("%p\n", p2);
输出:
0x7fff549f2c600x7fff549f2c60
2、利用指针来访问数组元素
1> int values[5] = {10, 9, 8, 67, 56}; intint *p = values; // 数组方式 for (int i = 0; i < sizeof(values) / sizeof(int); i++) { printf("values[%d] = %d\t", i, values[i]); } printf("\n"); // 数组访问方式1 for (int i = 0; i < sizeof(values) / sizeof(int); i++) { printf("values[%d] = %d\t", i, p[i]); } printf("\n"); // 数组访问方式2 for (int i = 0; i < sizeof(values) / sizeof(int); i++) { printf("values[%d] = %d\t", i, *(p + i)); } int values[5] = {10, 9, 8, 67, 56}; int *p = values; // 数组方式 for (int i = 0; i < sizeof(values) / sizeof(int); i++) { printf("values[%d] = %d\t", i, values[i]); } printf("\n"); // 数组访问方式1 for (int i = 0; i < sizeof(values) / sizeof(int); i++) { printf("values[%d] = %d\t", i, p[i]); } printf("\n"); // 数组访问方式2 for (int i = 0; i < sizeof(values) / sizeof(int); i++) { printf("values[%d] = %d\t", i, *(p + i)); }
输出:
values[0] = 10values[1] = 9values[2] = 8values[3] = 67values[4] = 56values[0] = 10values[1] = 9values[2] = 8values[3] = 67values[4] = 56values[0] = 10values[1] = 9values[2] = 8values[3] = 67values[4] = 56
注意:
*(p + 1);表示把指针指向的地址移到下一个该变量类型的地址
同理,*(p + i);表示在p指向的地址的基础上,把指针指向的地址移到第 i 个该变量类型的地址
3. 传递
数组作为参数传递给函数的本质是把数组的地址传递给函数
void test(int v[]) { printf("大小:%lu\n", sizeof(v)); printf("地址:%p\n", v); } int main() { int values[5] = {10, 9, 8, 67, 56}; printf("大小:%lu\n", sizeof(values)); printf("地址:%p\n", values); test(values); return 0; } void test(int v[]){ printf("大小:%lu\n", sizeof(v)); printf("地址:%p\n", v);} int main(){ int values[5] = {10, 9, 8, 67, 56}; printf("大小:%lu\n", sizeof(values)); printf("地址:%p\n", values); test(values); return 0;}
输出:
大小:20地址:0x7fff55dc6c60大小:8地址:0x7fff55dc6c60
六、指针与字符串
字符串的本质是字符数组,所以字符串的名字也就是第一个字符的地址,也是字符串的地址。
1. 定义
之前定义字符串的方式是:
char name[] = "itcast"; char name[] = "itcast";
有了指针后,可以:
charchar *name = "itcast"; char *name = "itcast";
2. 区别
1> 字符数组方式
特点:字符串里面的字符是可以修改的
使用场合:字符串的内容需要经常修改
2> 指针方式
特点:字符串其实是一个常量字符串,里面的字符是不能修改
使用场合:字符串的内容不需要修改,而且这个字符串经常使用
七、清空指针
假设p是任意的指针。清空指针的值方式如下:
p = 0; p = NULL;
八、为什么int类型的指针只能指向int类型的变量
1. 例子
先看下面的程序:
int i = 2; char c = 1; // int类型的指针指向char类型的变量 intint *p = &c; printf("%d", *p); int i = 2; char c = 1; // int类型的指针指向char类型的变量 int *p = &c; printf("%d", *p);
输出结果:
513
2. 内存分析
仿照MJ老师画了一张图,
由于p是int类型的指针,指向的地址是 ffc1,于是就从 ffc1 取出四个字节的内容来:0000 0000 0000 0000 0000 0010 0000 0001,换算成十进制就是513,这就是int类型的指针为什么不能指向char类型的变量的原因。
总结:同种类型的指针只能指向同种类型的变量
九、函数和指针
1. 返回指针的函数
定义格式:
数据类型 *函数名(参数列表){// ...}
如:
charchar *pChar() { return "hello"; }
2、指向函数的指针
定义格式:
数据类型 (*pointName)(参数列表);
如:
void test() { printf("调用了test函数\n"); } int sum(int a, int b) { return a + b; } int main() { int (*p)(int, int); // 定义 p = sum; // 初始化 int c = p(10, 11); // 调用函数,相当于sum(10, 11); printf("c is %d\n", c); void (*p2)() = test; // 定义的同时初始化 p2(); // 调用函数 return 0; }
- 黑马程序员——C语言学习之数组——字符串——指针
- 黑马程序员——C语言之字符串指针
- 黑马程序员——C语言之指针数组和数组指针的区别
- 黑马程序员之IOS学习总结——04 C语言中数组与字符串
- 黑马程序员——C复杂数据类型--数组、字符串、指针
- 黑马程序员——C语言——复杂数据类型(数组、字符串、指针)
- 黑马程序员——C语言------指针和一维数组、字符串、函数
- 黑马程序员——C语言—数组、指针
- 黑马程序员——C语言基础---数组、指针
- 黑马程序员——ios基础---C语言:字符串、指针
- 黑马程序员—C语言指针与数组
- 黑马程序员——C语言基础学习(四)---数组和指针的总结学习
- 黑马程序员—C语言—数组 && 字符串
- 黑马程序员——C语言基础--数组和字符串
- 黑马程序员—C语言笔记—数组和字符串
- 黑马程序员——c语言基础:数组和字符串
- 黑马程序员—C语言_数组、字符串
- 黑马程序员—IOS基础之C语言—数组与指针
- Hadoop源码分析:HDFS数据读写流量控制(DataTransferThrottler类)
- OJ 32之简单背包问题
- LA 4513 Stammering Aliens
- 如何自定义服务脚本以及如何制作标准rpm服务脚本
- iPhone静态库学习笔记
- 黑马程序员——C语言学习之数组——字符串——指针
- Linkedin Camus的使用
- 关于Java中数据库编程的整理
- hadoop2.2.0安装
- ssl https双向验证的配置与证书库的生成
- OJ 33之个数的最大值
- [shell]避免定时任务脚本的常见问题
- OC的点语法及变量作用域小析
- OJ 35之成绩的等级