初学c课程笔记整理7-->>二维数组、字符串、指针

是什么?有什么用?用在什么地方?(理解)

养成良好的编程习惯;

培养编程思想;

写代码之前应该先分析需求,分析完需求再开始写代码;(写注释)

 

1.二维数组

1.1 二维数组的基本概念:

所谓多维数组就是一个一维数组的每个元素又被声明为一 维数组,从而构成二维数组. 可以说二维数组是特殊的一维数组。

示例

int a[2][3]

可以看作由一维数组a[0]和一维数组a[1]组成,这两个一维数组都包含了3个int类型的元素

1.2 二维数组的定义:

数组中的每一个元素又是一个数组, 那么这个数组就称之为二维数组

元素类型 数组名称[一维数组的个数][每个一维数组的元素个数];
     元素类型 数组名称[行数][列数];
    
     元素类型: 说明二维数组中每个一维数组存储什么类型的数据
     一维数组的个数: 说明二维数组有多少个元素
     每个一维数组的元素个数 :  说明二维数组中每一个一维数组的元素个数
     */
    int scoress[3][5] =
    {

{1, 3, 5, 7, 9}, // 0

{2, 4, 6, 8, 10},// 1
        {1, 2, 3, 4 , 5} // 2

};  // 每一个一维数组都是二维数组的一个元素

如何遍历二维数组

思路: 1.取出二维数组的每一个元素(取出二维数组中的一维数组)

2.遍历一维数组

1.3 二维数组的存储

存储方式:

1)计算机会给二维数组分配一块连续的存储空间

2)数组名代表数组的首地址,从首地址位置,依次存入第1行、第2行、.....

3)每一行存储方式,从行首地址还是,依次存储行的第1个元素、第2个元素、第3个元素......

4)每个元素占用相同的字节数(取决于数组类型)

5)并且数组中元素之间的地址是连续

二维数组的存放顺序是按行存放的,先存放第一行的元素,再存放第2行的元素

1.4 二维数组初始化及注意点:

1.3.1二维数组的多种初始化方式

1.定义的同时初始化

int names[2][3] =
    {
        {‘l‘, ‘n‘, ‘j‘},
        {‘x‘, ‘m‘, ‘g‘}
    };

2.先定义再初始化

int names2[2][3];
    names2[0][0] = ‘l‘;
    names2[0][1] = ‘n‘;
    names2[0][2] = ‘j‘;
   
    names2[1][0] = ‘x‘;
    names2[1][1] = ‘m‘;
    names2[1][2] = ‘g‘;

3.完全初始化

int names3[2][3] =
    {
        {‘l‘, ‘n‘, ‘j‘},
        {‘x‘, ‘m‘, ‘g‘}
    };

4.不完全初始化

int names4[2][3] =
    {
        {‘l‘, ‘n‘},
    };

5.省略元素个数的两种写法

明确的告诉二维数组, 我们有2个一维数组

char names5[2][3] =
    {
        ‘l‘, ‘n‘, ‘j‘,
        ‘x‘, ‘m‘, ‘g‘
    };
    char names15[2][3] =
    {
        ‘l‘, ‘n‘, ‘j‘,
        ‘x‘, ‘m‘
    };

没有告诉二维数组我们有几个一维数组

如果在"定义的同时"进行初始化, 那么一位数组的个数可以省略

系统会自动根据每一个一维数组能够存放多少个元素, 自动根据初始化的值推断出二维数组中一共有多少个元素(多少个一维数组)
    char names6[][3] =
    {
        ‘l‘, ‘n‘, ‘j‘,
        ‘x‘, ‘m‘, ‘g‘,
        ‘n‘, ‘b‘
    };

6.错误写法

?? 注意点: 每个一维数组的元素个数不能省略

int names7[2][] =
    {
        {‘l‘, ‘n‘, ‘j‘},
        {‘x‘, ‘m‘, ‘g‘}
    };

搞不清楚应该分配多大的存储空间, 以及搞不清楚应该把哪些数据赋值给第一个数组, 以及哪些数据赋值给第二个数组

