C语言这种单细胞编程语言和指针的一些理解
作者:互联网
转行做嵌入式也有一段时间了,原来做c#以及一些其它的上层语言, 本想的是也就是仅仅是语法上有点不一样。但是实际使用的切身体会真的是只有自己才知道。很多方面刷新了我对c语言以及计算机结构体系的认知 ,绝对不仅仅是语法不一样那么简单。
关于字符串传递函数引起的
一切源于给函数传递字符串变量这种 原来在其它高级语言地方写的 再常见不过的功能。
1 void changeStr(char * ch) 2 { 3 *(ch + 1) = 'a'; 4 } 5 6 //char * cstr = "hello";//报错 7 char cstr[] = "hello";//这种可以 8 //数组也是传的引用函数里面更改的是此处数组的内容这个不用多说 9 changeStr(cstr); 10 printf(cstr);
当然对于这个问题的bug 你百度一下就会有很多帖子 ,基本上呢也会给你讲的大概差不多。如果非要死记硬背的话这种代码:
1 char * ch="hello";
他是以常量的形式存在于环境中的。具体的请看:
https://www.qb5200.com/article/405141.html
https://blog.csdn.net/u013066730/article/details/84231452
https://blog.csdn.net/silently_frog/article/details/96607516
总而言之 char * ch=“hello” 然后再去更改ch里的元素 是一个陷阱,至于这个"hello" 的地址大意估计是由编译器更底层的控制的我们不用管。
又啰嗦一遍 内存地址和数据
归根结底还是 指针的问题。内存地址 值 ,学了单片机后深深的认识到这 其实这就是计算机 汇编 ,还有编程的本质,本质就是内存管理 ,到处的计算机书 操作系统 或者其它方面讲的也都是这个,内存数据处理。单片机入门就是地址上的内存数据处理。c语言中处理字符串总是会遇到各种各样的问题也是因为没理解透。
还是返回c语言字符串的议题上来吧
c语言字符串的本质:需要一段连续地址的值 以\0结尾。处理的时候不要超出这个概念。以前在技术群里讨论也模糊的记得 有这个说法 ,上面的"hello"编译后是作为静态字符串存储的,在各处如果写的一模一样的"hello"那么他们在内存里本身就是同一个东西, "hello" 这种以引号引起来的 表示方式 它本质就代表了一个地址标识。另外一个"hello" 这种形式的写法编译器末尾会自动给带一个\0结尾 来确定字符串结束, 这个你是看不见 但他是存在的。再贴一遍字符串的代码:
1 char * str2 = "hello";
一些坑以及产生的原因(指针与分配确切空间):
而c语言指针不允许你指针随便指向一个未初始化的 地址,并不允许你一个指针随意指向一个地址 然后去修改 值 ,这是不被允许的 ,千言万语 归咎于此的根本原因。
1 char ch1 = 0x65; 2 char ch2 = 0x66; 3 char ch3 = 0x00; 4 5 char str1[] = "hello";//{ ch1, ch2, ch3 }这种写法意思是一样的 6 char * str2 = "hello"; 7 str1[1] = 'a'; 8 //*(str1 + 1) = 'a';数组指针式操作 老套路 9 10 //str2[1] = 'a';//报错 11 //*(str2 + 1) = 'a';//我们想当然的指针地址++ 进行操作是不行的 12 //str2 = &ch1;//这种是可以 但是指向单个字符地址 并不能形成连续的字符串 13 14 printf("%s--\r\n", str1); 15 printf("%s--\r\n", str2);//字符串参数给的是地址 16 printf("%c--\r\n", *str2);//注意字符参数给的是*p
这也是为什么数组字符串 能够 更改元素 (数组的内存空间是确切的),char* (内存空间不确切) ,所以不能随意更改。一切都归咎于内存管理, 使用内存时必须必须必须要固定的确切的 经过分配了的 确定的 空间。然后另一个 他们的这种指针的机制是相同的 所以 数组可以用 *p 的形式来访问。
1 int a = 44;
这个 a看似平平无奇 ,实际上这是一个内存空间确定的过程 , a代表了一个地址,编译过程只不过把这个过程变成了对应的汇编指令。
字符串不就是连续地址的值以\0结尾吗 ,于是乎有些大聪明就有了这种代码:
1 char ch1 = 'a'; 2 char * str1; 3 char * str2; 4 char * str3; 5 6 str1 = &ch1; 7 str2 = str1 + 1; 8 9 //这样更是错误,指针只能指向一个 给一个地址值 10 //char * str2 = { 'h', 'e', '\0' }; 11 12 //还想到 不是连续的指针 么 数组么 ,于是大聪明 这样 13 //又犯了迂回的错误 ,数组 里面 每一个元素都是指针 ,这其实是一个二维数组。 14 //char * str1[]
单片机中除了有定义的外设寄存器以外 ,普通区域 谁允许你擅自通过地址+1的方式 去访问未知的区域的。而单独一个char 一个char 的定义 变量又不可能 给你分配到连续的区域 让你char*去关联上,这是由于c语言本身的机制决定的 ,所以我们就不要去专这个牛角尖了。
也正是由于指针跟数组的相关性 ,指针跟数组有时候 实参 形参可以互相换,比如最开始的代码 形参定义的是指针 确可传数组,定义的是数组也可以传指针 都是可以的 是等价的 ,都相安无事 ,前提是你要自己眼睛看仔细了 传进去的是一个char * 的话 如果你函数内部 进行了元素更改的话 你就挂了。
因为这这些缺陷种种限制, 所以微量氧里到处都是用的数组 形式的字符串,数组就是一串连续确切空间地址的指针。
关于返回一个数组
当然 通过单片机函数不能返回数组 ,只可返回指针 ,返回一个指针么指向那里?函数大括号里的部分在函数运行结束就会被销毁,去哪里找 。
1 char * getChPointer() 2 { 3 //如果想使此函数起作用可以把cc定义成全局的 4 //static char cc = 'b'; 5 char cc = 'b'; 6 char * ch; 7 ch = &cc; 8 //其实c这种单细胞难用玩意儿,也没啥动态内存分配不动态内存分配 9 //单片机编程中根本就没用到动态内存也就是堆,管理太复杂了。 10 11 //到此方法体内所有的都是复制的 ,包括指针 则复制一模一样的指针 12 //每次调用方法都是独立副本运行,方法结束栈结束 所有内容销毁 13 14 //当栈结束时返回的是复制的跟ch一模一样的指针 都指向cc所以没区别 15 return ch; 16 } 17 char * ch = getChPointer(); 18 printf("dd\r\n"); 19 printf("%c", *ch);
c语言 真的非常非常的低能 单细胞动物 。深深的感受到c 语言为什么仅仅只是汇编的抽象 ,真是一种单细胞思考方式 ,因为真的是在是太低级了 ,跟其他什么Java相比真的是低一个级别的。诸多限制,更偏向于一种野人式的,要求你的功力要更高才能驾驭。也正是由于这种第一个级别 所有的这些不顺手都不得不逼着你去想 底层到底是怎么运作的。
标签:ch,编程语言,str2,C语言,char,数组,hello,指针 来源: https://www.cnblogs.com/assassinx/p/16580920.html