Discuz! Board

 找回密码
 立即注册
搜索
热搜: 活动 交友 discuz
查看: 1980|回复: 2
打印 上一主题 下一主题

数组

[复制链接]

1272

主题

2067

帖子

7958

积分

认证用户组

Rank: 5Rank: 5

积分
7958
跳转到指定楼层
楼主
发表于 2019-12-30 21:27:50 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
数组给数组赋值
float        PILOT_POL_STRENGTH[CdmaSCDR::MAX_PILOTPOL_NUM];
        float PILOT_POL_STRENGTH[MAX_PILOTPOL_NUM];       
memcpy(rec->PILOT_POL_STRENGTH, scdr->PILOT_POL_STRENGTH, sizeof(rec->PILOT_POL_STRENGTH));

回复

使用道具 举报

1272

主题

2067

帖子

7958

积分

认证用户组

Rank: 5Rank: 5

积分
7958
沙发
 楼主| 发表于 2020-1-4 15:02:38 | 只看该作者
我review的几个 发现计算数组索引的地方全错了 比如
void CommonStrengthRegion(int * ECIO,float fAccessStrength)//-1
{
int index = 0;
if (fAccessStrength == (int)fAccessStrength)
{
index = fAccessStrength * (-1);
}
else
{
index = (int)fAccessStrength *(-1) +1;
}
ECIO[index] += 1;
}

其中fAccessStrength的取值范围是(0,-31]

按照上面函数的计算 计算出来的数组索引范围是1 - 31

我把它改成如下:
int index = (int)fAccessStrength *(-1);
if (fAccessStrength == (int)fAccessStrength)
{
--index;
}
ECIO[index] += 1;

删字段的时候 要从结构体声明里也删掉
这样可以省点内存

还有注意结构体初始化的问题
有效值范围的问题

key就是汇总粒度描述

另外 注意一下除法运算 看有没有除0的可能
还有整数作为被除数 结果是浮点类型时,除数也要是浮点类型 比如:
float fOnewayDely = luc1x_scdr->LAST_ROUND_TRIP_DELAY * 244 / 2 / 8.0f;

float fOnewayDely = luc1x_scdr->LAST_ROUND_TRIP_DELAY * 244 / 2.0f / 8.0f;
的结果是不一样的
回复 支持 反对

使用道具 举报

1272

主题

2067

帖子

7958

积分

认证用户组

Rank: 5Rank: 5

积分
7958
板凳
 楼主| 发表于 2020-1-28 18:35:16 | 只看该作者
--------------一维数组----------------
数组可以初始化,即在定义时,使它包含程序马上能使用的值。
  例如,下面的代码定义了一个全局数组,并用一组Fibonacci数初始化:
    int iArray[10]={1,1,2,3,5,8,13,21,34,55); //初始化
    void main()
    {
      //...
    }
  初始化数组的值的个数不能多于数组元素个数,初始化数组的值也不能通过跳过逗号的方式来省略,这在C中是允许的,但在C++中不允许。
  例如,下面的代码对数组进行初始化是错误的:
    int arrayl[5]={1,2,3,4,5,6}; //error: 初始化值个数多于数组元素个数
    int array2[5]={1,,2,3,4}; //error:初始化值不能省略
    int array3[5]={1,2,3,}; //error:初始化值不能省略
    int array4[5]={}; //error:语法格式错误
    void main()
    {
      //...
    }
  初始化值的个数可少于数组元素个数。当初始化值的个数少于数组元素个数时,前面的按序初始化相应值, 后面的初始化为0(全局或静态数组)或为不确定值(局部数组)。
  例如,下面的程序对数组进行初始化:
    //*********************
    //**   ch7_2.cpp  **
    //*********************
    #include <iostream.h>

    int array1[5]={1,2,3};
    static int array2[5]={1};

    void main()
    {
     int arr1[5]={2};
     static int arr2[5]={1,2};

     int n;
     cout <<"global:/n";
     for(n=0; n<5; n++)
       cout <<" " <<array1[n];

     cout <<"/nglobal static:/n";
     for(n=0; n<5; n++)
       cout <<" " <<array2[n];

     cout <<"/nlocal:/n";
     for(n=0; n<5; n++)
       cout <<" " <<arr1[n];

     cout <<"/nlocal static:/n";
     for(n=0; n<5; n++)
        cout <<" " <<arr2[n];
     cout <<endl;
    }

  运行结果为:
    global:
     l  2  3  0  0
    global static:

     1  0  0  0  0
    local:
     2 23567 23567 23567 23567
    local static:
     1  2  0  0  0
  例中,全局数组和全局静态数组的初始化是在主函数运行之前完成的,而局部数组和局部静态数组的初始化是在进入主函数后完成的。
  全局数组arrayl[5]对于初始化表的值按序初始化为1,2,3,还有两个元素的值则按默认初始化为0。
  全局静态数组array2[5]与全局数组的初始化情况一样,初始化表值(1)表示第1个元素的值,而不是指全部数组元素都为1。
  局部数组arrl[5]根据初始化表值的内容按序初始化, 由于初始化表值只有1个,所以还有4个元素的值为不确定。在这里均为数值23567。
  局部静态数组arr2[5]先根据初始化表按序初始化,其余3个数组元素的值默认初始化为0。

