Linux_C编之(4)数组

数组

变量在内存存放是有地址的,数组在内存存放也同样具有地址。对于数组来说,数组名就是数组在内存中存放的数组首元素的地址。

(一)数组认知

C语言对属组的处理是非常有效的
原因有以下三点:
(1)除了少数编译器处于谨慎会做出一些繁琐的规定外,C语言的数组下标是在一个很低的层次上处理的。但是这个优点也有一个反作用,即在程序运行时你无法知道 一个数组到底有多大或者一个数组的下标是否有效。
对一个越界的下标可能导致以下几种后果:

  • 程序仍然能正常运行
  • 程序会异常终止或者崩溃
  • 程序能继续运行,但是无法获得正确的结果
  • 其他情况

(2)数组和指针能非常和谐地在一起工作,当数组出现在一个表达式中,它和指向数组中第一个元素的指针是等价的,因此数组和指针几乎可以互换使用,此外,使用指针要比使用数组下标快两倍。
将数组作为参数传递给函数和将指向数组中第一个元素的指针传递给函数是完全等价的,将数组作为参数传递给函数时可以采用值传递和地址传递两种方式,前者需要完整地复制初始数组,但比较安全;后者的速度要快得多。
数组和指针之间的这种联系会引起一些混乱,例如,一下两种定义是完全相同的:

void func(char a[max])
 {}
void func(char *a)
{
	;
}

(3)

char a[MAX];

系统将分配MAX个字符的内存空间

cahr *a;

系统将分配一个字符指针所需要的的内存空间,可能只能容纳2个或者4个字符

定义函数

char a[MAX];

声明却是这样声明

extern char *a;

就会报错

(二)使用数组之常见问题

(1)、数组的下标总是从0开始吗
是的,对数组a[MAX]来说,它的第一个和最后一个元素分别是a[0]和a[MAX-1]。注意:a[MAX]是一个有效的地址,但是地址中的值并不是数组a中的一个元素。
数组下标从0开始的原因: 指针和数组几乎是相同的,因此你可以定义一个指针,使它可以像一个数组一样引用另一个数组中的所有元素,但是引用前者的下标是从1开始的。

int a0[MAX];
int *a1=a0-1;

现在a0[0]和a1[1]是相同的,而a0[MAX-1]和a1[MAX]也是相同的。然而在实际编程中不应该这么做,因为:

  1. 这种方法可能行不通,这种行为是ANSI/ISO C 标准中没有定义的,而&a0[-1]完全可能是一个无效的地址。
  2. 违背了C语言的常规风格,别人很难读懂你的程序,可读性太差

(2)、可以使用数组后面第一个元素的地址吗
在这里插入图片描述
输出为1,说明确实可以用后面的地址

(3)为什么要小心对待位于数组后面的那些元素的地址呢
程序在计算机上运行,它的取址范围是00000000-FFFFFFFF。
但是在有些计算机上,地址是由两部分组成的,第一部分是一个指向某一块内存的起始点的指针(即基地址),第二部分是相对于这块内存的起始点的地址偏移量。这种地址被称为段地址结构,通常子程序的调用就是通过在栈指针上加上一个地址偏移量来实现的。如果基地址无法改变,而偏移量也不可能是个负值,所以位于a[0]前面的就没有意义了。同样,最后的也没有意义了。

(三)总结

1.一维数组的创建和初始化
数组的创建:在创建数组时,我们必须定义数组的类型和大小,数组的大小不能为0,数组中的元素类型都是相同的。
eg:

int arr[10];//[]内必须是常量/常量表达式(3+8),不能是一个变量(x…)
1
数组的初始化:在数组创建时,我们也要必须为数组初始化。
eg:

int arr1[3] = {1, 2, 3};
int arr2[] = {1, 2, 3};//在这里,我们arr[3]里边的数字可以不用写;
int arr3[3] = {1, 2};//也是可以的,只是把最后一个数初始化为0了而已
int arr4[3] = {1, 2, 3, 4};//是不可以的,不能超过数组长度  
char arr5[3] = {'a', 98, 'c'};//因为是字符类型,所以98其实就是字符'b'
char arr6[] = "abcdef";
#include<stdio.h>

int main()
{
    char arr1[] = { 'a', 'b', 'c' };
    char arr2[3] = "abc";
    char *p = "abc";//这里只是把a的地址放进了p里边

    return 0; 
}

2.一维数组的使用
eg:

#include<stdio.h>

int main()
{
    int arr[10] = { 0 };
    int i = 0;
    for (i = 0; i < 10; i++)//i<11是不可以的,不可以越界访问
    {
        arr[i] = i;
    }

    return 0; 
}

数组是使用下标来访问的,下标是从0开始。
数组的大小可以通过计算得到。(sz = sizeof(arr)/sizeof(arr[0]));

3.一维数组在内存中的存储
eg:

#include<stdio.h>

int main()
{
    int arr[10] = { 0 };
    int i = 0;
    for (i = 0; i < sizeof(arr)/sizeof(arr[0]); i++)
    {
        printf("&arr[%d] = %p\n", i, &arr[i]);
    }

    return 0; 
}
  1. 二维数组的创建和初始化
    eg:
#include<stdio.h>

int main()
{
    int arr[3][4] = { 1, 2, 3, 4, 5, 6 };
    //int arr[][4] = {{1, 2},{3, 4, 5},{6}};可以
    //arr[3][] = {{1, 2},{3, 4, 5},{6}};是不可以的

    return 0; 
}
  1. 二维数组的使用
    二维数组的使用也是通过下标方式
    eg:
#include<stdio.h>

int main()
{
    int arr[3][5] = { 0 };
    int i = 0;
    int j = 0;
    for (i = 0; i < 3; i++)
    {
        for (j = 0; j < 5; j++)
        {
            arr[i][j] = i * 5 + j + 1;
        }
    }

    for (i = 0; i < 3; i++)
    {
        for (j = 0; j < 5; j++)
        {
            printf("%d ", arr[i][j]);
        }
        printf("\n");
    }


    return 0; 
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值