数组

数组

1. 数组特性

# include <stdio.h>
# include <string.h>

int main(void)
{
    //数组初始化
    int a[5];
    int b[5] = {5, 6, 7, 8, 9}; 
    int c[5] = {0, 6};  
    int d[5] = {0}; 
    int e[5] = { [0 ... 2]=1, [3 ... 4]=2 };
    int f[ ] = {1, 2, 3, 4, 5};
    char ch[] = "12345";

    //单个输出各数组内容
    printf("%d\t%d\t%d\t%d\t%d\n",b[0], b[1], b[2], b[3], b[4]);
    printf("%d\t%d\t%d\t%d\t%d\n",c[0], c[1], c[2], c[3], c[4]);
    printf("%d\t%d\t%d\t%d\t%d\n",d[0], d[1], d[2], d[3], d[4]);
    printf("%d\t%d\t%d\t%d\t%d\n",e[0], e[1], e[2], e[3], e[4]);

    //获取数组大小和长度
    printf("a[] sizeof= %d\n", sizeof(a)); 
    printf("f[] len= %d\n", sizeof(f)/sizeof(*f));
    printf("ch[] len= %d\n", sizeof(ch)/sizeof(*ch));

    //循环输出数组地址及其相应内容、数组所占字节数
    int i;
    for (i=0;i<5;++i)
    {
        //scanf("%d", &a[i]);               // 输入
        printf("%p-->%d\n", &a[i], a[i]);   // 输出
    }

    //清空
    unsigned int g[3] = {0};
    memset(a, 0, sizeof a);                 // 用来对一段内存空间全部设置为某个字符
    bzero(a, sizeof a);                     // 置字节字符串前n个字节为零且包括‘\0’

    //十六进制输出的a和a[0]的地址
    printf("g\t= %#x\n&g[0]\t= %p\n", g, &g[0]);
    //scanf("%s", ch);                      //数组名为地址

    //数组越界访问
    printf("example:a[-1]=%d, a[5]=%d\n", a[-1], a[5]); 

    return 0;
}

运行结果

5   6   7   8   9
0   6   0   0   0
0   0   0   0   0
1   1   1   2   2

a[] sizeof= 20
f[] len= 5
ch[] len= 6

0xbfc74500-->8
0xbfc74504-->-1217364042
0xbfc74508-->-1217310720
0xbfc7450c-->-1217363943
0xbfc74510-->112

g   = 0xbfc744f4
&g[0]   = 0xbfc744f4

example:a[-1]=0, a[5]=5

1)数组初始化可以不赋值、全赋值、不完全赋值、赋零值;不完全赋值时余下自动清零,赋零值时等效于清空;数组可以范围赋值,缺省长度赋值。
2)元素内存连续分配,元素所占字节由数据类型决定。
3)数组大小等于数据类型*元素个数。缺省长度赋值时大小由系统按元素个数分配,字符串包含字符’\0’元素。
4)数组可定义时清空,使用函数清空。
5)数组名a是表示地址的常量,也是数组的起始位置。
6)a[i] = *(a+i),取起始地址向后偏移 i×sizeof(数据类型)字节的值。
7)数组越界不检查,例如: a[-1],a[5]。


2. 一维数组


# include <stdio.h>

int main(void)
{
    //定义初始化
    int a[3] = {0, 100, 200};

    //单个赋值
    a[0] = 100;
    a[1] = 200;
    a[2] = 300;

    //循环赋值
    int i;
    for (i=0;i<3;++i)
    {
        scanf("%d", &a[i]);             // 输入
        printf("a[%d]=%d\n", i, a[i]);  // 输出
    }

    return 0;
}

3. 二维数组

# include <stdio.h>

int main(void)
{

    int a[3][4] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12};
    int b[3][4] = { {1, 2, 3, 4}, {5, 6, 7, 8}, {9, 10, 11, 12} };
    int c[ ][4] = { {1, 2, 3, 4}, {5, 6, 7, 8}, {9, 10, 11, 12} };

    //二维数组理解:在线性连续d空间挖了两个坑,每个坑装"int [3]"(有三个小元素的元素,小元素为int型)
    int (d[2]) [3] = {   {77,   88,   99}     ,    {1,    2,    3}  };
    //                       d[0]                      d[1]
    //              d[0][0] d[0][1] d[0][2]   ,   d[1][0] d[1][1] d[0][2]


    int i, j;

    for (i=0; i<3; ++i)
    {
        for (j=0; j<4; ++j)
        {
            //scanf("%d", b[i][j]); 
            printf("%d\t", b[i][j]);
        }
        printf("\n");
    }

    return 0;
}

4. 字符数组