2.初始化字符数组

  初始化字符数组有两种方法,一种是:
    char array[10]={"hello"};
  另一种是:
    char array[10]={'h','e','l','l','/0'};
  第一种方法用途较广,初始化时,系统自动在数组没有填值的位置用,'/0'补上。另外, 这种方法中的花括号可以省略,即能表示成:
    char array[10]="hello";
  第二种方法一次一个元素地初始化数组,如同初始化整型数组。这种方法通常用于输入不容易在键盘上生成的那些不可见字符。
  例如,下面的代码中初始化值为若干制表符:
    char chArray[5]={'/t','/t','/t','/t','/0');
  这里不要忘记为最后的,'/0'分配空间。如果要初始化一个字符串"hello",那为它定义的数组至少有6个数组元素。
  例如,下面的代码给数组初始化,但会引起不可预料的错误:
    char array[5]="hello";
  该代码不会引起编译错误,但由于改写了数组空间以外的内存单元,所以是危险的。

3.省略数组大小

  有初始化的数组定义可以省略方括号中的数组大小。
  例如,下面的代码中数组定义为5个元素:
    int a[]={2,4,6,8,10};
  编译时必须知道数组的大小。通常,声明数组时方括号内的数字决定了数组的大小。有初始化的数组定义又省略方括号中的数组大小时,编译器统计花括号之间的元素个数,以求出数组的大小。
  例如,下面的代码产生相同的结果:
    static int a1[5]={1,2,3,4,5};
    static int a2[]={1,2,3,4,5};
  让编译器得出初始化数组的大小有几个好处。它常常用于初始化一个元素个数在初始化中确定的数组,提供程序员修改元素个数的机会。
  在没有规定数组大小的情况下,怎么知道数组的大小呢? sizeof操作解决了该问题。 例如,下面的代码用sizeof确定数组的大小:

    //*********************
    //** ch7_3.cpp **
    //*********************

    #include <iostream.h>

    void main()
    {
     static int a[]={1,2,4,8,16};
     for(int i=0; i<(sizeof(a)/sizeof(int)); i++)
      cout <<a <<" ";
     cout <<endl;
    }

  运行结果为:
    1 2 4 8 16
  sizeof操作使for循环自动调整次数。如果要从初始化a数组的集合中增删元素,只需重新编译即可,其他内容无须更动。
  每个数组所占的存储量都可以用sizeof操作来确定! sizeof返回指定项的字节数。sizeof常用于数组,使代码可在16位机器和32位机器之间移植:
  对于字符串的初始化,要注意数组实际分配的空间大小是字符串中字符个数加上末尾的,'/0',结束符。
  例如,下面的代码定义一个字符数组:

    //*********************
    //**   ch7_4.cpp  **
    //*********************

    #include <iostream.h>

    void main()
    {
     char ch[]="how are you";

     cout <<"size of array: " <<sizeof(ch) <<endl;
     cout <<"size of string: " <<strlen("how are you")            <<endl;
    }

  运行结果为:
    size of array:12
    size of string:ll
  例中,数组大小为12,而字符串长度为11。
  省略数组大小只能在有初始化的数组定义中。
  例如,下面的代码将产生一个编译错误:
    int a[];//error:没有确定数组大小
  在定义数组的场合,无论如何,编译器必须知道数组的大小。



