写作日期:2016.08.31

修改日期:2016.09.01 、2016.09.02。

交流qq:992591601

用了几天时间复习了下C语言。对于C语言的字符串操作有些不习惯,于是作为练习,写下了下面这样错误的程序:

  1. #include <stdio.h>
  2. #define MAX_STR_SIZE 100
  3. void copy_string(char* from, char* to) {
  4. while (*to++ = *from++);
  5. }
  6. void swap_strs(char* str1, char* str2) {
  7. char tmp[MAX_STR_SIZE];
  8. copy_string(str1, tmp);
  9. copy_string(str2, str1);
  10. copy_string(tmp, str2);
  11. }
  12. void sort_strs_by_ascii(char* arr[3]) {
  13. if (strcmp(arr[0], arr[1]) < 0)
  14. swap_strs(arr[0], arr[1]);
  15. if (strcmp(arr[1], arr[2]) < 0)
  16. swap_strs(arr[1], arr[2]);
  17. if (strcmp(arr[0], arr[1]) < 0)
  18. swap_strs(arr[0], arr[1]);
  19. }
  20. int main() {
  21. char* arr[3] = {"dd", "aa", "cc"};
  22. sort_strs_by_ascii(arr);
  23. for (int i = 0; i < 3; i++)
  24. printf("%s\n", arr[i]);
  25. return 0;
  26. }

这段程序写得当然不怎么样,主要是为了练习C语言,特意去使用一些东西,例如C字符串指针的,指针数组。

程序中的数组的中存放三个字符串指针。将该数组作为参数来通过sort_strs_by_ascii方法排序。但在字符串操作过程中报错。

之后我才了解,char* arr这样的字符串指针,指向的值是存放在常量区的,不可改写。但该指针可以随意指向其它的地址空间。

而char arr[]这样的数组指针虽然本质也是指针,指针指向的内容却是固定在数组的内存空间的。但该数组空间里的内容是可以改写的。

接下来,我也大言不惭地用反汇编技术来解释下char* arr和char arr[]的区别。

截图部分第一个白色框是char arr[]初始化对应的汇编语句,可以清晰看到其过程。首先字符串本身是在静态区。白框的语句是三个赋值过程,将静态区0x00D95858地址的内容赋给arr数组地址。所以并不是仅仅让arr指针指向0x00D95858。而是实实在在地将该地址的内容赋过来。因为字符串比较短,所以编译器编译的汇编语言是三个赋值语句,如果是很长的字符串,这个过程一定是循环。

第二个白框是,char* arr的过程,很简单,就是指向静态区对应的字符串地址就好了。

所以可以知道,不管哪种方式,xxx = "abcd",便意味着字符串赋值操作,C语言就会首先在静态区分配内存存储该字符串。接下来,采用char arr[] 或char* arr,则各有各的方式。

为了解决上面那个程序,使用了C语言的二级指针。

基本思路就是:

先建立用指针数组,里面每一个指针指向一个字符串数组。再使用二级指针来指向这个指针数组。

这样就构造了一种自制的“二维数组”。达到了我程序想达到的效果。当然这程序只是为了练习,不值一提~

  1. ##include <stdio.h>
  2. #define MAX_STR_SIZE 100
  3. void copy_string(char* from, char* to) {
  4. while (*to++ = *from++);
  5. }
  6. void swap_strs(char* str1, char* str2) {
  7. char tmp[MAX_STR_SIZE];
  8. copy_string(str1, tmp);
  9. copy_string(str2, str1);
  10. copy_string(tmp, str2);
  11. }
  12. void sort_strs_by_ascii(char **p) {
  13. if (strcmp(*p, *(p + 1)) < 0)
  14. swap_strs(*p, *(p + 1));
  15. if (strcmp(*(p + 1), *(p + 2)) < 0)
  16. swap_strs(*(p + 1), *(p + 2));
  17. if (strcmp(*p, *(p + 1)) < 0)
  18. swap_strs(*p, *(p + 1));
  19. }
  20. int main() {
  21. char arr0[] = "aaaaaa";
  22. char arr1[] = "cccccc";
  23. char arr2[] = "bbbbbb";
  24. char* p0 = arr0;
  25. char* p1 = arr1;
  26. char* p2 = arr2;
  27. char* final_arr[3];
  28. final_arr[0] = p0;
  29. final_arr[1] = p1;
  30. final_arr[2] = p2;
  31. char **p3 = final_arr;
  32. sort_strs_by_ascii(p3);
  33. for (int i = 0; i < 3; i++) {
  34. printf("%s\n", final_arr[i]);
  35. }
  36. return 0;
  37. }