#include <stdio.h>
#include <string.h>

int main(int argc, char const *argv[])
{
    char s1[9]  = {'a', '\0', 'c', '\0'};
    char s3[5]  = {'a', 'a', 'a'};  //"aaa"

    s3[1] = 'B';

    //输出单个字符和所有字符
    printf("%c, %s\n", s3[1], s3);

    //字符'\0'
    if('\0'==0 && '\0'==NULL)
        printf("\'\\0\' is 0 and NULL.\n");

    //字符的整型输出
    int i;
    for(i=0; i<5; ++i)
    {
        printf("s3[%d]= %d\n", i, s3[i]);
    }

    //strlen、sizeof
    int ret;
    ret = strlen(s1);       // 返回字符数'\0'截止
    printf("strlen(s1)= %d\n", ret);
    ret = sizeof(s1);       // 返回字符数含'\0'及数组范围内后面字符
    printf("sizeof(s1)= %d\n", ret);

    //字符串操作API
    strcpy(s1, s3);
    strncpy(s1, s3, 2);     //字符串复制

    strcat(s1, s3);
    strncat(s1, s3, 2);     //字符串拼接

    puts(s1);

    return 0;
}

5. 字符串保存

#include <stdio.h>
#include <string.h>

int main(void)
{
    // 栈
    char s2[20] = {'a', 'b', [15 ...18] = 'e','\0'};    //字符串应以'\0'结束
    char str[]  = "hello";
    const char *p   = "wrold!";

    char str2[2][5] = {"my","name"};
    char * pr[2]    = {"lisi", "wangwu"};

    printf("sizeof:str2= %d, pr= %d\n", sizeof(str2), sizeof(pr));

    // 常量区
    printf("%s\n", "ABC");
    printf("%c\n", "ABC"[1]);       // 字符串类型为匿名数组
    printf("%p, %p, %p, %p, %p\n", &"ABC", &"ABC"[0], &"ABC"[1], &"ABC"[2], &"ABC"[3]);

    return 0;
}

6. 数组与指针

#include <stdio.h>

//C允许多次声明函数原型,因为以下写法完全等价,所有不会报类型声明错误
void function(int a[5]);
void function(int a[ ]);
void function(int   *a);

int main(int argc, char const *argv[])
{
    //数组中的地址类型
    int a[5] = { 1, 2, 3, 4, 5 };

    int *p1     = a;        //数组名视为数组首元素的地址,类型为元素的类型*
    int *p2     = &a[0];    //元素类型*
    int(*p3)[5] = &a;       //数组类型*

    int b[2][3] = { { 1, 2, 3 }, { 7, 8, 9 } };

    int(*p4)[3]    = b;
    int(*p5)[3]    = &b[0];
    int(*p6)[2][3] = &b;
    int *p7        = &b[0][0];

    //数组取值
    printf("a[2]: %d\n", a[2]);
    printf("*(a+2): %d\n", *(a + 2));
    printf("*(&a[0]+2): %d\n", *(&a[0] + 2));

    //sizeof 指针和数组
    int *p = a;
    printf("p: %d\n", sizeof(p)); // 4 bytes
    printf("a: %d\n", sizeof(a)); // 20 bytes

    //数组传参
    function(a);

    return 0;
}

void function(int a[ ])
{
    printf("function sizeof(a): %d\n", sizeof(a)); // 4 bytes 退化为指针
}

7.柔性数组

#include <stdio.h>
#include <string.h>
#include <stdlib.h>

struct node
{
    int stlen;
    char msg[0];//结构体定义变量后也不为msg[0]分配内存
};

int main(int argc, char const *argv[])
{
    printf("sizeof(struct node)= %d\n", sizeof(struct node));

    char buf[100] = { 0 };
    fgets(buf, 100, stdin);         //从键盘获得最多100个字符存到buf中(含空格回车)

    int n = strlen(buf) + 1;        //计算buf的内容字符数,+1给'\0'

    struct node *p = malloc(sizeof(struct node) + n);   //申请动态内存=结构体固定内存+从键盘获得内容大小

    p->stlen = n;
    strncpy(p->msg, buf, n);        //拷贝n字节buf内容到msg

    printf("sizeo of struct: %d\n", sizeof(struct node) + n);
    printf("msg: %s", p->msg);

    return 0;
}

8. 变长数组

#include <stdio.h>

int main(int argc, char const *argv[])
{
    int n;

    fprintf(stdout,"printf enter n:");
    scanf("%d", &n);

    int a[n];   //不能初始化,程序运行才分配内存

    //但可不初始化的赋值
    int i;
    for (i = 0; i < n; i++)
    {
        scanf("%d", &a[i]);
    }

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

    return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值