指针与数组的区别详解

简介:
 指针是C语言的精华,它是一柄“双刃剑”,用的好与坏就看使用者的功力了。下面就一道测试题,看一下指针与数组的区别。
 

char *p1, *p2;
char ch[12];
char **pp;
p1 = ch;
pp = &ch;

p2 = *pp;
问p1和p2是否相同

 
    题目如上,找出其中的不妥之处。
 
    首先,数组ch是没有初始化的。其次,一个比较隐含的地方是,数组名可以代表数组第一个元素的首地址,这个没有问题,但是,数组名并非一个变量,数组分配 完成后,数组名就是固定的,地址也是固定的。这样导致的结果就是绝对不能把数组名当作变量来进行处理。上述题目中,pp=&ch,显然是把数组名 当作指针变量来使用了,这样肯定出问题。

    这个题目存在的两个问题,第一个问题比较简单,可以认为是粗心大意。但是第二个问题就是相当复杂了,扩展开来,那就是C语言中的精华中的指针和数组的联系 与区别问题了。

    下面分为两步,首先看一下指针和数组的区别方法,然后提出对上述程序的修改方案。

1 指针和数组的区别

(1)指针和数组的分配

    数组是开辟一块连续的内存空间,数组本身的标识符(也就是通常所说的数组名)代表整个数组,可以使用sizeof来获得数组所占据内存空间的大小(注意, 不是数组元素的个数,而是数组占据内存空间的大小,这是以字节为单位的)。举例如下:
 

#include <stdio.h>

int main(void)
{
        char a[] = "hello";
        int b[] = {1, 2, 3, 4, 5};

        printf("a: %d\n", sizeof(a));
        printf("b memory size: %d bytes\n", sizeof(b));
        printf("b elements: %d\n", sizeof(b)/sizeof(int));

        return 0;
}

 
    数组a为字符型,后面的字符串实际上占据6个字节空间(注意最后有一个\0标识字符串的结束)。从后面sizeof(b)就可以看出如何获得数组占据的内 存空间,如何获得数组的元素数目。至于int数据类型分配内存空间的多少,则是编译器相关的。gcc默认为int类型分配4个字节的内存空间。
 
(2)空间的分配

    这里又分为两种情况。

    第一,如果是全局的和静态的
    char *p = “hello”;
    这是定义了一个指针,指向rodata section里面的“hello”,可以被编译器放到字符串池。在汇编里面的关键字为.ltorg。意思就是在字符串池里的字符串是可以共享的,这也是 编译器优化的一个措施。
    char a[] = “hello”;
    这是定义了一个数组,分配在可写数据块,不会被放到字符串池。

    第二,如果是局部的
    char *p = “hello”;
    这是定义了一个指针,指向rodata section里面的“hello”,可以被编译器放到字符串池。在汇编里面的关键字为.ltorg。意思就是在字符串池里的字符串是可以共享的,这也是 编译器优化的一个措施。另外,在函数中可以返回它的地址,也就是说,指针是局部变量,但是它指向的内容是全局的。
    char a[] = “hello”;
    这是定义了一个数组,分配在堆栈上,初始化由编译器进行。(短的时候直接用指令填充,长的时候就从全局字符串表拷贝),不会被放到字符串池(同样如前,可 能会从字符串池中拷贝过来)。注意不应该返回它的地址。

(3)使用方法

    如果是全局指针,用于不需要修改内容,但是可能会修改指针的情况。
    如果是全局数组,用于不需要修改地址,但是却需要修改内容的情况。
    如果既需要修改指针,又需要修改内容,那么就定义一个数组,再定义一个指针指向它就可以了。

2 我编写的修改方案
 

[armlinux@lqm pointer]$ cat pointer.
/*
 * Copyright 2007 (c), Shandong University
 * All rights reserved.
 *
 * Filename : test.c
 * Description: about pointer
 * Author : Liu Qingmin
 * Version : 1.0
 * Date : 2007-08-27
 */


#include <stdio.h>

/*
 * define a macro which is used to debug array mode and pointer mode.
 * if 1, debug array mode; else debug pointer mode.
 * You can change it according to your decision.
 */

#define ARRAY_OR_POINTER 0

