频道栏目
首页 > 程序开发 > 软件开发 > C语言 > 正文
C语言基础学习之指针,数组和内存杂讲
2018-05-14 14:32:07      个评论    来源:wintershii的博客  
收藏   我要投稿

C语言基础学习之指针,数组和内存杂讲

大端与小端 sizeof对数组名和普通指针的区别 下标运算符 数组指针和指针数组

C语言允许直接访问物理地址,可以直接对硬件进行操作

因此C既具有高级语言的功能,又具有低级语言的许多功能,能够像汇编语言一样对位、字节和地址进行操作。

我们每个知识点会用具体的例子实现,方便理解。·


1.大端与小端

执行下面的代码,看看输出结果是什么(注意:源文件后缀为.c)

#include 
int main(){
    short num = 0x1122;     //short 占两个字节 
    char *c;                //char 占一个字节 
    c = #
    if(*c == 0x22)
        printf("this is little end\n");
    else
        printf("this is big end\n");
    return 0;
}

这里写图片描述

这表示我们的计算机处于小端模式,那么什么是大端模式和小端模式呢?

大端:数据的低位保存在高地址中,而高位保存在低地址中。 小端: 数据的低位保存在低地址中,高位保存在高地址中。

从上述的例子中,我们先定义一个short型的变量,我们知道short类型占两个字节,把0x1122赋给这个变量,再定义一个指向字符型的指针变量,把short变量的地址赋给它,最终输出显示 这个字符型指针指向的就是short型变量的低位。我们可以用下图来表示这个过程。

0x1122 11是高位,22是低位,我们让short的地址赋给c,其实就是让c指向short的位置,但因为char类型只有一个字节,所以只会输出short类型中的一个字节,如图所示:

这里写图片描述

*c输出结果为22,代表目前低位存在低地址中。所以现在机器是小端模式。


2.sizeof的注意项

#include 
int main(){
    int a[3] = {1,2,3}; 
    int *p = a;
    printf("%d\n", sizeof(a));
    printf("%d\n", sizeof(p));
    return 0;
}

输出结果是这样

这里写图片描述

因为a是数组名,sizeof在这里会自动判断,于是输出这个数组的大小。但虽然指针变量p也指向数组首地址,但sizeof判断接收到的是指针变量而不是数组名时,会输出 当前指针类型的大小。这个数组有三个整形变量,每个变量占四个字节,所以就是大小就是12字节,在64位系统下,指针变量的大小是8字节(32位下是4字节)。


3.下标运算符

在学完数组之后,我们都知道[]是放数组下标的地方,但怎么用其他方式表示呢?实际上,a[n] 就等同于 * (a+n)。同样我们可以这样写,n[a],这样写好像是错误但,但实际上它表示 *(n+(a)),其实和上面表示的意思是相同的。

下面是个例子

#include 

int main(int argc, char *argv[]){
    int nums[3][3] = {1, 2, 3, 4, 5, 6, 7, 8, 9};
    printf("%d\n", nums[1][-2]);
    printf("%d\n", (-1)[nums][5]);
    printf("%d\n",  -1[nums][5]);
    return 0;
}
nums[1][-2] 表示 : ((nums+1)+(-2)) 其实就是 nums[0][1] 结果是 2。 (-1)[nums][5] 表示:(*(nums+(-1))+5) 先向前移动一个一维元素大小(数组),再向后移动五个二维元素的大小(整形变量),其实就是nums[0][3],结果是3。 -1[nums][5] 表示:-((1+(nums))+5),其实就是-a[2][2],结果是-9。

4.数组指针和指针数组

我们先来看两行代码:int * a[5]和 int (* a)[5],它们的意义相同吗?答案是否定的。int *a[5] 表示a是一个数组,里面每个数组元素都是指向整形的指针变量。int ( *a)[5],()的优先级高于[],所以首先a是一个指针类型,其次这个指针指向一个数组。

下面是个例子:

#include 
int main(){
    int array[5] = {1, 2, 3, 4, 5};
    printf("%p %p\n", array, &array[0]);
    printf("%p %p\n", &array + 1, &array[0] + 1);
    int (*pArray)[5] = &array;          //数组指针 
    for (int i = 0; i < 5; i++) {
        printf("%d ", *pArray[i]);
    }
    printf("\n");
    int array2[2][5] = {
        {1, 2, 3, 4, 5},
        {6, 7, 8, 9, 10}
    };
    pArray = array2;
    printf("%d %d\n", *(*(array2 + 1) + 1), pArray[1][1]);
    int (*pArray2)[2][5] = &array2;
    for (int i = 0; i < 2; i++) {
        for (int j = 0; j < 5; j++) {
            printf("%d ", (*pArray2)[i][j]);
        }
        printf("\n");
    }
    return 0;
}

注:%p代表该变量的地址。

首先输出 array的地址 和array[0]的地址,这表明,数组名就表示数组的首地址。

接下来定义一个数组指针指向array,此时给这个指针每进行一次下标运算符,在内存中移动的是整个数组的大小,所以除了本身,其他运算后的数值都是不可预测的。

后面的也是相同的道理,只不过是二维数组的东西,理解以上之后会很容易理解这些。

点击复制链接 与好友分享!回本站首页
上一篇:用C语言打印100~200之间的素数的操作分享
下一篇:C数据结构之Floyd和Dijstra实现最短路径教程
相关文章
图文推荐
点击排行

关于我们 | 联系我们 | 广告服务 | 投资合作 | 版权申明 | 在线帮助 | 网站地图 | 作品发布 | Vip技术培训 | 举报中心

版权所有: 红黑联盟--致力于做实用的IT技术学习网站