【C语言笔记2】指针、数组

指针与数组

千万不要解引用未初始化的指针

指针常量

在这里插入图片描述
C99标准允许这样声明,创建了一种新型数组,称为变长数组(variable-length array)或简称** VLA**(C11放弃了这一创新的举措把 VLA设定为可选,而不是语言必备的特性)。

C99 引入变长数组主要是为了让C成为更好的数值计算语言.

VLA有一些限制,例如,声明 VLA 时不能进行初始化。

int a[10];
a和和&a[0]是等价的

行指针与高维数组

review

一般的定义:

int (*p)[8]; //行指针
p=a;
int *p[8]; //指针数组
int a[10][10];
a[5][6]=7;
int (*p) pa=a;
if(*(*(p+5)+6)==7) printf("OK!");
// *(p+1),*p都是列指针,行指针寻址即为一个列指针
// 反过来,&(p2)把一个列指针转化为行指针

本质上是&a[0] and a所代表的不是同一个东西,但是他们的值相同。a[0]实际上等于&a[0][0]内含1个int,而 a 等于 &a[0]含有两个int

a是地址的地址,必须解引用两次才能获得原始值。

指针与函数

返回值为指针的函数

int *function() 返回一个地址

编写一个处理基本类型

(如,int)的函数时,要选择是传递int类型的值还是传递指向int 的指针。通常都是直接传递数值,只有程序需要在函数中改变该数值时,才会传递指针。

对于数组而言,传递指针是更节约内存的选择.传递地址可能造成的问题是直接操作原始数据(而非处理值那样,函数会先copy一份原始数据的副本),而我们有时候希望在函数内部做一些对原始数据的操作.

问题:有时候不需要对原始数据进行修改. 如上运用const解决这一问题.

int sum(const int ar[],int n){
  int i;
  int total=0;
  for(i=0;i<n;i++)
    total+=ar[i];
  return total;
 }
 //此处若是ar[i]++会报错

调用时可使用指针变量pa或数组常量a

def时形参可以使用数组int a[20]和指针int *m
在这里插入图片描述

函数指针

定义函数指针的一般形式如下:
*类型说明符 (指针变量名)(参数列表)

函数指针在调用时要采用如下的形式:
(*指针变量名)(实参列表)

int add(int a,int b);
int (*p) (int,int);
p=add;
int j;
j=(*p)(a,b);

怎么实现可变数组?

array.h
#ifndef _ARRAY_H_
#define _ARRAY_H_
typedef struct
{
    int *array;
    int size;
} Array;

Array array_create(int init_size);
void array_free(Array *a);
int array_size(const Array *a);
int *array_at(Array *a, int index);
void array_inflate(Array *a, int more_size);

#endif

array.c
#include "array.h"
#include <stdlib.h>
const BLOCK_SIZE = 20;
// typedef struct
// {
//     int *array;
//     int size;
// }Array;

Array array_create(int init_size)
{
    Array a;
    a.size = init_size;
    a.array = (int *)malloc(sizeof(int) * init_size);
    return a;
} //创建数组

void array_free(Array *a)
{
    free(a->array);
    a->array = NULL;
    a->size = 0;
} //回收内存

int array_size(const Array *a)
{
    return a->size;
} //返回数组大小 //why do this?-->封装

int *array_at(Array *a, int index)
{
    if (index >= a->size)
    {
        array_inflate(a, (index / BLOCK_SIZE + 1) * BLOCK_SIZE - a->size);
    }
    return &(a->array[index]);
} // a[index]

void array_inflate(Array *a, int more_size)
{
    int *p = (int *)malloc(sizeof(int) * (a->size + more_size));
    // for (int i = 0; i < a->size; i++)
    // {
    //     *(p+i)=*((a->array)+i);
    // }
    memcpy((void *)p, (void *)a->array, a->size * sizeof(int));
    // The operation of library functions must be more efficient than our own loops
    free(a->array);
    a->array = p;
    a->size += more_size;
} // key,bigger the array
  // create one space new to copy the old's, then delete the old and modify the new

int main(int argc, char const *argv[])
{
    //引例
    int number;
    int cnt = 0;
    Array a = array_create(100);    // create one array with 100 index
    printf("%d\n", array_size(&a)); // print the size of a with the function in the pointer
    *array_at(&a, 0) = 10;          // a[0]=10
    while (1)
    {
        scanf("%d", &number);
        // scanf("%d",array_at(&a,cnt++));
        if (number != -1)
            *array_at(&a, cnt++) = number;
    }

    array_free(&a); // free the space
    return 0;
}
// Q:内存运用效率低,永远小于1/2.由此,我们一般使用链表去做相关的处理



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
C语言是一种广泛应用于软件开发的编程语言,具有简洁、高效、灵活等特点。为了更好地学习和掌握C语言,整理一份完整的笔记是非常有必要的。 首先,C语言的基础知识是理解和掌握该语言的关键。笔记中应包含C语言的基本语法,如变量的声明和定义、数据类型、运算符、控制语句等,这些是编写C程序的基础。 其次,C语言的函数也是非常重要的一部分。函数是C语言中的一种模块化的编程方式,可以提高代码的重用性和可维护性。在笔记中应包含函数的定义和调用、参数传递、函数返回值等内容,以及常用的C库函数的使用。 此外,C语言数组指针也是需要重点关注的内容。数组是一种存储多个相同类型数据的方式,而指针则是C语言中与内存地址相关的操作。在笔记中应包含数组的定义和初始化、多维数组的使用、指针的声明和运算等内容。 还有,C语言中的内存管理是需要特别注意的。动态内存分配是C语言的一个重要特性,可以根据需要在运行时分配和释放内存。笔记中应包括动态内存分配的函数,如malloc、free等,以及内存泄漏和内存溢出的问题的解决方法。 最后,C语言的文件操作也是需要掌握的一部分。文件操作是C语言中与磁盘文件进行读写的关键部分,可以实现数据的长久保存和共享。在笔记中应涵盖文件的打开和关闭、读取和写入、文件指针的操作等内容。 综上所述,C语言笔记的完整版应该包含C语言的基础知识、函数、数组指针、内存管理以及文件操作等内容。通过阅读和整理笔记,可以更好地理解和应用C语言,提高程序编写的效率和质量。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值