黑马程序员 《ios零基础教程》 --指针 2014-3-29总结

---------------------- <a href="http://edu.csdn.net"target="blank">ASP.Net+Unity开发</a>、<a href="http://edu.csdn.net"target="blank">.Net培训</a>、期待与您交流! ----------------------


今天学习了复杂数据类型中得指针,指针是关键中的关键


一、指针

1.基本使用

1>定义

#include <stdio.h>

void change(int);

int main(int argc, const char * argv[])
{

    /*
     int a = 90;
     
     change(&a); 
     
     printf("a = %d\n",a);
     */
    
    //指针的定义:
    //变量类型  变量名  
    //格式:变量类型 *变量名;  int *p
    //指针变量只能存储地址
    //指针就一个作用:能够根据一个地址值,访问对应的存储空间
    //指针变量p前面的int:指针变量p只能指向int类型的数据
    
    int *p;//这里的*只是定义这个指针
    
    int a = 90;
    
    //指针变量p指向了变量a
    p = &a;
    
    *p = 10;//这里的*是完成指向a地址的一个过程,即进入了a地址,修改a的值
    
    a = 20;
    printf("%d\n",*p);
    
    return 0;
}

void change(int n)
{
    n = 10;
}

2>配合定义作出的指针内存分析




2.利用指针修改a的值

//利用指针修改a的值

#include <stdio.h>

void change(int *n);

int main(int argc, const char * argv[])
{
    int a = 90;
    
    change(&a);
    
    printf("%d\n",a);
    
    return 0;
}

void change(int *n)
{
    *n = 10;
}

3.关于指针的使用注意事项

#include <stdio.h>

int main(int argc, const char * argv[])
{
    /*不建议的写法,int *p只能指向int类型的数据
     int *p;
     double d = 10.0;
     p = &d;
     */
    
    /*指针变量只能存储地址
     int *p;
     p = 200;
     */
    
    /*
     int *p;
     printf("%d\n",*p);
     */
    
    int a = 10;
    /*
     int a;
     a = 10;
     */
    
    /*
     int *p;
     p = &a;
     */
    
    
    //定义变量时的*仅仅是一个象征,没有其他特殊含义
    int *p;
    
    //不正确的写法
    //*p = &a;
    p = &a;
    
    //这个时候的*的作用:访问指向变量p指向的存储空间
    *p = 20;
    
    char c = 'Q';
    
    char *cp = &c;//其实就相当于(char *)cp = &c;
    
    *cp = 'D';
    
    printf("%c\n",c);
    
    return 0;
}

4.指向指针的指针

1>函数例子

#include <stdio.h>

int main(int argc, const char * argv[])
{

    int a = 10;
    
    int *p = &a;
    
    int **pp = &p;
    
    //a = 20;
    
    //*p = 20;
    
    /*
     (*pp) == p;//这里pp储存的是p的地址,*pp指向p,获取p中存储的值
     
     *(*pp) == *p = a;
     
     **pp == *p = a
     */
    **pp = 20;
    
    printf("%d\n",a);
    
    //int ***ppp = &pp;
    
    /*
     char a2 = 'A';
     char *p2 = &a2;
     */
    return 0;
}

2>指向指针的指针示意图



5.利用指针完成加减法

#include <stdio.h>

int sumAndMinus (int n1 ,int n2 ,int *n3);

int main(int argc, const char * argv[])
{
    int a = 10;
    int b = 7;
    int he ,cha;
    
    he = sumAndMinus(a, b, &cha);
    
    printf("%d  %d",he , cha);
    return 0;
}

int sumAndMinus (int n1 ,int n2 ,int *n3)
{
    *n3 = n1 - n2;
    
    return n1 + n2;
}

6.关于指针的疑问

1>函数例子

/*
 %d int
 %f float/double
 %ld long
 %lld long long 
 %c char
 %s 字符串
 %zd unsigned long
 */
#include <stdio.h>