----------------二维数组----------------------------------
一、数组定义和初始化

   1: 一维数组初始化:
   2: 标准方式一: int value[100]; // value的值不定,没有初始化
   3: 标准方式二: int value[100] = {1,2}; // value[0]和value[1]的值分别为1和2,而没有定义的value[i>1]
   4:                                  // 则初始化为0
   5: 指针方式: int* value = new int[n]; // 未初始化
   6:            delete []value;  // 一定不能忘了删除数组空间
   7:  
   8: 二维数组初始化:
   9: 标准方式一: int value[9][9]; // value[j]的值不定,没有初始化
  10: 标准方式二: int value[9][9] = {{1,1},{2}}; //value[0][0,1]和value[1][0]的值初始化,其他初始化为0
  11: 指针方式一: int (*value)[n] = new int[m][n];
  12:              delete []value; // n必须为常量,调用直观。未初始化
  13: 指针方式二: int** value = new int* [m];
  14:              for(i) value = new int[n];
  15:              for(i) delete []value;
  16:              delete []value; // 多次析构,存储麻烦,未初始化
  17: 指针方式三: int * value = new int[3][4]; // 数组的存储是按行存储的
  18:              delete []value; // 一定要进行内存释放,否则会造成内存泄露
  19:  
  20: 多维数组初始化:
  21: 指针方式: int * value = new int[m][3][4]; // 只有第一维可以是变量,其他几维必须都是常量,否则会报错
  22:            delete []value; // 一定要进行内存释放,否则会造成内存泄露

数组初始化的大括号后面要加“;”来表示结束。

数组访问:

指针形式:如二维数组value[j]的访问:

*(value + j) 或

(*(value + i))[j]

二、数组作为参数传递

   1: 一维数组参数传递:
   2: void Func(int *value);
   3: 或者是
   4: void Func(int value[]);
   5:  
   6: 二维数组传递:
   7: 定义是 int **value;的传递
   8: void Func(int **value);
   9: 定义是 int (*value)[n] = new int[m][n];的传递
  10: void func(int (*value)[n]); // sizeof(p)=4,sizeof(*value)=sizeof(int)*n;

三、数组与指针关系

1、数组名的内涵在于其指代实体是一种数据结构,这种数据结构就是数组;

2、数组名的外延在于其可以转换为指向其指代实体的指针,而且是一个指针常量;

3、指向数组的指针则是另外一种变量类型,(在win32平台下,长度为4),仅仅意味着数组存放地址。

4、数组名作为函数形参时,在函数体内,其失去了本身的内涵,仅仅只是一个指针,而且在其失去其内涵的同时,它还失去了其常量特性,可以作自增、自减等操作,可以被修改。

四、数组的存储格式

多维数组在内存中存储时是按照最低维连续的格式存储的,如二维数组{{1,2},{3,4}}在内存中的位置是这样顺序的“1,3,2,4”,这跟matlab是有区别的,matlab是按列进行存储的。在使用指针进行索引时很有用。

五、字符数组

char类型的数组被称作字符数组,通常用来存储字符串。字符串是附加有特殊字符(串尾标志)的字符序列。串终止字符表明字符串已经结束,该字符由转义序列‘\0’定义,有时被称为空字符,占用一个字节,其中8位全为0。这种形式的字符串通常被称为C型字符串,因为以这样的方式定义字符串是在C语言中推出的,在C++一般使用string,而MFC中则定义了CString类。

字符串中每个字符占用一个字节,算上最后的空字符,字符串需要的字节数要比包含的字节数多一个。如:

char movie_star[15] = “Marilyn Monroe”;

这里字符串是14个字符,但是要定义15个字符串的数组。也可以不指定字符数组的个数。如:

char movie_star[] = “Marilyn Monroe”;

六、内存泄露

我们定义了一个指针,然后给它赋予了一个地址值,然后又不再使用,但是没有delete,那么当给指针赋予其他的地址值时,原来的内存将无法释放,这就叫做内存泄露。


http://hi.baidu.com/%CC%EC%D1%C4 ... 9979123bf3cf59.html
先给出问题:
像下面这样的数组,在函数中如何传参?也就是说如何保证虚参与实参类型一致。

char str_arr[3][10] = {"yes","no","uncertain"};
char *str_array[] = {"yes","no","unsure"};

函数原型:
               void func1( char (*a)[10] )
               void func2( char **a )

调用:
              func1( str_arr );
              func2( str_array);
如果向func2()中传入str_arr会怎么样呢?编译器会警告:传递参数 1 (属于 ‘func2’)时在不兼容的指针类型间转换。即虚参与实参类型不一致。

同理,也不能向func1()中传入str_array。

我们给出完整的测试程序:

/********二维数组传参测试程序***************/
#include <stdio.h>
void func1( char (*a)[10])
{
        int i;
        for(i=0;i<3;i++)
                printf("%s\n",a);
}

void func2( char **a )
{
        int i;
        for(i=0;i<3;i++)
                printf("%s\n",*(a+i));
}

int main()
{
        char str_arr[3][10] = {"yes","no","uncertain"};
        char *str_array[] = {"yes","no","unsure"};
        char *str[3] = {"a","b","c"};/*这两种表达效果一样*/
        func1(str_arr);
        func2(str_array);   
        return 0;
}
/******************end*******************/
运行结果:
[root@localhost ansi_c]# gcc test.c
[root@localhost ansi_c]# ./a.out
yes
no
uncertain
yes
no
unsure
[root@localhost ansi_c]#
如果将
        func1(str_arr);
        func2(str_array);
改成:
        func1(str_array);
        func2(str_arr);
会怎么呢?
[root@localhost ansi_c]# gcc test.c
test.c: 在函数 ‘main’ 中:
test.c:22: 警告:传递参数 1 (属于 ‘func1’)时在不兼容的指针类型间转换
test.c:23: 警告:传递参数 1 (属于 ‘func2’)时在不兼容的指针类型间转换

这两种数组的正确赋值应该如下:
        char str_arr[3][10] = {"yes","no","uncertain"};
        char *str_array[] = {"yes","no","unsure"};
        char (*pa)[10] = str_arr;
        char **p = str_array;
pa和p才是和他们相一致的类型。




当然,如果不是传参的话,在main()函数中就不会发生这么多烦恼了。
/*************非传参时的情况************************/
#include <stdio.h>
int main()
{
        char str_arr[3][10] = {"yes","no","uncertain"};
        char *str_array[] = {"yes","no","unsure"};
        char *str[3] = {"a","b","c"};
        int i;
        for(i=0;i<3;i++)
              printf("%s\n",str_arr);
        for(i=0;i<3;i++)
              printf("%s\n",str_array);
         return 0;
}
/*************************************/
运行结果:
[root@localhost ansi_c]# gcc test1.c
[root@localhost ansi_c]# ./a.out
yes
no
uncertain
yes
no
unsure
[root@localhost ansi_c]#

这说明了一点,在没传参之前,main()函数清楚它们都是二维数组。对于上面给出的两种函数原型:
函数原型:
               void func1( char (*a)[10] )
               void func2( char **a )
这两种传参方法有什么不同呢?这们对实参有什么要求呢?

上面只是抛出了一个问题,我在这里的主题是想搞清楚二维数组传参有什么奥秘,而非只针对这一个问题提出解决方法。
后面从基础的开始讨论。

我们先看看教材上怎么讲这一块的,
谭浩强的《C程序设计》二维数组作为参数传递,原文如下(略有改变,请原谅):

