数组

数组是一串连续的内存,用于存储数据类型相同的元素。

数组的创建与访问。

int cod[10];

这就是数组的声明,cod是能够存储10个int的数组。

cod[0]=10;

我们可以使用[]来访问cod,每一个元素都有一个标志,称为数组下标。

  • 数组的下标从0开始。

我们可以编写代码,向cod中填入1~10的整数,随后输出。

#include <stdio.h>
  int main(){
  int cod[10];
  for(int i=0;i<10;i++){
  cod[i]=i;
  }
  for(int j=0;j<10;j++){
  printf("%d ",cod[j]);
  }
  return 0;
  }

在这里插入图片描述

我们也可以在声明时初始化数组。

int cod[10]={0,1,2,3,4,0,0,0};
int cod[]={0,1,2,3,4,0,0,0};

不去写数组长度也是可以的,在编译的时候编译器会自动判断数组长度。

  • C99标准中,指定可以使用变量作为数组的长度。但不能在程序运行过程中修改数组的长度。

多维数组

在刚才的示例中我们声明的仅为1维数组,那样的数据是类似于线性存储的。

int cod[2][2]={
{1,2},
{3,4}
};

如上,这是一个简单的二维数组。

  • 如果我们要访问数据3,则需要cod[1][0]来访问。
    二维数组可以用来制作一些画面。
#include <stdio.h>
  void show(){
  char c[4][32]={
  {"-------------------"},
  {"------1. Exit------"},
  {"-2. 你想要的描述。-"},
  {"-------------------"}
  };
  for(int i=0;i<4;i++){
  printf("%s\n",c[i]);
  }
  }
  int main(){
  show();
  return 0;
  }

在这里插入图片描述

一个简单的菜单,抽象菜单

指针

指针是一种特殊的存储变量,它存储的是变量在运行时的地址。关于地址我们之前简单的在输入篇章讨论过。
指针本身并无多么复杂的使用,主要是与其他语法的结合运用。

指针的创建与简单应用

int cod=0;
int* p=&cod;

这样指针p就指向了cod了。

  • 指针指向的变量必须与自身的数据类型相同。

我们可以输出来看。

printf("&cod=%p\np=%p",&cod,p);

在这里插入图片描述

这是一串16进制的地址,你不必看懂它是什么,但是我们可以看得出来指针pcod的地址是相同的数。

  • 这里是指针p的值,并非指针p的地址,指针p的地址与之并不相同,可以使用&p来输出指针p的地址。

我们可以使用指针读取和更改变量的内容,同时也可以更改指针的指向。

#include <stdio.h>
  int main(){
  int cod=0;
  int* p=&cod;
  printf("1 *p=%d\n",*p);
  *p=10;
  printf("2 *p=%d\n",*p);
  int cod1=9;
  p=&cod1;
  printf("3 *p=%d\n",*p);
  return 0;
  }

在这里插入图片描述

我们分别验证了读取,修改,和转移指向。

多重指针

大概就是:指针的指针,或者指针的指针的指针等等的形式。

int cod=0;
int *p=&cod; //cod的指针
int **p2=&p; //指针p的指针
int ***p3=&p2;  //指针p2的指针,也是指针p的指针的指针

空指针

int *p=NULL;

这样的指针就是空指针。

  • NULL是定义在标准库中的宏。

空指针就是什么也不指的指针。

野指针

就是指针指向了错误的内存地址。

int a[5]={0,1,2,3,4};
int *p=a;
printf("%d",*(++p));

这里我们用指针指向了数组的第一位,在输出的时候令指针向后偏移一位。

  • 如果我们让指针偏移出数组的长度,就会造成程序访问了不该访问的内存地址。
int a[5]={0,1,2,3,4};
int *p=a;
printf("%d",*(p+=10));

我们直接让指针向后偏移10位。
在这里插入图片描述

程序输出了一个莫名其秒的值。

  • 虽然让指针偏移出数组长度在语法中是合法的,但是如果不管制,令指针访问到了危险的内存中,很有可能造成如:系统崩溃、程序崩溃等等的危险行为。
  • 请谨记,在对内存进行操作时一定要确保在程序的安全范围内。

结构体(Struct)

结构体定义与声明

struct cod {   // 显式标签定义
int a;
};

或匿名定义:

struct {            // 匿名结构体
int x;
}var;

成员访问与初始化

#include <stdio.h>
  struct Cod{
  int a;
  };
  int main(){
  struct Cod cod;
  printf("cod.a=%d\n",cod.a=10);
  return 0;
  }

在这里插入图片描述

我们可以使用如上代码来访问,和初始化结构体变量。
也可以使用其他初始化的方式。

struct Student s = {101, "Alice", 90.5}; // 顺序初始化
struct Student s2 = {.name = "Bob"};      // C99指定初始化器  
  • 结构体嵌套

struct Date {
int year, month, day;
};
struct Person {
char name[20];
struct Date birthday;  // 嵌套定义
};
  • 这样的嵌套结构体也是被允许的。

联合(Union)

联合可以理解为所有成员共享同一内存空间的结构体。

union Data {
int i;
float f;
char str[20];
};

内存空间的大小由最大的成员决定。

  • 任意时刻仅一个成员有效。
    • 由于共享同一片内存所以在使用其他数据时,之前的数据会被覆盖。