int main(int argc, const char * argv[])
{
   //这里看内存分析图,如若不明白再看视频,讲解很详细
    //0000 0000 0000 0000 0000 0000 0000 0010 
    int i = 2;
    
    //0000 0001
    char c = 1;
    
    //char *p;
    int *p;//这里定义的char c,指针却用int *p,内存图分析原因为什么不行
    p = &c;
    
    //*p = 10
    
    printf("c的值是%d\n",*p);
    
    return 0;
}

void test()
{
    char c;//1字节
    int a;//4字节
    long b;//8字节
    
    //任何指针都占用8个字节的存储空间
    char *cp;
    int *ap;
    long *bp;
    
    //因为这里返回默认是unsigned long的值,所以返回字符%zd
    printf("cp=%zd , ap=%zd , bp=%zd\n",sizeof(cp),sizeof(ap),sizeof(bp));
    
    //这里的返回值显示不管什么类型指针都占用8个字节
}

2>指针在内存中示意图




7.指针与数组

1>函数例子

#include <stdio.h>

/*
 int ages[5];
 int *p;
 p = ages;
 
 1.数组元素的访问方式
 1>数组名[下标] ages[i]
 2>指针变量名[下标] p[i]
 3>*(p + i)
 
 2.指针变量的+1究竟加多少,取决于指针的类型
 int *    4字节
 char *    1字节
 double *    8字节
 
 */

void change(int array[]);
void test();

int main(int argc, const char * argv[])
{
    //20个字节
    int ages[] = {10 , 9 , 8 , 67 ,56};
    
    change(ages);
    test();
    return 0;
}

//利用一个指针来接受一个数组,指针变量array指向了数组的首元素

void change(int *array)
{
    printf("%d\n",array[2]);
    //printf("%d\n",*(array + 2));
}


 void test()
 {
     double d = 10.8;
     double *dp;
     dp = &d;
     
     printf("dp = %p\n",dp);
     printf("dp + 1 = %p\n",dp + 1);//这里dp + 1表示地址指向下一位
     
     int ages[] = {10 , 9 , 8 , 67 ,56};
     
     int *p;
     //指针变量p指向数组首元素
     p = &ages[0];
     //数组名就是数组的地址,也是数组首元素的地址
     //p = ages;
     
     /*
     p --->&ages[0]
     p + 1 --->&ages[1]
     p + 2 --->&ages[2]
     p + i --->&ages[i]
     */

    printf("%d\n",*(p+2));

    printf("%d\n",p[2]);

    /*
     for (int  i = 0; i < 5; i++) {
     printf("ages[%d] = %d\n",i ,ages[i]);
     }*/
}

2>指针遍历数组示意图



8.指针与字符串

#include <stdio.h>
/*
 1.常量区
 存放一些常量字符串,这里的字符串一般不能修改
 
 2.堆
 对象
 
 3.栈
 存放局部变量
 */

/*
 1>利用数组
 char name[] = "itcase";
 *特点:字符串里面的字符是可以修改的
 *使用场合:字符串的内容需要经常修改
 
 2>利用指针
 char *name = "itcase";
 *特点:字符串其实是一个常量字符串,里面的字符是不嫩修改
 *使用场合:字符串的内容不需要修改,而且这个字符串经常使用
 */

int main(int argc, const char * argv[])
{
    char name[20];
    
    printf("请输入名字:\n");
    
    scanf("%s",name);
    
    printf("刚才输入的字符串是:%s\n",name);
    return 0;
}

//定义字符串数组
void test2()
{
    char *name = "jack";
    
    //int ages[5];
    
    //指针数组(字符串数组)
    char *names[5] = {"jack","rose","jake"};
    
    //二维字符数组(字符串数组)
    char names2[2][10] = {"jack","rose"};

}


//定义字符串
void test()
{
    
    //字符串变量
    char name[] = "it";
    
    name[0] = 'T';
    
    printf("%s\n",name);
    
    //"it" == 'i' + 't' + '\0'
    //指针变量name2指向了字符串的首字符
    //字符串常量
    char *name2 = "it";
    
    char *name3 = "it";
    
    //    *name2 = 'T';
    
    //printf(%c\n,*name2);
    printf("%s\n",name2);

}

9.返回指针的函数

/*
 只要求看懂
 */

#include <stdio.h>