[原文开始]

    可以用二维数组名作为实参或者形参,在被调用函数中对形参数组定义时可以可以指定所有维数的大小,也可以省略第一维的大小说明,如:
    void Func(int array[3][10]);
    void Func(int array[][10]);
    二者都是合法而且等价,但是不能把第二维或者更高维的大小省略,如下面的定义是不合法的:
    void Func(int array[][]);

    因为从实参传递来的是数组的起始地址,在内存中按数组排列规则存放(按行存放),而并不区分行和列,如果在形参中不说明列数,则系统无法决定应为多少行多少列,不能只指定一维而不指定第二维,下面写法是错误的:
    void Func(int array[3][]);

    实参数组维数可以大于形参数组,例如实参数组定义为:
    void Func(int array[3][10]);
    而形参数组定义为:
    int array[5][10];
    这时形参数组只取实参数组的一部分,其余部分不起作用。

[原文结束]

   也就是说多维数组传参要指定第二维或者更高维的大小,可以省略第一维的大小。
像 int array[3][4],要传参的话,函数原型可以为下面三种的任一种:
      void func(int a[3][4])
     void func(int a[][4])
     void func(int (*a)[4])
调用时为:func(array);

    同时教材里也说了,如果在型参里不说明列数,则编译器无法决定应为多少行多少列。那么能不能把
int array[3][4]的数组名 array 传给 void func(int **a)呢?
看下面:
/**********************************/
#include <stdio.h>
int main()
{
int array[3][4];
int **p = array;
}
**********************************/
root@localhost ansi_c]# gcc test2.c
test2.c: 在函数 ‘main’ 中:
test2.c:5: 警告:从不兼容的指针类型初始化
[root@localhost ansi_c]#

虽然从本质上讲int array[3][4] 的数组名相当于二级指针,但它不等同于一般的二级指针,因为它还含有数组相关的信息,所以在main函数中:
char str_arr[3][10] = {"yes","no","uncertain"};

for(i=0;i<3;i++)
              printf( "%s\n",str_arr+i );

它可以通过下标,每次跳过10个字节来寻址。我们再看看编译器是怎样处理数组的:
对于数组 int p[m][n];
       如果要取p[j]的值(i>=0 && i<m && 0<=j && j < n),
编译器是这样寻址的:
       p + i*n + j;

我们再看一个例子:
/*********************二维数组传参*****************************/
#include <stdio.h>
void fun( int *a, int m, int n)
{
        int i,j;
        for( i=0; i<m; ++i)
        {
                for(j=0;j<n;++j)
                {
                        printf("%d ", *( a+i*n+j ) );
                }
                putchar('\n');
        }
}

void func( int *a, int m, int n)
{
        int i,j;
        for( i=0;i<m*n;++i)
        {
                        printf("%d ",a);
        }
        putchar('\n');
}

int main()
{
     int a[3][3] =
    {
      {1, 1, 1},
      {2, 2, 2},
      {3, 3, 3}
    };
        fun( (int *)a, 3,3);
        func( &a[0][0],3,3);
        func( (int *)a, 3,3);
        return 0;
}

********************end******************************/
[root@localhost ansi_c]# gcc test4.c
[root@localhost ansi_c]# ./a.out
1 1 1
2 2 2
3 3 3
1 1 1 2 2 2 3 3 3
1 1 1 2 2 2 3 3 3
[root@localhost ansi_c]#

我们来看其中的要点,
数组为:
int a[3][3] =
    {
      {1, 1, 1},
      {2, 2, 2},
      {3, 3, 3}
    };
函数原型和调用为:
原型:
void fun( int *a, int m, int n)  
{
.............
         printf("%d ", *( a+i*n+j ) );
.............
}   
调用:
    fun( (int *)a, 3,3);

另一个函数为:
原型:
void func( int *a, int m, int n)
{
.............
         printf("%d ",a);
.............
}   
调用:
    func( &a[0][0],3,3);
    func( (int *)a, 3,3);