int main(void)
{
        char *p1;
        char *p2;
        char **pp;

        //test1

        #if ARRAY_OR_POINTER
                char ch[] = "hello, world!\n";

                printf("%d, %d, %d, %d\n", sizeof(p1), sizeof(p2),
                                           sizeof(pp), sizeof(ch));
        #else
                char *ch = "hello, world!\n";

                printf("%d, %d, %d, %d\n", sizeof(p1), sizeof(p2),
                                           sizeof(pp), sizeof(ch));
        #endif

        //test2

        p1 = ch;

        #if ARRAY_OR_POINTER
                pp = &p1;
        #else
                pp = &ch;
        #endif

        p2 = *pp;


        if (p1 == p2) {
                printf("p1 equals to p2\n");
        } else {
                printf("p1 doesn't equal to p2\n");
        }

        return 0;
}

 
    执行结果如下:
 

// ARRAY_OR_POINTER为0时

[armlinux@lqm pointer]$ ./test
4, 4, 4, 4
p1 equals to p2
// ARRAY_OR_POINTER为1时

[armlinux@lqm pointer]$ ./test
4, 4, 4, 15
p1 equals to p2

 
    如果使用了数组定义方式,而又使用pp=&ch,那么就会出现类似下面的错误:
 

[armlinux@lqm pointer]$ make
gcc -Wall --O2 --o pointer.o pointer.c
pointer.c: In function `main':
pointer.c:44: warning: assignment from incompatible pointer type
gcc -Wall -g -O2 pointer.o -o test
[armlinux@lqm pointer]$ ./test
4, 4, 4, 15
p1 doesn'
equal to p2

目录
相关文章
|
2月前
|
存储 数据可视化 C++
第九问:能否尽可能详细阐述指针和引用的区别?
在C++中,指针和引用是两个重要的概念,用于操作内存地址和数据。指针是一个存储内存地址的变量,可以动态分配和释放内存;引用是变量的别名,绑定后不可改变指向。指针提供更大的灵活性和控制力,适用于复杂内存操作;引用更直观,适合简化代码并提高可读性。根据实际需求选择合适的工具。
46 0
|
3月前
|
存储 程序员 编译器
C 语言数组与指针的深度剖析与应用
在C语言中,数组与指针是核心概念,二者既独立又紧密相连。数组是在连续内存中存储相同类型数据的结构,而指针则存储内存地址,二者结合可在数据处理、函数传参等方面发挥巨大作用。掌握它们的特性和关系,对于优化程序性能、灵活处理数据结构至关重要。
|
3月前
|
容器
在使用指针数组进行动态内存分配时,如何避免内存泄漏
在使用指针数组进行动态内存分配时,避免内存泄漏的关键在于确保每个分配的内存块都能被正确释放。具体做法包括:1. 分配后立即检查是否成功;2. 使用完成后及时释放内存;3. 避免重复释放同一内存地址;4. 尽量使用智能指针或容器类管理内存。
|
3月前
|
存储 C语言 计算机视觉
在C语言中指针数组和数组指针在动态内存分配中的应用
在C语言中,指针数组和数组指针均可用于动态内存分配。指针数组是数组的每个元素都是指针,可用于指向多个动态分配的内存块;数组指针则指向一个数组,可动态分配和管理大型数据结构。两者结合使用,灵活高效地管理内存。
|
3月前
|
存储 NoSQL 编译器
C 语言中指针数组与数组指针的辨析与应用
在C语言中,指针数组和数组指针是两个容易混淆但用途不同的概念。指针数组是一个数组,其元素是指针类型;而数组指针是指向数组的指针。两者在声明、使用及内存布局上各有特点,正确理解它们有助于更高效地编程。
|
3月前
|
存储 人工智能 算法
数据结构实验之C 语言的函数数组指针结构体知识
本实验旨在复习C语言中的函数、数组、指针、结构体与共用体等核心概念,并通过具体编程任务加深理解。任务包括输出100以内所有素数、逆序排列一维数组、查找二维数组中的鞍点、利用指针输出二维数组元素,以及使用结构体和共用体处理教师与学生信息。每个任务不仅强化了基本语法的应用,还涉及到了算法逻辑的设计与优化。实验结果显示,学生能够有效掌握并运用这些知识完成指定任务。
81 4
|
3月前
使用指针访问数组元素
【10月更文挑战第31天】使用指针访问数组元素。
63 2
|
3月前
使用指针访问数组元素
【10月更文挑战第30天】使用指针访问数组元素。
53 3
|
3月前
|
算法 索引
单链表题+数组题(快慢指针和左右指针)
单链表题+数组题(快慢指针和左右指针)
51 1
|
4月前
|
存储 安全 编译器
在 C++中,引用和指针的区别
在C++中,引用和指针都是用于间接访问对象的工具,但它们有显著区别。引用是对象的别名,必须在定义时初始化且不可重新绑定;指针是一个变量,可以指向不同对象,也可为空。引用更安全,指针更灵活。

热门文章

最新文章