C语言数组与指针的例子,你真的都会了吗

942 阅读3分钟

概览

  • sizeof 计算数组元素个数,指定初始化器
  • 函数中传递数组的通用方法与两个指针方法、越界指针有效、只读形参
  • 双重间接
  • 数组指针与指针数组
  • 函数与多维数组
  • 变长数组

示例

  1. sizeof 计算数组元素个数,指定初始化器
#include <stdio.h>

int main(void){
    int a[] = {1,2,3,4,5,6,7};
    printf("%zd",sizeof a / sizeof(int));
}

//  结果
// 7
  1. 函数中传递数组的通用方法与两个指针方法、越界指针有效、只读形参
#include <stdio.h>

void myPrint(int *, int);
int main(void){
    // 通用方法:传递数组指针与元素个数
    int a[] = {1,2,3,4,5,6,7};
    myPrint(a,7);
}

void myPrint(int * a, int n){
    for(int i=0; i<n; i++){
        printf("%d ",*(a+i));
    }
}

// 结果
// 1 2 3 4 5 6 7 
#include <stdio.h>

void myPrint(int *, int *);
int main(void){
    // 指针方法:传递数组首末元素地址
    int a[] = {1,2,3,4,5,6,7};
    myPrint(a,a+7); // 数组后面第一个位置的指针仍然有效
}

void myPrint(int * start, int * end){
    for(; start < end; start++){  // 可以使用while循环代替
        printf("%d ",*start);
    }
}

// 结果
// 1 2 3 4 5 6 7 
#include <stdio.h>

// 只读形参
void myPrint(const int *, int);
int main(void){
    int a[] = {1,2,3,4,5,6,7};
    // 可以将非const赋给const
    myPrint(a,7);
}

void myPrint(const int * a, int n){
    a[0] = 2;
}

// 结果
// test.c:14:10: error: read-only variable is not assignable
//     a[0] = 2;
//     ~~~~ ^
// 1 error generated.
  1. 双重间接
#include <stdio.h>

int main(void){
    // 双重间接:指的是二维数组与指针表示法
    // **a == a[0][0]
    int a[][3] = {{1,2,3},{4,5,6},{7},[4]={3,2,9}};  // 多维数组只允许第一个维度为空,表示是一个数组;指定初始化器的方式
    printf("%d\n", **a); // 数组名是数组首元素的地址
    printf("%d\n", *a[0]);
    printf("%d\n", a[0][0]);
    printf("%d\n", *(*(a+4)+2));
}

// 结果
// 1
// 1
// 1
// 9
  1. 数组指针与指针数组、复合字面量

运算符优先级

#include <stdio.h>

int main(void){
    // 数组指针:[]优先级比*的优先级要高,为什么要有确定的维度?必须告诉指针指向对象的类型,例如3个int型的对象
    int (*a)[3] = (int [][3]){{1,2,3},{4,5,6},{7},[4]={3,2,9}};  // 复合字面量在创建的时候使用
    int b[][3] = {{1,2,3},{4,5,6},{7},[4]={3,2,9}};  // [] 表明b是一个指针
    printf("%d\n",a[4][2]);
    printf("%d\n",b[4][2]);
    printf("%zd\n", sizeof b/sizeof(int));
    printf("%zd\n", sizeof *a/sizeof(int));
    // 指针数组
    int *c[3]; // 内含3个元素,每个元素都是指向int类型的指针
    printf("%p\n",c[1]);
    printf("%d\n",*c[1]);
}

// 结果
// 9
// 9
// 15
// 3
// 0x10d268000
// -17958193
  1. 函数与多维数组
#include <stdio.h>

void myPrint(int (*)[3],int);
//void myPrint(int [][3],int);
int main(void){
    int a[][3] = {{1,2,3},[2]={4,5,6}};
    myPrint(a,3);
}

void myPrint(int (*a)[3], int n){
    for(int i = 0; i<n; i++){
        for(int j = 0; j<3;  j++){
            printf("%d ",a[i][j]);
        }
        printf("\n");
    }
}
// 结果
// 1 2 3 
// 0 0 0 
// 4 5 6 
  1. 变长数组
#include <stdio.h>

void myPrint(int, int, int [*][*]);  // 必须用*代替省略的维度
//void myPrint(int [][3],int);
int main(void){
    // 变长数组,变不是说可以修改已创建的数组大小,而是可以在创建时用变量指定维度
    int row = 3;
    int col = 3;
    int a[row][col];  // VLA 不能在声明时初始化,且支持的编译器不多
    for(int i=0; i<row; i++){
        for(int j=0; j<col; j++){
            a[i][j] = i+j;
        }
    }
    myPrint(row,col,a);
}

void myPrint(int row, int col, int a[row][col]){
    for(int i = 0; i<row; i++){
        for(int j = 0; j<col;  j++){
            printf("%d ",a[i][j]);
        }
        printf("\n");
    }
}

// 结果
// 0 1 2 
// 1 2 3 
// 2 3 4