char *test();

int main(int argc, const char * argv[])
{

    char *name = test();
    printf("name = %s\n",name);
    return 0;
}

char *test()
{
    return "rose";
}

10.指向函数的指针

#include <stdio.h>

/*
 掌握:
 1.看懂语法
 2.定义指向函数的指针
    double (*p)(double , char *,int);
    p = haha;
    或者
    double (*p)(double ,char *,int) = haha;
 3.如何间接调用函数
 1>p(10.7 , "jack",10)
 2>(*P)(10.7 , "jack",10);
 */

void test()
{
    printf("调用了test函数\n");
}

int sum(int a ,int b)
{
    return a + b;
}
int main(int argc, const char * argv[])
{
    //定义指针变量指向sum函数
    //左边的int:指针变量p指向的函数返回int类型的数据
    //右边的(int ,int):指针变量p指向的函数有2个int类型的形参
    int (*p)(int ,int);
    
    p = sum;
    
    //int c = p(10 ,11);
    
    int c = (*p)(10 ,11);
    
    printf("c is %d\n",c);
    
    return 0;
}

void test1()
{
    //(*p)是固定写法,代表指针变量p指向的函数没有返回值
    //左边的void:指向变量p指向的函数没有返回值
    //右边的():指针变量p指向的函数没有形参
    void (*p)();
    
    //指针变量p指向了test函数
    p = test;
    
    p();
    //(*p)();//利用指针变量间接调用函数
    
    //test();//直接调用函数
}

恩,今天学的比较多,需要好好消化

---------------------- <a href="http://edu.csdn.net"target="blank">ASP.Net+Unity开发</a>、<a href="http://edu.csdn.net"target="blank">.Net培训</a>、期待与您交流! ----------------------


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
在信号处理领域,DOA(Direction of Arrival)估计是一项关键技术,主要用于确定多个信号源到达接收阵列的方向。本文将详细探讨三种ESPRIT(Estimation of Signal Parameters via Rotational Invariance Techniques)算法在DOA估计中的实现,以及它们在MATLAB环境中的具体应用。 ESPRIT算法是由Paul Kailath等人于1986年提出的,其核心思想是利用阵列数据的旋转不变性来估计信号源的角度。这种算法相比传统的 MUSIC(Multiple Signal Classification)算法具有较低的计算复杂度,且无需进行特征值分解,因此在实际应用中颇具优势。 1. 普通ESPRIT算法 普通ESPRIT算法分为两个主要步骤:构造等效旋转不变系统和估计角度。通过空间平移(如延时)构建两个子阵列,使得它们之间的关系具有旋转不变性。然后,通过对子阵列数据进行最小二乘拟合,可以得到信号源的角频率估计,进一步转换为DOA估计。 2. 常规ESPRIT算法实现 在描述中提到的`common_esprit_method1.m`和`common_esprit_method2.m`是两种不同的普通ESPRIT算法实现。它们可能在实现细节上略有差异,比如选择子阵列的方式、参数估计的策略等。MATLAB代码通常会包含预处理步骤(如数据归一化)、子阵列构造、旋转不变性矩阵的建立、最小二乘估计等部分。通过运行这两个文件,可以比较它们在估计精度和计算效率上的异同。 3. TLS_ESPRIT算法 TLS(Total Least Squares)ESPRIT是对普通ESPRIT的优化,它考虑了数据噪声的影响,提高了估计的稳健性。在TLS_ESPRIT算法中,不假设数据噪声是高斯白噪声,而是采用总最小二乘准则来拟合数据。这使得算法在噪声环境下表现更优。`TLS_esprit.m`文件应该包含了TLS_ESPRIT算法的完整实现,包括TLS估计的步骤和旋转不变性矩阵的改进处理。 在实际应用中,选择合适的ESPRIT变体取决于系统条件,例如噪声水平、信号质量以及计算资源。通过MATLAB实现,研究者和工程师可以方便地比较不同算法的效果,并根据需要进行调整和优化。同时,这些代码也为教学和学习DOA估计提供了一个直观的平台,有助于深入理解ESPRIT算法的工作原理。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值