指针域数组

  1.指针数组:一个数组里存放的都是同一个类型的指针,通常我们把他叫做指针数组。

int * a[10];它里边放了10个int * 型变量,由于它是一个数组,已经在栈区分配了10个(int * )的空间,也就是32位机上是40个byte,每个空间都可以存放一个int型变量的地址,这个时候你可以为这个数组的每一个元素初始化,或者单独做个循环去初始化它。

一个指针数组中的指针可以为任何同一类型,例如可以为结构指针、函数指针等
struct a
{

    int a;

 
    int b;

}

typedef struct a STRUCTA


STRUCTA* b[4];//一个存放了4个STRUCTA*型指针的数组,其大小为4*sizeof


(STRUCTA*)=16


typedef void(*FUNC)();


FUNC funarr[4];//定义了一个函数指针数组


2.结构数组

struct a

{

   int a;

   int b;

}a[12];//定义了一个结构数组,大小为12*sizeof(struct a) = 48;


3.数组指针 : 一个指向一维或者多维数组的指针;


int (*b2) [20];     //指针;b2指向一个大小为20*sizeof(int)的int型数组


int(*b3) [30] [20];  //指针――>指向二维数组的指针;


4.数组的数组名具备一些指针的用法,近似于指针

例如:int array[12][31];//数组的嵌套定义,array是一个含有12个数组类型元素的数

组,其中的每一个元素是一个int数组

array是指向数组的指针。
array[1]是一个含有31个int型元素的数组,它的类型是int[31],它指向的类型是int;

int I;
I = array[4][7] 等同于 I = *(array[4]+7)  等同于 I = *(*(array +4)+7)

int *p; int **q;  int (*ptr1)[31];  int (*ptr2)[41];
p = array[2];//正确,p指向数组array[2]中下标为0的元素
p = array; // 错误,array是二维数组,其类型为“数组的数组”,类型不匹配
q = array; //错误,array不是指向指针的指针
ptr1 = array; // 正确,同是指向数组int[31]的指针。
ptr2 = array;//错误,array是指向int[31]的指针,ptr2是指向int[41]的指针。

char*str[3]={
"Hello,thisisasample!",
"Hi,goodmorning.",
"Helloworld"
};
chars[80];
strcpy(s,str[0]);//也可写成strcpy(s,*str);
strcpy(s,str[1]);//也可写成strcpy(s,*(str+1));
strcpy(s,str[2]);//也可写成strcpy(s,*(str+2));

str是一个三单元的数组,该数组的每个单元都是一个指针,这些指针各指向一个字符串。

指针数组名str当作一个指针的话,它指向数组的第0号单元,它的类型是char**,指向的类型是
char*。


*str也是一个指针,它的类型是char*,它所指向的类型是char,它指向的地址是字符串"Hello,thisisasample!"的第一个字符的地址,即'H'的地址。

str+1也是一个指针,它指向数组的第1号单元,它的类型是char**,它指向的类型是char*。
*(str+1)也是一个指针,它的类型是char*,它所指向的类型是char,它指向 "Hi,goodmorning."的第一个字符'H'。


5.下面总结一下数组的数组名的问题。声明了一个数组TYPE array[n],则数组名称array就有了两重含义:
               第一,它代表整个数组,它的类型是TYPE[n];
               第二 ,它是一个指针,该指针的类型是TYPE*,该指针指向的类型是TYPE,该指针指                           向的内存区就是数组第0号单元。
                           该指针自己占有单独的内存区,注意它和数组第0号单元占据的内存区是不同                           的。该指针的值是不能修改的,即类似array++的表达式是错误的。
                           在不同的表达式中数组名array可以扮演不同的角色。
                          在表达式sizeof(array)中,数组名array代表数组本身,故这时sizeof函数测出的                          是整个数组的大小。
                          在表达式*array中,array扮演的是指针,因此这个表达式的结果就是数组第                          0号单元的值。
                          sizeof(*array)测出的是数组单元的大小。
                         表达式array+n(其中n=0,1,2,....。)中,array扮演的是指针,故array+n                          的结果是一个指针,它的类型是TYPE*,它指向的类型是TYPE,它指向数组第                         n号单元。故sizeof(array+n)测出的是指针类型大小。
               例十:
                                  int array[10];
                                  int(*ptr)[10];
                                   ptr=&array;
                                  上例中ptr是一个指针,它的类型是int(*)[10],他指向的类型是int[10] ,                                   我们用整个数组的首地址来初始化它。在语句ptr=&array中,array代表                                   数组本身。