我们发现这两种方式都能正常执行,我们把一个二级指针,强制转换成了一级指针传了进去,并在函数中模仿编译器数组的寻址方式:*( a+i*n+j )。

我们再看看二维字符数组的例子:
/*******************二维字符数组*******************************/

#include <stdio.h>
void f( char **a, int n)
{
        int i;
        printf("%c\n",*( (char*)a+0 ) );
        printf("%c\n",((char * )a)[n] );
        puts("------------OK");

        for(i=0;i<3;i++)
                printf("%s\n",(char*)a+i*n );
        }
int main()
{
        char str_arr[3][10] = {"yes","no","uncertain"};

        f( (char **)str_arr, 10);
        return 0;
}
/****************end*************************/
运行结果:
[root@localhost ansi_c]# ./a.out
y
n
------------OK
yes
no
uncertain
[root@localhost ansi_c]#
这里也做了强制类型转换,转换成字符指针,
printf("%s\n",(char*)a+i*n ); 每个字符串的地址就是数组中字符'y'、'n'、'u'的地址,
printf("%c\n",*( (char*)a+0 ) );字符在数组中的排列是顺序的,可以用 *( (char*)a+i )或 ((char * )a) 表示。
当然这个程序也可以改成这样,完全不用二级指针:
/*****************************************************************/
#include <stdio.h>
void f( char *a, int n)
{
        int i;
        printf("%c\n",*( a+0 ) );
        printf("%c\n",(a)[n] );
        puts("------------OK");

        for(i=0;i<3;i++)
                printf("%s\n",a+i*n );
        }
int main()
{
        char str_arr[3][10] = {"yes","no","uncertain"};

        f( (char *)str_arr, 10);
        return 0;
}
/*****************************************************************/
归根结底,还是把它转成一级指针来用。

下面做个小结:

数组传参
数组:
        int array[4][10];
函数原型:
         void func1( int a[][10] );
        void func2( int (*a)[10] );
        void func3( int *p, int col, int row );
函数调用:
        func1( array );
        func2( array );
         func3( (int *)array, 4, 10 );

容易出错的地方:
int arr[][10];
int **p = arr;
这种方式是错误的.
应该是
int (*p)[10] = arr;
同理,也不能将arr传给fun( int **p)

另外数组传参之后会降级为指针,如:
#include <stdio.h>
void Test(char a[][2])
{
     int size = sizeof( a );//4
}
int main(void)
{
      char a[3][2] = {'a','b','c','d','e','f'};
      int size =sizeof( a );//6
     Test( a );
     return 0;
}


来源:http://hi.baidu.com/d_life/blog/ ... d363e9ce1b3e2a.html



函数原型:要求传入一个动态二维数组
void func1(int **p,int row, int column)
{
}
调用:
int main()
{
int m,n;
int **b;
cin >> m;
cin >> n;
b = new int *[m];
for(int i=0; i<m; i++)
{
  b = new int[n];
};
func1(b,m,n);
return 0;
}

我习惯的做法是不用指针数组,定义一个大块(这种情况主要面向每行行数相同):比如现在有一个W*H的矩阵(H个长度为W的数组),你就直接定义一个float型指针:   float* pfBuffer;然后动态分配大小 pfBuffer = new float[W*H];这个buffer在用完之后要调用 delete pfBuffer;来释放.你传递这个float指针,传递行列数之后,你如果要访问y行x列的话,只要算一下它在哪儿, int addr = y*W+x;就是其"地址"了,你要访问它,直接使用pfBuffer[addr]就OK了,实际上我做图象处理的时候全部这样做,因为这样的地址访问很明了,不会给阅读带来不便,而且作为大部分的时候,我们用矩阵比较多,列数不等的情况很少。这只是个人见解。



来源:http://www.sunxin.org/forum/thread/5416.html?page=1



回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|Archiver|手机版|小黑屋|firemail ( 粤ICP备15085507号-1 )

GMT+8, 2024-11-22 23:00 , Processed in 0.062461 second(s), 18 queries .

Powered by Discuz! X3

© 2001-2013 Comsenz Inc.

快速回复 返回顶部 返回列表