sincomaster 发表于 2018-8-27 17:18:09

wrdt24435 发表于 2018-8-27 13:32
看了各位回复,首先u32型指针地址指的是4个地址的值意思吧?比如地址0x0000到0x0003的值是1,2,3,4,u32型 ...

如我上图所示给楼主说下吧!
首先你第一段话就是错的:(括号这段)
(看了各位回复,首先u32型指针地址指的是4个地址的值意思吧?比如地址0x0000到0x0003的值是1,2,3,4,u32型指针能指向0x01020304的值)
你说U32指针能指向0x01,0x02,0x03,0x04,步进是1,这只能是char *p指针才是这样.因为char 是1个字节,

u32 *p的意思是:
声明一个u32类型的指针,指针指向的数据是u32类型,所以u32类型数据占4个字节(要注意不同的系统可能不一样)

我的第11行代码:
arr的地址就是arr的地址,也就是0x001FFAA8
arr地址是0x001FFAAC

注意parr这个(sizeof parr)也就是说指针变量本身占4个字节,(比如你的指针类型是占8个字节但指针变量本身还是4个字节,因为指针变量内存得是地址,不用8个字节这么大去存地址,除非地址很长//这句话你要好好理解一下,)

然后你看到没,&(*parr++)读出来的地址,0x001FFAA8(arr的地址) 到0x001FFAAC(arr的地址)指针加1就是跳转4个字节地址,

你的第一个问题:(1. 那要怎么指呢?也就是u32 *p=什么?是0x0000吗?)
这个就看函数调用了,像我的long *parr,我传的是(第20行代码)数组arr的首地址,所以long *parr = arr =arr= 1,但我32行代码用的是&(*parr++),用了%p来输出地址,如果是%d就输出值1,去掉&,

你的第二个问题:(其次也就是说数组a其实是指针地址,而a则是一个变量,那么比如我想往void fn(u32 *a)这个函数输入a,是(u32 *)&a这样输入吗?)
你要读a,正确的做法是*a+2(就不能使用*a++),你这种写法有点看不懂((u32*)&a)

你的第三个问题:
如果前面用了const修饰,那么后面的函数调用也用上吧,报错应该不至于吧,警告就会有,

tanic 发表于 2018-8-27 17:24:53

1.u32 *p=?
这里?建议是指向变量地址
如 uint32_t a;
    uint32_t *p=a;
,不建议直接写地址如 0x20000000这种,因为ARM是精简指令集集必须寻址必须对齐,有的ram也只能对其访问
2.是的
3.类型确实不一样,const修饰的是常量不可修改 没有const是变量可修改,强制转换不建议做,因为const修饰的应该不在ram中

stm1024 发表于 2018-8-27 17:46:01

本帖最后由 stm1024 于 2018-8-27 18:23 编辑

我的C也学得很一般,针对你的问题,我还是一点点用例子来说明吧。我要说的都是老生常谈,基本上都是入门级的问题。
没什么技术含量,如果讲的不好甚至不对的地方,欢迎大家比较客气的批评指正。
1. 指针的自增
入门问题:指针的申明,到底是用
Type *x;
还是
Type* x;
答案是都可以,不过我个人更喜欢第二种。
void f1(uint32_t* a)
{
    printf("Test For uint32_t\r\n");
    do
    {
      printf("0x%08x\r\n",a);
      a++;
    }while(*a);
}

void f2(uint8_t* a)
{
    printf("Test For uint8_t\r\n");
    do
    {
      printf("0x%08x\r\n",a);
      a++;
    }while(*a);
}

//测试一下这两段代码:
    uint32_t a[]={7,6,5,4,3,2,1,0};
    uint8_t b[]={7,6,5,4,3,2,1,0};
    f1(a);
    f2(b);运行的结果是:


f1和f2中同样都是a++,但是递增的效果并不一样,因为形参的类型分别是uint32_t*和uint8_t*的,所以指针的值,其实就是指向的对应数据类型的首地址,类型告诉了编译器该如何使用这个地址。




2.指针类型的转换
为了说明问题,我再写一个函数:
void f3(uint8_t* a,uint8_t n)
{
    uint8_t i;
    for(i=0;i<n;i++)
      printf("%d\r\n",*(a+i));
}然后代码是:
f1(a);
    f2((uint8_t *)a);
    f3(a,32);运行效果呢?

可以看到,即使f2调用的时候做了强制类型转换,但是f2((uint8_t *)a);输出的第一个地址和f1(a)中的是一样的。
不过为什么第二函数只输入了一个值呢?因为在内存布局中,a数组的组织方式是07 00 00 00...

当到了第二个字节的时候,变成00,也就是'\0',函数提前退出了。
f3则直接打印32个字节的值,也有助于验证这个情况。
所以,要往哪个函数里面输入什么,取决于你要如何理解那一块内存区域,任何可访问的内存区域都是可以提供给这个函数的。
这个函数的意思是说,不管你那块内存区域是啥,我拿到内存首地址后,就按uint32_t,每四个字节作为一个单位来处理数据。
还有需要说明的是,有些控制器会有内存对齐的要求。


此外,对于一些内存操作的函数,如memcpy (void*, const void*, size_t);第一个数据类型是void*的指针类型。




stm1024 发表于 2018-8-27 18:15:31

3. const指针和一般指针
    char a='x';
    const char* p=&a;
    *p='y';

这段代码是通过不了编译的,因为你的p是常常量指针,特点是,你可以修改指针指向的内存地址,但是不能修改指向地址的内容。
不过还是可以通过a来修改这个值。像string头文件中,很多函数,source char 都被定义为const char*,就是怕调用者瞎搞,把原始内容都给你破坏了。
和这个相反的还有char* const,指针常量,这个所指向的地址不能变,但是可以修改其中的内容。
还有常量指针常量const char* const类型,都不能改变……

页: 1 [2]
查看完整版本: vodi 函数(u32 *a)里的*a是要往函数输入什么?