C/C++ char* arr与char arr[]的区别(反汇编解析)的更多相关文章

  1. char* strcpy( char* dest, const char* src ), int binary_search(int *arr, int key, int n), 可能的实现

    #include <stdio.h> char* stringCopy( char* dest, const char* src ) { size_t i = 0; while (dest ...

  2. char[]数组与char *指针的区别

    char[]数组与char *指针的区别 问题描述 虽然很久之前有看过关于char指针和char数组的区别,但是当时没有系统的整理,到现在频繁遇到,在string,char[], char *中迷失了 ...

  3. no suitable ctr exists to convert from 'int' to 'std::basic_string<char,std::char_traits<char>,std::allocator<char> >

    int xfun(int *a,int n) { int x = *a;//a的类型是int *,a+1跳动一个int的长度 ; pa < a + n; pa++)//指向同一个类型的指针比较大 ...

  4. C语言执行时报错“表达式必须是可修改的左值,无法从“const char [3]”转换为“char [120]” ”,原因:字符串不能直接赋值

    解决该问题的方法:使用strcpy函数进行字符串拷贝   原型声明:char *strcpy(char* dest, const char *src); 头文件:#include <string ...

  5. 【转】深入理解const char*p,char const*p,char *const p,const char **p,char const**p,char *const*p,char**const p

    一.可能的组合: (1)const char*p (2)char const*p (3)char *const p(4)const char **p (5)char const**p (6)char ...

  6. 初始化char指针--赋值和strcpy() 本质区别【转】

    原文地址:http://hi.baidu.com/todaygoodhj/item/0500b341bf2832e3bdf45180 使用常量字符串初始化char指针,或者使用strcpy复制,从语法 ...

  7. char *p 与char p[] 比较

    看看下面的程序的输出: #include <stdio.h>char *returnStr(){    char *p="hello world!";    retur ...

  8. char str[]和char *str的区别

    1.http://blog.csdn.net/szchtx/article/details/10396149 char ss[]="C++";  ss[0]='c';        ...

  9. char *c和char c[]区别

    char *c和char c[]区别 问题引入:在实习过程中发现了一个以前一直默认的错误,同样char *c = "abc"和char c[]="abc",前者 ...

随机推荐

  1. 在rails 4 中 使用 CSV 组件来 把csv文件导入到数据库

    class HardWorker include Sidekiq::Worker require 'CSV' def perform(file_path) csv_text = File.read(f ...

  2. 验证radio 是否被选中

    var radioType=document.getElementsByName("radioType");    var isCheckRadio=false;    for(v ...

  3. ES6详解

    1.ES6新增了let命令,用来声明变量.它的用法类似于var,但是所声明的变量,只在let命令所在的代码块内有效. const声明常亮,不可改变 2.变量的解构赋值 (1)数组的解构赋值: 以前,为 ...

  4. 高性能 CSS3 动画

    注:本文出自腾讯AlloyTeam的元彦,文章也可以在github上浏览.请尊重版权,转载请注明来源,多谢-- 高性能移动Web相较PC的场景需要考虑的因素也相对更多更复杂,我们总结为以下几点: 流量 ...

  5. 子进程 已安装 pre-removal 脚本 返回了错误号 1或2 与 子进程 已安装 post-installation 脚本 返回了错误号 1或2

    今天在ubuntu kylin上安装了virtualbox, 后来我想删除了再装个新一点的,结果正常的情况下删除不了,我就把找到的virtualbox的目录全部都删除了, 再通过apt-get rem ...

  6. 安卓奇葩问题之:运行OK,打包安装崩溃(原因是:代码不规范导致编译出错)

    咳咳,还是那句话,真是日了狗了 这个问题真的很难找,废话不多少,上酸菜. 报错信息是这个方法返回的图片找不到 public static int getImgID(boolean isBig, int ...

  7. 【安装mysql数据库】

    方法/步骤   请注意上图中选择Custom选项,这样才能修改安装目录.   请注意为了数据安全,不要把mysql安装在系统盘,如C:盘. 可以在其他盘符下,新建两个文件夹,一个存储mysql的文件, ...

  8. I2C VHDL程序

    http://blog.sina.com.cn/s/blog_9bd80b7601012o9y.html library ieee ; use ieee.std_logic_1164.all ; us ...

  9. 学习ES6--data1

    在ES6之前,ES5没有块级作用域,没有继承,只有函数作用域,这些导致ES5会变量提升,和函数提升,例(如有错误,请指正): function test() { var name = 'test' t ...

  10. 自动挂载文件/etc/fstab功能详解

    今天看了这篇文章,对于自动挂载中的一些小细节和参数有了更深的理解,所以这次把它摘下来,留做查询 一./etc/fstab文件的作用 1.我们把磁盘手动挂载之后如果不把它写入/etc/fstab这个文件 ...