本节中提到了函数sizeof(),那么我来问一问,sizeof(指针名称)测出的究竟是指针自身类型的大小呢还是指针所指向的类型的大小?答案是前者。例如:


int(*ptr)[10];


则在32位程序中,有:


sizeof(int(*)[10])==4


sizeof(int[10])==40


sizeof(ptr)==4


实际上,sizeof(对象)测出的都是对象自身的类型的大小,而不是别的什么类型的大小。


声明与定义

搞清楚这个问题之前,澄清一些重要概念:

C语言中的对象必须有且只有一个定义,但它可以有多个extern声明。

 

 

概念

区别

定义

只能出现在一个地方,确定对象的类型并分配内存,用于创建新的对象。例如:int a[12]

相当于特殊声明,它为对象分配内存。

声明

可多次出现,描述对对象的类型,用于指代其他地方定义的对象。例如:extern int a[]

相当于普通声明,它所说明的并非自身,而是描述其他地方创建的对象。

 

由于extern声明不为对象分配内存,所以不必提供关于数组长度的信息。对于多维数组,需要提供除最左边一维之外其他维的长度——给编译器足够的信息产生相应代码。

 

62输组与指针的访问过程

char a[9] = “abckefg”;                       c = a[i];

编译器符号表具有一个地址9980

              运行时步骤1:取i的值,将它与9980相加;

              运行时步骤2:取地址[9980+i]的内容。

Char *p;                                                          c = *p;

编译器符号表有一个符号p,它的地址是4624

              运行时步骤1:取地址4624的内容,就是’5081’

              运行时步骤2:取地址5081的内容。

 

63定义为指针,但以数组方式引用的过程

char *p = “abchdefs”                                        c = p[i]

编译器符号表有个p,地址为4624

              运行时步骤1:取地址4624的内容,即’5081’

              运行时步骤2:取得I的值,并将它与5081相加;

              运行时步骤3:取地址[5081+i]的内容。

 

如果将p声明为指针,那么不管p原来是定义为指针还是数组,都会按照上面的三个步骤操作。

如:char *p[10];

另一个文件中extern char *p

当用p[I]提取这个声明中的内容时,实际上得到的是一个字符,而编译器却把它当作一个指针……

 

64指针和数组的其他区别

指针

数组

保存数据地址

保存数据

间接访问数据,首先取得指针的内容,把它作为地址,然后从这个地址提取数据。如果指针有个下标[I],就把指针的内容加上I作为地址,从中提取数据

直接访问数据,a[I]只是简单的以a+I为地址取的数据。

通常用于动态数据结构

通常用于存储固定数目且数据类型相同的元素

相关函数为malloc(),free()

隐式分配和删除

通常指向匿名数据

自身即为数据名

 

7 数组与指针相同时

71输组与指针的可交换性

数组    声明:                extern 如:extern char a[];不能改写成指针形式

                            定义,如 char a[10];不能改写成指针形式

                            函数参数,如func(char a[]);可随意选择数组或指针

        在表达式中使用      如c = a[I];随意选择数组或者指针形式

 

规则1:“表达式中的数组名”就是指针。

规则2C语言把数组下表作为指针偏移量

规则3:作为函数参数的数组名等同于指针

 

数组与指针可交换性总结:

1.  a[I]这样的形式对数组进行访问总是被编译器解释为像*(a+1)这样的指针访问。

2.  指针始终就是指针。它绝不可以改写成数组。可以用下标形式访问指针,一般都是指针作为函数参数时,而且实际传递给函数的是一个数组。

3.  在特定的上下文环境中,也就是它作为函数的参数(也只有这种情况),一个数组的声明可以看作是一个指针。作为函数参数的数组(就是在一个函数调用中)始终会被编译器修改成为之乡第一个元素的指针。

4.  因此,当把一个数组定义为函数参数时,可以选择把它定义为数组,也可定义为指针。不管用那种方法,在函数内部事实上获得的都是一个指针。

