深入理解c语言数组

一 数组名是什么

数组就是一段连续可用的内存。
比如声明一个 int数组

int array[]={1,2,3};

array代表什么?有的资料说:数组名是指向数组首地址的常量指针。

下面我们可以验证一下。
我都知道sizeof操作符可以返回一个对象或者类型所占的内存字节数。
如:
int i=1;
那么sizeof(i) 的结果就是4(64位机器下的部分编译器是8)

那我们打印sizeof(array)

printf("%d\n",sizeof(array));

结果是:12。

但是我们都知道sizeof(指针变量)==4的。

所有我们得出:数组名不完全是指向数组首地址的常量指针

为什么要用不完全,因为我们利用数组来访问数组元素的时候。它又变得像一个常量指针。

比如
array[0]等效于*(array+0)

这时候 array就是一个指向数组首地址的常量指针,指针类型是指向数组元素类型的指针。这里就是 int*类型

我们可以这样理解:

一个大学的名字叫array。
有人问你array是什么。你会告诉他array是大学,面积多少之类的。
但是有人问你去array怎么走,你会告诉他array的校门(首地址)在哪里。

结论:数组名其实代表的是一个内存区域,但是使用的时候变成了 指向数组首地址的常量指针。

但是这里还有一个小陷阱:

代码如下:

#include <stdio.h>

void foo(int a[])
{
  printf("%d\n",sizeof(a));
}

int main(void)
{
  int array[]={1,2,3};
    foo(array);
    return 0;
}

输出的不是12,而是4。

出于效率的考虑,数组传参是引用传参而不是拷贝传参。因为数组长度可能很大,拷贝一份的话太耗资源。
虽然我是这样函数是这样的

代码如下:

void foo(int a[])
{
printf("%d\n",sizeof(a));
}

编译器的眼中是这样

代码如下:

void foo(int *a)
{
printf("%d\n",sizeof(a));
}

所以sizeof(a)是sizeof(指针变量)肯定是4;

二 字符数组

首先我们看一个简单的程序

代码如下:

# include <stdio.h>

int main(void)
{
  char *str1="abc";
  char str2[]="def";

  printf("%s\n",str1+4);
  return 0;
}

输出的结果是 def。

我们要知道c语言中只要用到了 "xxxxx",系统都会自动的把双引号的内容添加到字符常量区。
注意:printf("xxxx");不会把"xxxx"添加到字符常量区。

代码如下:

char *str1="abc";         //会把 abc\0 添加到字符常量区,并把首地址赋值给str指针变量。
char str2[]="def";        //会把 def\0 添加到字符常量区,并且函数栈中添加一个字符数组 内容也是 def\0,str2指向的是栈中的数组。
char str[]={'x','y','z'}; //只会在函数栈中添加数组

由于字符常量区是连续的,所以

printf("%s\n",str1+4);

可以打印出str2的值。

三 二维数组

int array[][3]={1,2,3,4,5,6};

前面我们已经说了,使用array访问元素时,array就是一个指针类型为指向数组元素的指针类型,指向数组首地址的指针。
二维数组的元素就是数组,

这样写就更容易理解:
int array[][3]={{1,2,3},{4,5,6}};

所有可以 这样认为 array是这样认为的
int (*const array)[3];
当我访问数组元素时候

array[x][y]在编译器看来就是 *(*(array+x)+y)

*(array+x) 得到的是一个 第x行 类型为 “int[3]”(c语言没有这样的写法) 的数组,

数组名在访问元素的时候当做首地址指针来用,在这里 *(array+x)等同于数组名,
指针类型int *,指向的地址为 array+sizeof(int(*)[3])*x。

访问这个数组的第y个元素的时候,就要用 *(*(array+x)+y)。

这些就是我对c语言数组的理解,如果错误的地方,谢谢指正,轻喷哈。

(0)