int names7[2][] =
    {
        ‘l‘, ‘n‘, ‘j‘,

‘x‘, ‘m‘, ‘g‘

};//错误写法

1.5 二维数组与函数

1.二维数组的元素作为函数参数

二维数组的元素就相当于变量,作为函数参数与变量相同

2.二维数组中的一维数组作为函数

二维数组的一维数组实际上就是一个一维数组,作为函数参数与一维数组相同

3.二维数组作为函数参数

**二维数组作为函数参数是地址传递**

二维数组作为函数形参,参数中一维数组的元素个数不可以省略

void test(char cs[2][]) // 错误写法

{

printf("我被执行了\n");

}

void test(char cs[2][3]) // 正确写法

{

printf("我被执行了\n");

}

void test(char cs[][3]) // 正确写法

{

printf("我被执行了\n");

二维数组作为函数参数,在被调函数中不能获得其有多少行,需要通过参数传入。

```

void test(char cs[2][3])

{

int row = sizeof(cs);

printf("row = %zu\n", row);

}

输出结果:

row = 8

```

- 二维数组作为函数参数,在被调函数中可以计算出二维数组有多少列

```

void test(char cs[2][3])

{

size_t col = sizeof(cs[0]);

printf("col = %zd\n", col);

}

输出结果:

col = 3

```

以后只要看到函数的参数是一个数组, 那么就是地址传递

在函数中修改形参的值会影响到参数

2.字符串

 

1.字符串概念

字符串是位于双引号中的字符序列

在内存中以“\0”结束,所占字节比实际多一个

2.字符串的初始化

- 在C语言中没有专门的字符串变量,通常用一个字符数组来存放一个字符串。前面介绍字符串常量时,已说明字符串总是以‘\0’作为串的结束符。因此当把一个字符串存入一个数组时,也把结束符‘\0’存入数组,并以此作为该字符串是否结束的标志。有了‘\0’标志后,就不必再用字符数组 的长度来判断字符串的长度了。

- 初始化

```

char name[9] = "lnj"; //在内存中以“\0”结束, \0ASCII码值是0

char name1[9] = {‘l‘,‘n‘,‘j‘,‘\0‘};

char name2[9] = {‘l‘,‘n‘,‘j‘,0};

char name3[9] = {‘l‘,‘n‘,‘j‘};//静态数组如果没有赋值默认就是0,0就相当于\0

```

- 错误的初始化方式

```

//不正确地写法,结尾没有\0 ,只是普通的字符数组

char name4[] = {‘l‘,‘n‘,‘j‘};

//    \0的作用:字符串结束的标志

char name[] = "c\0ool";

printf("name = %s\n",name);

输出结果: c

3.字符串的输出、输入

使用的格式字符串为“%s”,表示输入、输出的是一个字符串

scant(“%s”,ch);//输入

printf(“%s”,ch);//输出

%s的原理, 从传入的"地址"开始逐个取出, 直到遇到"\0"位置

4.字符串的注意点

字符串注意点, 字符串的初始化

char str1[] = "lnj";

char str2[] = {‘l‘, ‘n‘, ‘j‘, ‘\0‘};

// 部分初始化, 部分初始化中, 没有被初始化的元素默认是0
    // \0对应的ASCII 0
    char str3[10] =  {‘l‘, ‘n‘, ‘j‘}; // l n j 0000000
   
    char str4[3] = {‘l‘, ‘n‘, ‘j‘}; // 该方式不是字符串, 而是字符数组, 因为没有\0
    char str5[] = {‘l‘, ‘n‘, ‘j‘}; // 错误写法

需要明白的一点就是字符串以\0结尾, 没有\0就不是字符串

只要是用双引号括起来的都是字符串

字符串的本质就是数组

3.指针(重点)只能保存地址

3.1内存地址

地址与内存单元中的数据是两个完全不同的概念

地址如同房间编号

内存单元如同房间

内存单元中存放着数据

变量地址:

系统分配给"变量"的"内存单元"的起始地址

3.2 什么是指针

在计算机中所有数据都存储在内存单元中,而每个内存单元都有一个对应的地址, 只要通过这个地址就能找到对应单元中存储的数据. 由于通过地址能找到所需的变量单元,可以说,地址指向该变量单元。因此,将地址形象化的称为“指针”

内存单元的指针(地址)和内存单元的内容是两个不同的概念。

3.3 什么是指针变量

在C语言中,允许用一个变量来存放指针,这种变量称为指针变量。因此,一个指针变量的值就是

某个内存单元的地址或称为某内存单元的指针。

+ 严格意义上说,指针是一个地址,是一个常量

+ 针变量是存放一个地址,是一个变量。

http://7xj0kx.com1.z0.glb.clouddn.com/指针变量.png

示例

http://7xj0kx.com1.z0.glb.clouddn.com/Snip20150518_8.png

3.4定义指针变量的格式

指针变量的定义包括两个内容:

指针类型说明,即定义变量为一个指针变量;

指针变量名;

> 其中,*表示这是一个指针变量,变量名即为定义的指针变量名,类型说明符表示本指针变量所指 向的变量的数据类型

char *p; // 一个用于指向字符形变量的指针

int *q; // 一个用于指向整形变量的指针

long *t; // 一个用于指向长整形变量的指针

float *r; // 一个用于指向单精度浮点形变量的指针

double *s; // 一个用于指向双精度浮点形变量的指针

??注意

1)在定义指针时,“*”号表示定义的变量是指针变量,变量的值只能存放地址。

2)一个类型的指针只能指向同类型的变量,不能指向其他类型的变量。

3)指针也可以被声明为全局、静态局部和局部的。

3.5指针变量初始化及注意点

1.指针变量的初始化方法

指针变量初始化的方法有两种:定义的同时进行初始化和先定义后初始化

定义的同时进行初始化

int a = 5;

int *p = &a;

先定义后初始化

int a = 5;

int *p;

p=&a;

把指针初始化为NUL

int *p=NULL;

int *q=0;

不合法的初始化:

指针变量不能被赋值一个整数值(因为我们不知道这个整形常量是内存哪块地址

int *p;

p =  250; // 错误写法

int *p;

*p=&a; //错误写法

int *p;

*p = &a;//正确写法

??注意:

多个指针变量可以指向同一个地址

指针的指向是可以改变

int a = 5;

int *p = &a;

int b = 10;

p = &b; // 修改指针指

指针没有初始化里面是一个垃圾值,这时候我们这是一个野指针

+ 野指针可能会导致程序崩溃

+ 野指针访问你不该访问数据

+ 所以指针必须初始化才可以访问其所指向存储区域

访问指针所指向的存储空间

int a = 5;

int *p = &a;

printf("a = %d", *p); // 访问指针变量

4.(多)二级指针

二级指针介绍

如果一个指针变量存放的又是另一个指针变量的地址,则称这个指针变量为指向指针的指针?变量。也称为“二级指针”

char c = ‘a‘;

char *cp;

cp = &c;

char **cp2;

cp2 = &cp;

printf("c = %c", **cp2);

多级指针介绍

int ***m1; 取值***m1

int *****m2 取值*****m2

时间: 2024-12-27 13:34:44

初学c课程笔记整理7-->>二维数组、字符串、指针的相关文章

C语言 二维数组与指针笔记

今天分析了C语言二维数组和指针的基本理解,感觉有点懵...代码记录一下,如果有大神临幸发现哪里有误,欢迎指正~~~ #include <stdio.h> #include <stdlib.h> #include <string.h> //void func(int p[][]) //这样写等同于void func(int **p) p++移动了四个字节,(*p)++移动了四个字节,不符合二维数组规律 //{ //} //列优先输出的函数(即竖着输出) void func

程序猿之--C语言细节13(二维数组和指针,&amp;*a[i][0]的理解,数组1[e]和e[1]很可能你没见过)

主要内容:二维数组和指针,&*a[i][0]的理解.数组1[e]和e[1] #include <stdio.h> #define NUM_ROWS 10 #define NUM_COLS 10 int main(int argc, char **argv) {     int a[NUM_ROWS][NUM_COLS], *p, i = 0; // a理解为指向整数指针的指针 即int **     int c, d=2,*test, e[2] = {4,5},f[2][2] = {{

直观理解C语言中指向一位数组与二维数组的指针

一维数组和指针: 对于一位数组和指针是很好理解的: 一维数组名: 对于这样的一维数组:int a[5];  a作为数组名就是我们数组的首地址, a是一个地址常量 . 首先说说常量和变量的关系, 对于变量来说, 用箱子去比喻再好不过了, 声明一个变量就声明一个箱子,比如我们开辟出一个苹果类型的箱子, 给这个变量赋值就是把盛放苹果的箱子中放入一个实实在在的苹果, 这就是变量的赋值.  而对于数组来说, 就是一组类型相同的箱子中,一组苹果箱子, 可以放入不同的苹果. 一维数组空间: 变量被声明后, 我

例看二维数组,指针,二维数组指针

例程: /****************************************************** * * 文件名:例程 * * 文件描述:例看二维数组,指针,二维数组指针 * * 创建人:Jesse * * 版本号: * * 修改记录: * ******************************************************/ #include <stdio.h> #define ROW 3 #define LINE 3 void main(voi

C语言--二维数组,字符串数组,多维数组

#import <Foundation/Foundation.h> int main(int argc, const char * argv[]) { // int a[2][3]={ // {1,2,3}, // {4,5,6} // }; // int a[2][3]={1,2,3,4,5,6}; // //打印单个元素 // printf("%d",a[1][1]); // //元素没赋全,默认为0 // int b[2][3]={{1,2,3},{4}}; // /

程序员之--C语言细节13(二维数组和指针,&amp;amp;*a[i][0]的理解,数组1[e]和e[1]非常可能你没见过)

主要内容:二维数组和指针.&*a[i][0]的理解.数组1[e]和e[1] #include <stdio.h> #define NUM_ROWS 10 #define NUM_COLS 10 int main(int argc, char **argv) {     int a[NUM_ROWS][NUM_COLS], *p, i = 0; // a理解为指向整数指针的指针 即int **     int c, d=2,*test, e[2] = {4,5},f[2][2] = {{

***php解析JSON二维数组字符串

客户端的请求体中的数据:[{"msg_id": 1, "msg_status": "HAS_READ" }, { "msg_id": 2, "msg_status": "HAS_READ" }] 是一个二维数组字符串 $json_data = json_decode($GLOBALS['HTTP_RAW_POST_DATA'], true);其实用这一句即可实现JSON二维数组字符串转P

二维数组及指针

首先,看一维数组. []符号是下标运算符,a[i]就是*(a+i) 那么a[i][j] 就是*(a[i]+j)=*(*(a+i)+j) 本人对二级和多级指针的理解:1.抽象上说二级指针的内容是地址的地址.变量A好像跟你捉迷藏似的,你要想找到A,你先得去一个地方把A的地址给找出来,然后再根据这个地址找到A.就类似武侠电影里的宝藏,你要先去一个人的背上发现藏宝图,然后再根据藏宝图里画的地址找到宝藏,在这里,这个人的背就是一个最外层的地址,藏宝图就是内层的地址.2.对于二级指针和多级指针,定义时,我们

二维数组和指针

二维数组和指针⑴ 用指针表示二维数组元素.要用指针处理二维数组,首先要解决从存储的角度对二维数组的认识问题.我们知道,一个二维数组在计算机中存储时,是按照先行后列的顺序依次存储的,当把每一行看作一个整体,即视为一个大的数组元素时,这个存储的二维数组也就变成了一个一维数组了.而每个大数组元素对应二维数组的一行,我们就称之为行数组元素,显然每个行数组元素都是一个一维数组 下面我们讨论指针和二维数组元素的对应关系,清楚了二者之间的关系,就能用指针处理二维数组了.设p是指向数组a的指针变量,若有:p=a

C二维数组用指针地址遍历

#include <stdio.h> #include <stdlib.h> int main(){ int a = 100; void *p = &a; printf("a:%d address:%p\n",*(int*)p, &a); //unsigned int *pt = (unsigned int*)0xbfa70ee8; int *pt = (int*)malloc(sizeof(int)); *pt = 200; printf(&q