5.  在其他所有情况中,定义和声明必须匹配。如果定义了一个数组,在其他文件对他进行声明时也必须把它声明为数组,指针也是如此。

 

72多维数组

例:

int apricot[2][3][5];

int (*q)[2][3][5] = &apricot;

int (*p)[3][5] =  apricot;

int (*r)[5] = apricot[i];

int *t = apricot[I][j];

int u = apricot[I][j][k];

 

初始化:

只有字符串常量才可以初始化指针数组

char * vegetables[] = { “carrot”,“celery”,“corn”,“cilantro”,“crispy”};

指针数组不可以由非字符串的类型直接初始化:

int *weights[] = {{1,2,3,4,5},       {6,7,8},};    //无法编译成功

可以这样做:

int row_1[] = {1,2,3,4,5,-1}; //-1是行结束标志。

Int row_2[] = {6,7,8,-1};

Int *weights[] = {Row_1,Row_2,};

 

73 向函数传递一个一维数组

任何一维数组都可以作为函数实参,形参被改写为指向数组第一个元素的指针,所以需要一个约定来提示数组的长度。一般有两个基本方法:

1,  增加一个额外的参数,表示元素数目(argc就起这个作用)

2,  赋予数组最后一个元素一个特殊的值,提示他是数组的尾部(字符串结尾的‘\0’字符就是起这个作用)。这个特殊值必须不会做为正常的元素值在数组中出现。

 

74 使用指针向函数传递一个多维数组

C语言无法表达“这个数组的边界在不同的调用中可以变化”这个概念。C语言必须知道数组边界,从而为下标引用产生正确代码。

二维或多维数组无法在C语言中作一般的形参。无法向函数传递一个普通的多维数组。

可以向函数传递预先确定长度的特殊数组。

 

方法1my_function( int my_array[10][20] );//只能处理1020列的数组。调用时参数也要匹配

方法2my_function( int my_array[][20] );//只能处理20列的数组,调用时参数也要匹配

由于必须提供数组除最左边一维以外的所有维的长度,所以形参只能省略第一个长度。

方法3my_function( char **my_array,…… );

此方法使用前提,必须在调用之前将二维数组改为一个指向向量的指针数组。必须是指针数组,而且必须是指向字符串的指针数组。

 

总结:如果多维数组各维的长度是一个完全相同的固定值,那么把它传给一个函数毫无问题。如果情况更一般些,也更常见一些,就是作为函数的参数的数组的长度是任意的,分析如下:

1,  一维数组——没有问题,但须包括一个计数值或者是一个能够标识越界位置的结束符。被调用的函数无法检测数组参数的边界。

2,  二维数组——不能直接传递给寒暑,但可以把矩阵改写为一个一维的指针数组,并使用相同的下标表示法。对于字符串来说,这样是可以的,对于其他类型,需要增加一个计数值或者能够标识越界位置的结束符。同样,他依赖于调用函数和被调用函数之间的约定。

3,  三维或更多维——都无法使用。必须把它分解为几个维数更少的数组。

1

int main( int argc, char *argv[] )//由于字符串以’\0’作为结束标志,所以只需要一个argc计数有多少个字符串即可。

2

    int arr[2][3] = {{1,2,3},{4,5,6}};//将要进行传递的二维数组

做法1:

    int *p[2] = {arr[0],arr[1]};将二维数组改造成指针数组,每个指针指向一个一维数组

void fun(int rownum,int colnum,int *array[]);

fun(2,3,p);//传递一个二维数组必须在传递之前将其转化为一个指针数组,传递时还要传递该二维数组的行数和列数。

做法2:

    int *p[3] = {arr[0],arr[1],NULL};将二维数组改造成指针数组,每个指针指向一个一维数组