相关推荐

  • C语言实现在数组A上有序合并数组B的方法

    本文实例讲述了C语言实现在数组A上有序合并数组B的方法,分享给大家供大家参考.具体分析如下: 题目:数组A和数组B均有序,数组A有足够大内存来容纳数组B,将数组B有序合并到数组A中 分析:如果由前至后合并,复杂度将会是O(N2),这样的复杂度显然不是最优解,利用两个指针指向两个数组的尾部,从后往前遍历,这样的复杂度为O(n2) 由此可以写出下面的代码: #include <iostream> #include <algorithm> #include <iterator>

  • C语言构建动态数组完整实例

    本文以一个完整的实例代码简述了C语言构建动态数组的方法,供大家参考,完整实例如下: #include <stdio.h> #include <malloc.h> int main(void) { int len; int * arr; printf("请输入数组长度:"); scanf("%d", &len); arr = (int *)malloc(sizeof(int)*len); printf("请输入数组的值:&qu

  • c语言中数组名a和&a详细介绍

    最近又把学习c语言提上日程上来了~~~先把我打算看的书都写下来吧,<C语言深度剖析>,<c和指针>系类,<c语言陷阱和缺陷> 先说说a和&a的区别(有三点,三个方向):1.是a和&a的本质,都是什么类型的.2.从2维数组的角度看.3.从指针运算的角度看. 声明:虽然数组名不是指针,但是用的很像指针,我们暂且把它叫做一个指针吧. 第一个问题:int a[10];  a ,&a和&a[0] 都是分别是什么?先说明a ,&a和&

  • C语言数组指针的小例子

    1.功能:输入6个学生的5门课程成绩,计算出每个学生的平均分和每门课程的平均分.2.C语言实现代码:(其实就是用二维数组来实现的,二维数组的引用传递使用数组指针来完成) 复制代码 代码如下: #include <stdio.h>#define STUDENT 5#define SCORE 6void input_array(float (*score)[STUDENT]);void avg_score(float (*score)[STUDENT]);void avg_course(float

  • C语言中多维数组的内存分配和释放(malloc与free)的方法

    如果要给二维数组(m*n)分配空间,代码可以写成下面: 复制代码 代码如下: char **a, i; // 先分配m个指针单元,注意是指针单元 // 所以每个单元的大小是sizeof(char *) a = (char **) malloc(m * sizeof(char * )); // 再分配n个字符单元, // 上面的m个指针单元指向这n个字符单元首地址 for(i = 0; i < m; i++) a[i] = (char * )malloc(n * sizeof(char )); 释

  • c语言字符数组与字符串的使用详解

    1.字符数组的定义与初始化字符数组的初始化,最容易理解的方式就是逐个字符赋给数组中各元素.char str[10]={ 'I',' ','a','m',' ','h','a','p','p','y'};即把10个字符分别赋给str[0]到str[9]10个元素如果花括号中提供的字符个数大于数组长度,则按语法错误处理:若小于数组长度,则只将这些字符数组中前面那些元素,其余的元素自动定为空字符(即 '\0' ). 2.字符数组与字符串在c语言中,将字符串作为字符数组来处理.(c++中不是)在实际应用

  • C语言一维数组初步学习笔记

    数组 可以存储一组或者多组数值的变量,里面包含多个元素,数组的每个成员都是一个数组元素. 一维数组 定义:类型 数组名[常量表达式] = {值1, 值2, 值3-}; int a[3] = {0, 1, 2}; float f[2] = {1.2, 2.3, 3.14}; char str[] = {'h', 'e', 'l', 'l', 'o'}; chat str1 = "iPhone";//这也是定义字符数组的方法,字符数组后面会详细讲解,这里先了解一下 当数组元素个数为变量时,

  • 约瑟夫环问题(数组法)c语言实现

    问题说明这个问题是以弗拉维奥·约瑟夫斯命名的,它是1世纪的一名犹太历史学家.他在自己的日记中写道,他和他的40个战友被罗马军队包围在洞中.他们讨论是自杀还是被俘,最终决定自杀,并以抽签的方式决定谁杀掉谁.约瑟夫斯和另外一个人是最后两个留下的人.约瑟夫斯说服了那个人,他们将向罗马军队投降,不再自杀.约瑟夫斯把他的存活归因于运气或天意,他不知道是哪一个机智的约瑟夫! 有N个编号为1~N的人围成一圈,现在每隔两个人(比如:1.4 之间隔了2.3)就将一个人淘汰出去,问最后剩下的是编号为几的人? 算法代

  • C语言中全局数组和局部数组的问题

    今天同学遇到一个在C语言中全局数组和局部数组的问题,卡了许久,我也没有第一时间看出问题,现在把问题梳理一下,并给出解决方案. 问题描述: 在全局声明的数组与在局部声明的数组有着不同的效果. 首先来看一个程序: 复制代码 代码如下: #include <stdio.h> #include <stdlib.h> #define MAX 10 char a[MAX]; int main() { int i; char b[MAX]; char *c=(char *)malloc(MAX

  • c语言合并两个已排序数组的示例(c语言数组排序)

    问题:将两个已排序数组合并成一个排序数组 这里先不考虑大数据量的情况(在数据量很大时不知大家有什么好的思路或方法?),只做简单数组的处理. 简单代码如下: 说明:之所以把merge函数定义成返回数组长度,是因为后续会有重复数据合并功能的merge版本,考虑到接口一致性. 复制代码 代码如下: #include <stdio.h>#include <stdlib.h>#include <string.h> int merge(int* ar1, int len1, int

随机推荐