void fun(in

作者:leeao   更新日期:2004-11-23
来源:upsdn特约撰稿   浏览次数:



相关评论   发表评论

  • leeao  [2004-11-23]

    做法2:

    int *p[3] = {arr[0],arr[1],NULL};将二维数组改造成指针数组,每个指针指向一个一维数组

    void fun(int colnum,int *array[]);//内部以NULL指针判断第一维的结束

    fun(3,p);//只需要传递数组的列数。

    在例2中,若arr[2][3]是char型,则参数还可以少一个。



    9.5 使用指针从函数返回一个数组

    严格的说,无法直接从函数返回一个数组。

    可以让函数返回一个指向任何数据结构的指针来实现:

    例:

    typedef  int (*PARR_20)[20]; //定义数组指针。

    PARR_20 paf(void) //定义一个函数,该函数返回一个指向20维int数组的指针。

    {

    PARR_20 pear;

    int i;

    pear = (PARR_20)calloc(20,sizeof(int));

    if(!pear)

    printf("error!!");

    for (i = 0; i<20 ;i++)

    (*pear)[i] = i;

    return pear;

    }

    调用如下:

    PARR_20 result;

    result = paf();

    printf("result[3] = %d",(*result)[3]);

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: 在 C 语言中,可以使用以下方法来新建一个大小为 10 个整型的指针数组,而不使用 malloc 函数: 1. 在函数内部声明一个指针数组,并分配一个固定的数组大小。 ``` int *arr[10]; ``` 2. 在全局作用声明一个指针数组,并分配一个固定的数组大小。 ``` int *arr[10]; ``` 3. 使用宏来声明一个指针数组,并分配一个固定的数组大小。 ``` #define N 10 int *arr[N]; ``` 注意:上述方法只能声明一个指针数组,并不能为数组中的每个元素分配内存。如果需要为每个数组元素分配内存,还需要使用 malloc 或其他内存分配函数。 例如,可以使用以下代码为数组中的每个元素分配内存: ``` for (int i = 0; i < 10; i++) { arr[i] = malloc(sizeof(int)); } ``` 还可以使用以下代码为数组中的每个元素分配内存: ``` for (int i = 0; i < 10; i++) { *(arr + i) = malloc(sizeof(int)); } ``` 此外,还可以使用 calloc 函数来为数组中的每个元素分配内存,并将内存初始化为 0: ``` for (int i = 0; i < 10; i++) { arr[i] = calloc(1, sizeof(int)); } ``` ### 回答2: 在C语言中,我们可以使用静态分配的方法来创建一个大小为10的整型指针数组,而不使用malloc函数。 具体步骤如下: 1. 声明一个整型指针数组数组大小为10:int *ptrArr[10]; 2. 声明10个整型变量:int num1, num2, num3, num4, num5, num6, num7, num8, num9, num10; 3. 将每个整型变量的地址赋值给指针数组的对应位置,即将变量的地址存储到指针数组的元素中: ptrArr[0] = &num1; ptrArr[1] = &num2; ptrArr[2] = &num3; ptrArr[3] = &num4; ptrArr[4] = &num5; ptrArr[5] = &num6; ptrArr[6] = &num7; ptrArr[7] = &num8; ptrArr[8] = &num9; ptrArr[9] = &num10; 通过这种方法,我们可以创建一个大小为10的整型指针数组,并且不使用malloc函数。这样做的好处是不需要动态内存分配,减少了内存管理的复杂性,但是缺点是数组大小是固定的,无法动态调整。 ### 回答3: 在C语言中,可以使用静态数组来创建一个大小为10个整型的指针数组,而不使用malloc函数来动态分配内存。静态数组的大小是在编译时确定的,因此不需要malloc函数来分配内存。下面是一个示例代码: ```c #include <stdio.h> int main() { int* ptrArray[10]; // 创建一个大小为10的整型指针数组 int a = 1, b = 2, c = 3; // 假设有3个整数需要被指针数组指向 ptrArray[0] = &a; ptrArray[1] = &b; ptrArray[2] = &c; // 继续添加其他整数的指针数组中... // 访问指针数组中的元素 for (int i = 0; i < 10; i++) { if (ptrArray[i] != NULL) { printf("指针数组中的元素 %d 的值为:%d\n", i, *(ptrArray[i])); } } return 0; } ``` 在上述代码中,我们声明一个指针数组`ptrArray`,其大小为10个整型指针。然后,我们可以将具体整数的地址赋值给数组的元素,从而使数组的元素成为指向这些整数的指针。这样,我们就利用了静态数组来存储一组指针而不用使用malloc函数进行动态分配。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值